Skip to content

Commit

Permalink
Merge pull request #170 from daodaoedu/dev
Browse files Browse the repository at this point in the history
 Merge to Prod
  • Loading branch information
vincentxuu authored Dec 16, 2024
2 parents 02de466 + 5d45e19 commit a7e5673
Show file tree
Hide file tree
Showing 132 changed files with 9,378 additions and 835 deletions.
11 changes: 10 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,22 @@ module.exports = {
settings: {
'import/resolver': {
alias: {
extensions: ['.js', '.jsx'],
extensions: ['.js', '.jsx', '.ts', '.tsx'],
map: [['@', '.']],
},
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx']
},
},
},
rules: {
"import/no-extraneous-dependencies": ["error", { devDependencies: ["./*.js"] }],
'import/extensions': ['error', 'ignorePackages', {
js: 'never',
jsx: 'never',
ts: 'never',
tsx: 'never',
}],
'react/no-unescaped-entities': 'off',
'@next/next/no-page-custom-font': 'off',
'react/prop-types': [0],
Expand Down
188 changes: 188 additions & 0 deletions components/Banner.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import styled from '@emotion/styled';
import Image from '@/shared/components/Image';
import { Box } from '@mui/material';

import LearningMarathonImgDesktopGroup from '@/public/assets/learning-marathon/2025S1-desktop-group.png';
import LearningMarathonImgDesktopIcon1 from '@/public/assets/learning-marathon/2025S1-desktop-icon-1.png';
import LearningMarathonImgDesktopIcon2 from '@/public/assets/learning-marathon/2025S1-desktop-icon-2.png';
import LearningMarathonImgDesktopIcon3 from '@/public/assets/learning-marathon/2025S1-desktop-icon-3.png';
import LearningMarathonImgDesktopIcon4 from '@/public/assets/learning-marathon/2025S1-desktop-icon-4.png';
import LearningMarathonImgDesktopIcon5 from '@/public/assets/learning-marathon/2025S1-desktop-icon-5.png';
import LearningMarathonImgDesktopIcon6 from '@/public/assets/learning-marathon/2025S1-desktop-icon-6.png';
import LearningMarathonImgDesktopGirl from '@/public/assets/learning-marathon/2025S1-desktop-girl-1.png';
import LearningMarathonImgDesktopBoy from '@/public/assets/learning-marathon/2025S1-desktop-boy-1.png';
import LearningMarathonImgDesktopBg from '@/public/assets/learning-marathon/2025S1-desktop-bg.png';
import LearningMarathonImgMobile from '@/public/assets/learning-marathon/[email protected]';

import { cn } from '@/utils/cn';

const StyledBanner = styled(Box)`
width: 100%;
height: calc(100vw / 1.6);
position: relative;
box-sizing: border-size;
overflow: hidden;
@media (max-width: 767px) {
height: calc(100vw / 0.6428);
}
`;

const Banner = ({ children }) => {
return (
<StyledBanner>
<div className="hidden md:block">
<div className="absolute inset-0">
<Image
src={LearningMarathonImgDesktopBg.src}
alt="島島盃 - 學習馬拉松 2025 春季賽"
height="inherit"
background="linear-gradient(#fcfefe 10%, #e0f1f2 40%)"
borderRadius="0"
/>
</div>
<div
className={cn(
"absolute bottom-0 left-1/2 -translate-x-1/2 w-[30%] aspect-[433/427]",
"opacity-0 animate-fade-in animate-duration-700 animate-delay-200",
)}
>
<Image
src={LearningMarathonImgDesktopGroup.src}
alt="揪團"
height="inherit"
borderRadius="0"
/>
</div>
<div
className={cn(
"absolute top-[39%] -left-[2.8%] w-[18%] aspect-[271/404]",
"-translate-x-full animate-slide-x-in animate-distance-from-left animate-duration-1100 animate-delay-500",
)}
>
<Image
src={LearningMarathonImgDesktopBoy.src}
alt="男角色"
height="inherit"
borderRadius="0"
/>
</div>
<div
className={cn(
"absolute top-[33%] -right-[1.6%] w-[18%] aspect-[256/351]",
"translate-x-full animate-slide-x-in animate-distance-from-right animate-duration-1100 animate-delay-1100",
)}
>
<Image
src={LearningMarathonImgDesktopGirl.src}
alt="女角色"
height="inherit"
borderRadius="0"
/>
</div>
<div
className={cn(
"absolute top-[14%] left-[27.5%] w-[5%] aspect-[75/77]",
"opacity-0 animate-fade-in animate-duration-500 animate-delay-200",
)}
>
<div className="animate-oscillate animate-delay-200">
<Image
src={LearningMarathonImgDesktopIcon5.src}
alt="icon5"
height="inherit"
borderRadius="0"
/>
</div>
</div>
<div
className={cn(
"absolute top-[19.5%] left-[21%] w-[6%] aspect-[91/131]",
"opacity-0 animate-fade-in animate-duration-500 animate-delay-1700",
)}
>
<div className="animate-oscillate animate-delay-1700">
<Image
src={LearningMarathonImgDesktopIcon3.src}
alt="icon3"
height="inherit"
borderRadius="0"
/>
</div>
</div>
<div
className={cn(
"absolute top-[45.5%] left-[27.5%] w-[4.8%] aspect-[70/39]",
"opacity-0 animate-fade-in animate-duration-500 animate-delay-500",
)}
>
<div className="animate-oscillate animate-delay-1100">
<Image
src={LearningMarathonImgDesktopIcon1.src}
alt="icon1"
height="inherit"
borderRadius="0"
/>
</div>
</div>
<div
className={cn(
"absolute top-[16.5%] right-[24.5%] w-[4.7%] aspect-[68/112]",
"opacity-0 animate-fade-in animate-duration-500 animate-delay-1300",
)}
>
<div className="animate-oscillate animate-delay-1900">
<Image
src={LearningMarathonImgDesktopIcon4.src}
alt="icon4"
height="inherit"
borderRadius="0"
/>
</div>
</div>
<div
className={cn(
"absolute top-[29%] right-[18.5%] w-[5.9%] aspect-[85/72]",
"opacity-0 animate-fade-in animate-duration-500 animate-delay-500",
)}
>
<div className="animate-oscillate animate-delay-300">
<Image
src={LearningMarathonImgDesktopIcon2.src}
alt="icon2"
height="inherit"
borderRadius="0"
/>
</div>
</div>
<div
className={cn(
"absolute top-[40%] right-[20.5%] w-[11%] aspect-[160/153]",
"opacity-0 animate-fade-in animate-duration-500 animate-delay-1900",
)}
>
<div className="animate-oscillate animate-delay-1300">
<Image
src={LearningMarathonImgDesktopIcon6.src}
alt="icon6"
height="inherit"
borderRadius="0"
/>
</div>
</div>
</div>
<div className="md:hidden">
<Image
src={LearningMarathonImgMobile.src}
alt="島島盃 - 學習馬拉松 2025 春季賽"
height="inherit"
background="linear-gradient(#fcfefe 10%, #e0f1f2 40%)"
borderRadius="0"
/>
</div>
{children}
</StyledBanner>
);
};

export default Banner;
9 changes: 7 additions & 2 deletions components/Group/Form/Form.styled.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@ export const StyledDescription = styled.p`

export const StyledContainer = styled.main`
position: relative;
display: flex;
align-items: center;
flex-direction: column;
background: #f3fcfc;
padding: 60px 0;
min-height: 100vh;
margin: 0 auto;
width: 720px;
.MuiInputBase-input,
.MuiFormControlLabel-label {
Expand All @@ -30,7 +35,6 @@ export const StyledContainer = styled.main`
@media (max-width: 760px) {
padding: 20px;
width: 100%;
}
`;

Expand Down Expand Up @@ -58,6 +62,7 @@ export const StyledGroup = styled.div`
export const StyledFooter = styled.div`
display: flex;
justify-content: center;
width: 100%;
`;

export const StyledChip = styled(Chip)`
Expand Down
18 changes: 7 additions & 11 deletions components/Group/Form/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Button from '@/shared/components/Button';
import Checkbox from '@mui/material/Checkbox';
import FormControlLabel from '@mui/material/FormControlLabel';
import { activityCategoryList } from '@/constants/activityCategory';
import { ProtectedComponent } from '@/contexts/Auth';
import StyledPaper from '../Paper.styled';
import {
StyledHeading,
Expand Down Expand Up @@ -40,7 +41,6 @@ export default function GroupForm({
onSubmit,
}) {
const {
notLogin,
control,
values,
errors,
Expand All @@ -66,14 +66,10 @@ export default function GroupForm({
<Checkbox size="small" onClick={() => setIsChecked((pre) => !pre)} />
);

if (notLogin) {
return <Box sx={{ minHeight: '50vh' }} />;
}

return (
<Box sx={{ background: '#f3fcfc', py: '60px' }}>
<ProtectedComponent>
<StyledContainer>
<StyledPaper sx={{ p: '40px', mb: '16px' }}>
<StyledPaper className="p-10 mb-4 md:w-[720px]">
<StyledHeading>
{isCreateMode ? '發起揪團' : '編輯揪團'}
</StyledHeading>
Expand Down Expand Up @@ -149,7 +145,7 @@ export default function GroupForm({
placeholder="希望在什麼時間舉行?"
/>
</StyledPaper>
<StyledPaper sx={{ p: '40px', mb: '16px' }}>
<StyledPaper className="p-10 mb-4 md:w-[720px]">
<Fields.TextField
label="想找的夥伴"
name="partnerStyle"
Expand Down Expand Up @@ -219,7 +215,7 @@ export default function GroupForm({
helperText="標籤填寫完成後,會用 Hashtag 的形式呈現,例如: #一起學日文"
/>
</StyledPaper>
<StyledPaper>
<StyledPaper className="md:w-[720px]">
<Fields.DateRadio
label="揪團期限"
name="deadline"
Expand All @@ -230,7 +226,7 @@ export default function GroupForm({
/>
</StyledPaper>
{!isCreateMode && (
<StyledPaper sx={{ p: '40px', mt: '16px' }}>
<StyledPaper className="p-10 mb-4 md:w-[720px]">
<StyledSwitchWrapper>
{values.isGrouping ? '開放揪團中' : '已關閉揪團'}
<Switch
Expand Down Expand Up @@ -277,6 +273,6 @@ export default function GroupForm({
</Button>
</StyledFooter>
</StyledContainer>
</Box>
</ProtectedComponent>
);
}
25 changes: 6 additions & 19 deletions components/Group/Form/useGroupForm.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import dayjs from 'dayjs';
import { useEffect, useRef, useState } from 'react';
import { useSelector } from 'react-redux';
import { useRef, useState } from 'react';
import { ZodType, z } from 'zod';
import { useSnackbar } from '@/contexts/Snackbar';
import { CATEGORIES } from '@/constants/category';
import { AREAS } from '@/constants/areas';
import { EDUCATION_STEP } from '@/constants/member';
import { BASE_URL } from '@/constants/common';
import openLoginWindow from '@/utils/openLoginWindow';
import { activityCategoryList } from '@/constants/activityCategory';
import useLeaveConfirm from '@/hooks/useLeaveConfirm';
import { useAuth } from '@/contexts/Auth';

const _eduOptions = EDUCATION_STEP.filter(
(edu) => !['master', 'doctor', 'other'].includes(edu.value),
Expand Down Expand Up @@ -84,9 +83,8 @@ const rules = {
};

export default function useGroupForm(defaultValue) {
const { user, token } = useAuth();
const [isDirty, setIsDirty] = useState(false);
const me = useSelector((state) => state.user);
const notLogin = !me?._id;
const [values, setValues] = useState(() => ({
...INITIAL_VALUES,
...defaultValue,
Expand All @@ -96,7 +94,7 @@ export default function useGroupForm(defaultValue) {
rule.safeParse(defaultValue[key])?.data ?? INITIAL_VALUES[key],
])
),
userId: me?._id,
userId: user?._id,
}));
const [errors, setErrors] = useState({});
const { pushSnackbar } = useSnackbar();
Expand Down Expand Up @@ -136,7 +134,7 @@ export default function useGroupForm(defaultValue) {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${me.token}`,
Authorization: `Bearer ${token}`,
},
});
};
Expand All @@ -154,7 +152,7 @@ export default function useGroupForm(defaultValue) {
const response = await fetch(`${BASE_URL}/image`, {
method: 'POST',
headers: {
Authorization: `Bearer ${me.token}`,
Authorization: `Bearer ${token}`,
},
body: formData,
});
Expand Down Expand Up @@ -211,20 +209,9 @@ export default function useGroupForm(defaultValue) {
onValid({ ...result.data, photoURL });
};

useEffect(() => {
let timer;
if (notLogin) {
timer = setTimeout(() => {
openLoginWindow();
}, 100);
}
return () => clearTimeout(timer);
}, [notLogin]);

useLeaveConfirm({ shouldConfirm: isDirty });

return {
notLogin,
control,
errors,
values,
Expand Down
Loading

0 comments on commit a7e5673

Please sign in to comment.