diff --git a/components/Profile/Edit/ErrorMessage.jsx b/components/Profile/Edit/ErrorMessage.jsx new file mode 100644 index 00000000..5d979991 --- /dev/null +++ b/components/Profile/Edit/ErrorMessage.jsx @@ -0,0 +1,27 @@ +import { IoMdCloseCircleOutline } from 'react-icons/io'; +import { Box, Typography } from '@mui/material'; + +const ErrorMessage = ({ errText }) => { + return ( + errText && ( + + + {errText} + + ) + ); +}; + +export default ErrorMessage; diff --git a/components/Profile/Edit/index.jsx b/components/Profile/Edit/index.jsx index 9d4dd038..030c5a1c 100644 --- a/components/Profile/Edit/index.jsx +++ b/components/Profile/Edit/index.jsx @@ -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'; @@ -167,6 +168,7 @@ function EditPage() { ))} + 身份 * @@ -194,6 +196,7 @@ function EditPage() { ))} + diff --git a/components/Profile/Edit/useEditProfile.jsx b/components/Profile/Edit/useEditProfile.jsx index 70f88872..23485b50 100644 --- a/components/Profile/Edit/useEditProfile.jsx +++ b/components/Profile/Edit/useEditProfile.jsx @@ -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(), { @@ -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})$/, @@ -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) => { @@ -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 }) => { diff --git a/components/Terms/Ipr.jsx b/components/Terms/Ipr.jsx index 0421a68f..a8dae751 100644 --- a/components/Terms/Ipr.jsx +++ b/components/Terms/Ipr.jsx @@ -1,9 +1,11 @@ import React from 'react'; import { TermsWrapper, PaperWrapper } from './Terms.styled'; +import TermsMenu from './TermsMenu'; const Terms = () => { return ( +

島島阿學資源共享自主學習網站智慧財產權

diff --git a/components/Terms/Privacypolicy.jsx b/components/Terms/Privacypolicy.jsx index ab8df481..0148a4ec 100644 --- a/components/Terms/Privacypolicy.jsx +++ b/components/Terms/Privacypolicy.jsx @@ -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 ( +

島島阿學資源共享自主學習網站隱私權政策

diff --git a/components/Terms/Service.jsx b/components/Terms/Service.jsx index 303f9084..99d4e411 100644 --- a/components/Terms/Service.jsx +++ b/components/Terms/Service.jsx @@ -1,9 +1,11 @@ import React from 'react'; import { TermsWrapper, PaperWrapper } from './Terms.styled'; +import TermsMenu from './TermsMenu'; const Terms = () => { return ( +

島島阿學資源共享自主學習網站使用者條款

diff --git a/components/Terms/Terms.styled.jsx b/components/Terms/Terms.styled.jsx index 62238ea2..2dfc5f5b 100644 --- a/components/Terms/Terms.styled.jsx +++ b/components/Terms/Terms.styled.jsx @@ -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) { diff --git a/components/Terms/TermsMenu.jsx b/components/Terms/TermsMenu.jsx new file mode 100644 index 00000000..0b0254eb --- /dev/null +++ b/components/Terms/TermsMenu.jsx @@ -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 ( + +

網站規約

+
    +
  • + + 隱私權政策 + +
  • +
  • + + 智慧財產權 + +
  • +
  • + + 使用者條款 + +
  • +
+ + ); +}; + +export default TermsMenu; diff --git a/layout/DefaultLayout.jsx b/layout/DefaultLayout.jsx new file mode 100644 index 00000000..37894a47 --- /dev/null +++ b/layout/DefaultLayout.jsx @@ -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 ( + <> + + {children} +