From aa524165731d0242b133b1fdaff3d841f33a4497 Mon Sep 17 00:00:00 2001 From: matushl Date: Fri, 10 Nov 2023 23:58:36 +0100 Subject: [PATCH] Add ProfileForm and improve SchoolSubForm --- src/components/Profile/ProfileForm.tsx | 124 ++++++++++++++++++ .../SchoolSubForm/SchoolSubForm.tsx | 24 ++-- src/pages/strom/profil/uprava.tsx | 12 ++ 3 files changed, 150 insertions(+), 10 deletions(-) create mode 100644 src/components/Profile/ProfileForm.tsx create mode 100644 src/pages/strom/profil/uprava.tsx diff --git a/src/components/Profile/ProfileForm.tsx b/src/components/Profile/ProfileForm.tsx new file mode 100644 index 00000000..5bb94267 --- /dev/null +++ b/src/components/Profile/ProfileForm.tsx @@ -0,0 +1,124 @@ +import {useMutation, useQuery} from '@tanstack/react-query' +import axios from 'axios' +import {useRouter} from 'next/router' +import {FC} from 'react' +import {SubmitHandler, useForm} from 'react-hook-form' + +import styles from '@/components/FormItems/Form.module.scss' +import {FormInput} from '@/components/FormItems/FormInput/FormInput' +import {SelectOption} from '@/components/FormItems/FormSelect/FormSelect' +import {IGeneralPostResponse} from '@/types/api/general' +import {Profile} from '@/types/api/personal' +import {AuthContainer} from '@/utils/AuthContainer' +import {useSeminarInfo} from '@/utils/useSeminarInfo' + +import {Button} from '../Clickable/Clickable' +import {SchoolSubForm} from '../SchoolSubForm/SchoolSubForm' + +export type ProfileFormValues = { + first_name?: string + last_name?: string + phone?: string + parent_phone?: string + new_school_description?: string + without_school: boolean + school?: SelectOption | null + school_not_found: boolean + grade: number | '' +} + +const defaultValues: ProfileFormValues = { + first_name: '', + last_name: '', + phone: '', + parent_phone: '', + new_school_description: '', + without_school: false, + school: null, + school_not_found: false, + grade: '', +} + +export const ProfileForm: FC = () => { + const {isAuthed} = AuthContainer.useContainer() + + const {data} = useQuery({ + queryKey: ['personal', 'profiles', 'myprofile'], + queryFn: () => axios.get(`/api/personal/profiles/myprofile`), + enabled: isAuthed, + }) + const profile = data?.data + const profileValues: ProfileFormValues = { + first_name: profile?.first_name, + last_name: profile?.last_name, + phone: profile?.phone ?? '', + parent_phone: profile?.parent_phone ?? '', + new_school_description: '', + without_school: profile?.school_id === 1, + school: ({id: profile?.school.code, label: profile?.school.verbose_name} as SelectOption) ?? null, + school_not_found: profile?.school_id === 0, + grade: profile?.grade ?? '', + } + + const {handleSubmit, control, watch, setValue} = useForm({ + defaultValues, + values: profileValues, + }) + + const scrollToTop = () => { + window.scrollTo({ + top: 0, + behavior: 'smooth', + }) + } + + const router = useRouter() + + const {seminar} = useSeminarInfo() + + const transformFormData = (data: ProfileFormValues) => ({ + profile: { + first_name: data.first_name, + last_name: data.last_name, + school: data.school?.id, + phone: data.phone, + parent_phone: data.parent_phone, + grade: data.grade, + }, + new_school_description: data.new_school_description || '', + }) + + const {mutate: submitFormData} = useMutation({ + mutationFn: (data: ProfileFormValues) => { + return axios.put(`/api/user/user`, transformFormData(data)) + }, + onSuccess: () => router.push(`/${seminar}/profil`), + }) + + const onSubmit: SubmitHandler = async (data) => { + submitFormData(data) + } + + const requiredRule = {required: '* Toto pole nemôže byť prázdne.'} + const phoneRule = { + validate: (val?: string) => { + if (val && !/^(\+\d{10,12})$/u.test(val.replaceAll(/\s+/gu, ''))) + return '* Zadaj telefónne číslo vo formáte validnom formáte +421 123 456 789 alebo +421123456789.' + }, + } + return ( +
+
+ + + + + +

* takto označéné polia sú povinné

+ + +
+ ) +} diff --git a/src/components/SchoolSubForm/SchoolSubForm.tsx b/src/components/SchoolSubForm/SchoolSubForm.tsx index 9390215b..10bd1d9b 100644 --- a/src/components/SchoolSubForm/SchoolSubForm.tsx +++ b/src/components/SchoolSubForm/SchoolSubForm.tsx @@ -1,7 +1,8 @@ import {useQuery} from '@tanstack/react-query' import axios from 'axios' -import {FC, useEffect, useRef} from 'react' +import {useRef} from 'react' import {Control, UseFormSetValue, UseFormWatch} from 'react-hook-form' +import {useUpdateEffect} from 'usehooks-ts' import styles from '@/components/FormItems/Form.module.scss' import {IGrade} from '@/types/api/competition' @@ -11,15 +12,20 @@ import {FormAutocomplete} from '../FormItems/FormAutocomplete/FormAutocomplete' import {FormCheckbox} from '../FormItems/FormCheckbox/FormCheckbox' import {FormInput} from '../FormItems/FormInput/FormInput' import {FormSelect, SelectOption} from '../FormItems/FormSelect/FormSelect' +import {ProfileFormValues} from '../Profile/ProfileForm' import {RegisterFormValues} from '../RegisterForm/RegisterForm' -type SchoolSubFormProps = { - control: Control - watch: UseFormWatch - setValue: UseFormSetValue +type SchoolSubFormProps = { + control: Control + watch: UseFormWatch + setValue: UseFormSetValue } -export const SchoolSubForm: FC = ({control, watch, setValue}) => { +export const SchoolSubForm = ({ + control, + watch, + setValue, +}: SchoolSubFormProps) => { const [school_not_found, without_school] = watch(['school_not_found', 'without_school']) const otherSchoolItem = useRef() @@ -49,7 +55,7 @@ export const SchoolSubForm: FC = ({control, watch, setValue} const schoolItems = allSchoolItems.filter(({id}) => ![0, 1].includes(id)) // predvyplnenie/zmazania hodnôt pri zakliknutí checkboxu pre užívateľa po škole - useEffect(() => { + useUpdateEffect(() => { if (without_school) { setValue('school', withoutSchoolItem.current) setValue('grade', 13) @@ -58,18 +64,16 @@ export const SchoolSubForm: FC = ({control, watch, setValue} setValue('school', null) setValue('grade', '') } - // eslint-disable-next-line react-hooks/exhaustive-deps }, [without_school]) // predvyplnenie/zmazania hodnôt pri zakliknutí checkboxu pre neznámu školu - useEffect(() => { + useUpdateEffect(() => { if (school_not_found) { setValue('school', otherSchoolItem.current) } else if (!without_school) { setValue('school', null) setValue('grade', '') } - // eslint-disable-next-line react-hooks/exhaustive-deps }, [school_not_found]) const requiredRule = {required: '* Toto pole nemôže byť prázdne.'} diff --git a/src/pages/strom/profil/uprava.tsx b/src/pages/strom/profil/uprava.tsx new file mode 100644 index 00000000..fd1f514e --- /dev/null +++ b/src/pages/strom/profil/uprava.tsx @@ -0,0 +1,12 @@ +import {NextPage} from 'next' + +import {PageLayout} from '@/components/PageLayout/PageLayout' +import {ProfileForm} from '@/components/Profile/ProfileForm' + +const Profil: NextPage = () => ( + + + +) + +export default Profil