Skip to content

Commit

Permalink
Add ProfileForm and improve SchoolSubForm
Browse files Browse the repository at this point in the history
  • Loading branch information
Matushl committed Nov 10, 2023
1 parent cd7af4d commit aa52416
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 10 deletions.
124 changes: 124 additions & 0 deletions src/components/Profile/ProfileForm.tsx
Original file line number Diff line number Diff line change
@@ -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<Profile>(`/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<ProfileFormValues>({
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<IGeneralPostResponse>(`/api/user/user`, transformFormData(data))
},
onSuccess: () => router.push(`/${seminar}/profil`),
})

const onSubmit: SubmitHandler<ProfileFormValues> = 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 (
<div>
<form className={styles.form} onSubmit={handleSubmit(onSubmit)}>
<FormInput control={control} name="first_name" label="krstné meno*" rules={requiredRule} />
<FormInput control={control} name="last_name" label="priezvisko*" rules={requiredRule} />
<SchoolSubForm control={control} watch={watch} setValue={setValue} />
<FormInput control={control} name="phone" label="telefónne číslo" rules={phoneRule} />
<FormInput control={control} name="parent_phone" label="telefónne číslo na rodiča" rules={phoneRule} />
<p style={{fontWeight: 'bold'}}>* takto označéné polia sú povinné</p>
<Button type="submit" onClick={scrollToTop}>
Uložiť údaje
</Button>
</form>
</div>
)
}
24 changes: 14 additions & 10 deletions src/components/SchoolSubForm/SchoolSubForm.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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<RegisterFormValues, unknown>
watch: UseFormWatch<RegisterFormValues>
setValue: UseFormSetValue<RegisterFormValues>
type SchoolSubFormProps<T extends RegisterFormValues | ProfileFormValues> = {
control: Control<T, unknown>
watch: UseFormWatch<T>
setValue: UseFormSetValue<T>
}

export const SchoolSubForm: FC<SchoolSubFormProps> = ({control, watch, setValue}) => {
export const SchoolSubForm = ({
control,
watch,
setValue,
}: SchoolSubFormProps<RegisterFormValues | ProfileFormValues>) => {
const [school_not_found, without_school] = watch(['school_not_found', 'without_school'])

const otherSchoolItem = useRef<SelectOption>()
Expand Down Expand Up @@ -49,7 +55,7 @@ export const SchoolSubForm: FC<SchoolSubFormProps> = ({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)
Expand All @@ -58,18 +64,16 @@ export const SchoolSubForm: FC<SchoolSubFormProps> = ({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.'}
Expand Down
12 changes: 12 additions & 0 deletions src/pages/strom/profil/uprava.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {NextPage} from 'next'

import {PageLayout} from '@/components/PageLayout/PageLayout'
import {ProfileForm} from '@/components/Profile/ProfileForm'

const Profil: NextPage = () => (
<PageLayout contentWidth={2} title="Profil">
<ProfileForm />
</PageLayout>
)

export default Profil

0 comments on commit aa52416

Please sign in to comment.