Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge: dev to prod #107

Merged
merged 7 commits into from
Oct 20, 2024
Merged
27 changes: 27 additions & 0 deletions components/Profile/Edit/ErrorMessage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { IoMdCloseCircleOutline } from 'react-icons/io';
import { Box, Typography } from '@mui/material';

const ErrorMessage = ({ errText }) => {
return (
errText && (
<Box
sx={{
mt: '8px',
display: 'flex',
alignItems: 'center',
gap: '8px',
color: '#EF5364',
bgcolor: '#FFEFF1',
borderRadius: '4px',
padding: '4px 8px',
fontSize: '14px',
}}
>
<IoMdCloseCircleOutline size={20} />
<Typography as="p">{errText}</Typography>
</Box>
)
);
};

export default ErrorMessage;
3 changes: 3 additions & 0 deletions components/Profile/Edit/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { MobileDatePicker } from '@mui/x-date-pickers/MobileDatePicker';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import InputTags from '../InputTags';
import ErrorMessage from './ErrorMessage';

import TheAvator from './TheAvator';
import FormInput from './EditFormInput';
Expand Down Expand Up @@ -167,6 +168,7 @@ function EditPage() {
</StyledSelectBox>
))}
</StyledSelectWrapper>
<ErrorMessage errText={errors.gender} />
</StyledGroup>
<StyledGroup>
<Typography fontWeight="500">身份 *</Typography>
Expand Down Expand Up @@ -194,6 +196,7 @@ function EditPage() {
</StyledSelectBox>
))}
</StyledSelectWrapper>
<ErrorMessage errText={errors.roleList} />
</StyledGroup>
</Box>
</StyledTitleWrap>
Expand Down
27 changes: 10 additions & 17 deletions components/Profile/Edit/useEditProfile.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,18 @@ const initialState = {
const buildValidator = (maxLength, regex, maxMsg, regMsg) =>
z.string().max(maxLength, maxMsg).regex(regex, regMsg).optional();

const tempSchema = Object.keys(initialState).reduce((acc, key) => {
return key !== 'birthDay'
? {
...acc,
[key]: z.string().optional(),
}
: acc;
}, {});

const schema = z.object({
...tempSchema,
name: z
.string()
.min(1, { message: '請輸入名字' })
.max(50, { message: '名字過長' })
.optional(),
gender: z
.string()
.refine((val) => val !== undefined && val !== '', {
message: '請選擇您的性別',
})
.optional(),
birthDay: z
.any()
.refine((date) => dayjs(date).isValid(), {
Expand All @@ -56,8 +52,6 @@ const schema = z.object({
message: '您的年齡未滿16歲,目前無法於平台註冊,請詳閱島島社群條款',
})
.optional(),
isOpenLocation: z.boolean().optional(),
isOpenProfile: z.boolean().optional(),
instagram: buildValidator(
30,
/^($|[a-zA-Z0-9_.]{2,20})$/,
Expand All @@ -82,10 +76,7 @@ const schema = z.object({
'長度最多20個字元',
'長度最少6個字元,支援英文、數字、底線、句號',
),
isLoadingSubmit: z.boolean().optional(),
tagList: z.array(z.string()).optional(),
wantToDoList: z.array(z.string()).optional(),
roleList: z.array(z.string()).optional(),
roleList: z.array(z.string()).min(1, '請選擇您的身份').optional(),
});

const userReducer = (state, payload) => {
Expand Down Expand Up @@ -136,7 +127,9 @@ const useEditProfile = () => {

const onChangeHandler = ({ key, value, isMultiple }) => {
stateDispatch({ key, value, isMultiple });
validate({ [key]: value }, true);
// if isMultiple is true, value must be in array , if not, create a new array then check
const checkVal = isMultiple && !Array.isArray(isMultiple) ? [value] : value;
validate({ [key]: checkVal }, true);
};

const onSubmit = async ({ id, email }) => {
Expand Down
2 changes: 2 additions & 0 deletions components/Terms/Ipr.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React from 'react';
import { TermsWrapper, PaperWrapper } from './Terms.styled';
import TermsMenu from './TermsMenu';

const Terms = () => {
return (
<TermsWrapper>
<TermsMenu />
<PaperWrapper>
<h2>島島阿學資源共享自主學習網站智慧財產權</h2>
<p>
Expand Down
4 changes: 2 additions & 2 deletions components/Terms/Privacypolicy.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';
import styled from '@emotion/styled';
import { Paper } from '@mui/material';
import { TermsWrapper, PaperWrapper } from './Terms.styled';
import TermsMenu from './TermsMenu';

const Terms = () => {
return (
<TermsWrapper>
<TermsMenu />
<PaperWrapper>
<h2>島島阿學資源共享自主學習網站隱私權政策</h2>
<p>
Expand Down
2 changes: 2 additions & 0 deletions components/Terms/Service.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React from 'react';
import { TermsWrapper, PaperWrapper } from './Terms.styled';
import TermsMenu from './TermsMenu';

const Terms = () => {
return (
<TermsWrapper>
<TermsMenu />
<PaperWrapper>
<h2>島島阿學資源共享自主學習網站使用者條款</h2>
<p>
Expand Down
6 changes: 5 additions & 1 deletion components/Terms/Terms.styled.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import { Paper } from '@mui/material';
export const TermsWrapper = styled.section`
padding-top: 40px;
padding-bottom: 40px;
position: relative;
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: center;
`;

export const PaperWrapper = styled(Paper)`
width: min(90%, 800px);
margin: 0 auto;
padding: 40px 20px;

@media (max-width: 767px) {
Expand Down
107 changes: 107 additions & 0 deletions components/Terms/TermsMenu.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import React from 'react';
import styled from '@emotion/styled';
import Link from 'next/link';
import { useRouter } from 'next/router';

const TermsMenuWrapper = styled.nav`
position: sticky;
top: 138px;
left: 0;
padding: 40px 0;
margin-right: 1em;
background-color: #fff;
width: 200px;
border-radius: 4px;
box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2),
0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);

@media (max-width: 1040px) {
display: none;
}

h2 {
margin-bottom: 1em;
padding: 0 1em;
font-weight: 500;
font-size: 18px;
}

ul {
list-style-type: none;
padding: 0;
margin: 0;
}

li {
margin-bottom: 10px;
}

a {
color: #16b9b3;
padding: 0 1em;

@media (hover: hover) {
&:hover {
text-decoration: underline;
text-underline-offset: 0.2em;
}
}
}

.current {
position: relative;

&:before {
content: '';
position: absolute;
left: 0em;
top: 50%;
transform: translateY(-50%);
width: 0;
height: 0;
border-top: 0.5em solid transparent;
border-bottom: 0.5em solid transparent;
border-left: 0.5em solid #16b9b3;
border-right: 0.5em solid transparent;
}
}
`;

const TermsMenu = () => {
const router = useRouter();
const currentPath = router.pathname;

return (
<TermsMenuWrapper>
<h2>網站規約</h2>
<ul>
<li>
<Link
href="/terms/privacypolicy"
className={currentPath === '/terms/privacypolicy' ? 'current' : ''}
>
隱私權政策
</Link>
</li>
<li>
<Link
href="/terms/ipr"
className={currentPath === '/terms/ipr' ? 'current' : ''}
>
智慧財產權
</Link>
</li>
<li>
<Link
href="/terms/service"
className={currentPath === '/terms/service' ? 'current' : ''}
>
使用者條款
</Link>
</li>
</ul>
</TermsMenuWrapper>
);
};

export default TermsMenu;
15 changes: 15 additions & 0 deletions layout/DefaultLayout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import Navigation from '@/shared/components/Navigation_v2';
import Footer from '@/shared/components/Footer_v2';

const DefaultLayout = ({ children }) => {
return (
<>
<Navigation />
{children}
<Footer />
</>
);
};

export default DefaultLayout;
Loading
Loading