diff --git a/frontend/src/routes/index.tsx b/frontend/src/routes/index.tsx index 8ecd1892468cfa5a643ddf40632f5c5f758333fc..a62d0d7f75f6ae2da3f547e464fa2093ebdaca80 100644 --- a/frontend/src/routes/index.tsx +++ b/frontend/src/routes/index.tsx @@ -8,7 +8,7 @@ import fetchIntercept from 'fetch-intercept' import { useUserContext } from 'contexts' import Sponsor from 'routes/sponsor' -import Register from 'routes/register' +import Register from 'routes/sponsor/register' import FrontPage from 'routes/frontpage' import Invite from 'routes/invite' import InviteLink from 'routes/invitelink' diff --git a/frontend/src/routes/register/stepPersonForm.tsx b/frontend/src/routes/register/stepPersonForm.tsx deleted file mode 100644 index cb93d43d9d9379d0498b56dceb39af24e557dd15..0000000000000000000000000000000000000000 --- a/frontend/src/routes/register/stepPersonForm.tsx +++ /dev/null @@ -1,233 +0,0 @@ -import { - Box, - FormControl, - InputLabel, - MenuItem, - Select, - SelectChangeEvent, - Stack, - TextField, - Typography, -} from '@mui/material' -import { Controller, SubmitHandler, useForm } from 'react-hook-form' -import { DatePicker } from '@mui/lab' -import React, { forwardRef, Ref, useEffect, useImperativeHandle, useState } from 'react' -import { useTranslation } from 'react-i18next' -import { RegisterFormData } from './formData' -import { PersonFormMethods } from './personFormMethods' -import useOus, { OuData } from '../../hooks/useOus' -import useRoleTypes, { RoleTypeData } from '../../hooks/useRoleTypes' -import { isValidEmail } from '../../utils' - - -interface StepPersonFormProperties { - nextHandler(formState: RegisterFormData): void - - formData: RegisterFormData -} - -const StepPersonForm = forwardRef((props: StepPersonFormProperties, ref: Ref<PersonFormMethods>) => { - const { i18n, t } = useTranslation(['common']) - const { nextHandler, formData } = props - const ous = useOus() - const [ouChoice, setOuChoice] = useState(formData.ou_id ? formData.ou_id : '') - const [selectedRoleType, setSelectedRoleType] = useState(formData.role_type ? formData.role_type : '') - const roleTypes = useRoleTypes() - - - const roleTypeSort = () => (a: RoleTypeData, b: RoleTypeData) => { - if (i18n.language === 'en') { - return a.name_nb.localeCompare(b.name_nb) - } - return a.name_en.localeCompare(b.name_en) - } - - const enSort = (a: OuData, b: OuData) => { - if (a.en > b.en) { - return 1 - } - if (b.en > a.en) { - return -1 - } - return 0 - } - - const nbSort = (a: OuData, b: OuData) => { - if (a.nb > b.nb) { - return 1 - } - if (b.nb > a.nb) { - return -1 - } - return 0 - } - - const submit: SubmitHandler<RegisterFormData> = (data) => { - nextHandler(data) - } - - const { - register, - control, - handleSubmit, - formState: { errors }, - reset, - setValue, - } = useForm<RegisterFormData>() - const onSubmit = handleSubmit(submit) - - - useEffect(() => { - reset(formData) - }, []) - - const handleOuChange = (event: SelectChangeEvent) => { - if (event.target.value) { - setOuChoice(event.target.value) - setValue('ou_id', parseInt(event.target.value, 10)) - } else { - setValue('ou_id', undefined) - } - } - - register('role_type', { - required: t<string>('validation.roleTypeRequired'), - }) - - const handleRoleTypeChange = (event: any) => { - setValue('role_type', event.target.value) - setSelectedRoleType(event.target.value) - } - - function doSubmit() { - return onSubmit() - } - - useImperativeHandle(ref, () => ({ doSubmit })) - - return ( - <> - <Typography variant='h5' sx={{ - paddingTop: '1rem', - paddingBottom: '1rem', - }}>{t('registerWizardText.registerContactInfo')}</Typography> - <Typography sx={{ paddingBottom: '2rem' }}>{t('registerWizardText.registerPage')}</Typography> - <Box sx={{ maxWidth: '30rem' }}> - <form onSubmit={onSubmit}> - <Stack spacing={2}> - <TextField - id='firstName' - label={t('input.firstName')} - error={!!errors.first_name} - helperText={errors.first_name && errors.first_name.message} - {...register(`first_name`, { - required: t<string>('validation.firstNameRequired'), - })} - /> - <TextField - id='lastName' - label={t('input.lastName')} - error={!!errors.last_name} - helperText={errors.last_name && errors.last_name.message} - {...register(`last_name`, { - required: t<string>('validation.lastNameRequired'), - })} - inputProps={{ 'data-testid': 'lastName-input-field' }} - /> - <TextField - id='email' - label={t('input.email')} - error={!!errors.email} - helperText={errors.email && errors.email.message} - {...register(`email`, { - validate: isValidEmail, - })} - /> - - <Typography variant='h5' sx={{ paddingTop: '1rem' }}>{t('registerWizardText.registerPeriod')}</Typography> - <Typography sx={{ paddingBottom: '1rem' }}>{t('registerWizardText.registerPeriodText')}</Typography> - <FormControl fullWidth> - <InputLabel id='ou-select-label'>{t('common:ou')}</InputLabel> - <Select - labelId='ou-select-label' - id='ou-select-label' - value={ouChoice?.toString()} - label={t('common:ou')} - onChange={handleOuChange} - > - {ous.length > 0 ? ( - ous - .sort(i18n.language === 'en' ? enSort : nbSort) - .map((ou) => ( - <MenuItem key={ou.id.toString()} value={ou.id}> - {i18n.language === 'en' ? ou.en : ou.nb} ({ou.id}) - </MenuItem> - )) - ) : ('')} - </Select> - </FormControl> - - <TextField - id='roletype-select' - select - value={selectedRoleType} - error={!!errors.role_type} - label={t('input.roleType')} - onChange={handleRoleTypeChange} - > - { - roleTypes.sort(roleTypeSort()) - .map((roleType) => ( - <MenuItem - key={roleType.id.toString()} - value={roleType.id}>{i18n.language === 'en' ? roleType.name_en : roleType.name_nb}</MenuItem> - )) - } - </TextField> - - <Controller name='role_start' - control={control} - render={({ field }) => ( - <DatePicker - mask='____-__-__' - label={t('input.roleStartDate')} - value={field.value} - inputFormat='yyyy-MM-dd' - onChange={(value) => { - field.onChange(value) - }} - renderInput={(params) => <TextField {...params} />} - />)} - /> - - <Controller name='role_end' - control={control} - defaultValue={undefined} - render={({ field }) => ( - <DatePicker - mask='____-__-__' - label={t('input.roleEndDate')} - value={field.value} - inputFormat='yyyy-MM-dd' - onChange={(value) => { - field.onChange(value) - }} - renderInput={(params) => <TextField {...params} />} - />)} - /> - - <TextField - id='comment' - label={t('input.comment')} - multiline - rows={5} - {...register(`comment`)} - /> - </Stack> - </form> - </Box> - </> - ) -}) - -export default StepPersonForm diff --git a/frontend/src/routes/register/stepSummary.tsx b/frontend/src/routes/register/stepSummary.tsx deleted file mode 100644 index 2f2f432afbeb51908c09376b3cd4205f11572d79..0000000000000000000000000000000000000000 --- a/frontend/src/routes/register/stepSummary.tsx +++ /dev/null @@ -1,171 +0,0 @@ -import React, { forwardRef, Ref, useImperativeHandle, useState } from 'react' -import { useTranslation } from 'react-i18next' - -import { - Box, - Grid, - Table, - TableBody, - TableCell, - TableHead, - TableRow, -} from '@mui/material' - -import format from 'date-fns/format' -import i18n from 'i18next' -import { RegisterFormData } from './formData' -import { postJsonOpts } from '../../utils' -import { PersonFormMethods } from './personFormMethods' -import useOus from '../../hooks/useOus' -import useRoleTypes from '../../hooks/useRoleTypes' -import SubmitState from './submitState' - - -interface StepSummaryProperties { - formData: RegisterFormData - onSubmitSuccess: () => void - onSubmitFailure: () => void -} - -const StepSummary = forwardRef((props: StepSummaryProperties, ref: Ref<PersonFormMethods>) => { - const { t } = useTranslation(['common']) - const { formData, onSubmitSuccess, onSubmitFailure } = props - const ous = useOus() - const roleTypes = useRoleTypes() - const [submitState, setSubmitState] = useState(SubmitState.NotSubmitted) - - const submit = () => { - const payload = { - first_name: formData.first_name, - last_name: formData.last_name, - email: formData.email, - role: { - type: formData.role_type, - start_date: formData.role_start === null ? null : format(formData.role_start as Date, 'yyyy-MM-dd'), - end_date: formData.role_end === null ? null : format(formData.role_end as Date, 'yyyy-MM-dd'), - comments: formData.comment, - orgunit_id: formData.ou_id, - }, - } - - console.log('submitting', JSON.stringify(payload)) - fetch('/api/ui/v1/invite/', postJsonOpts(payload)) - .then((res) => { - if (!res.ok) { - onSubmitFailure() - setSubmitState(SubmitState.SubmitFailure) - return null - } - return res.text() - }) - .then((result) => { - if (result !== null) { - console.log('result', result) - onSubmitSuccess() - setSubmitState(SubmitState.SubmitSuccess) - } - }) - .catch((error) => { - console.log('error', error) - onSubmitFailure() - setSubmitState(SubmitState.SubmitFailure) - }) - } - - function doSubmit() { - return submit() - } - - useImperativeHandle(ref, () => ({ doSubmit })) - - const selectedOus = ous.find((value) => value.id === formData.ou_id) - const ousName = selectedOus === undefined ? '' : (`${i18n.language === 'en' ? selectedOus.en : selectedOus.nb} (${selectedOus.id})`) - - // TODO Fix this confusing mix between use of id and identifier - const selectedRoleType = roleTypes.find((value) => value.id === (formData.role_type === undefined ? -1 : parseInt(formData.role_type, 10))) - const roleTypeName = selectedRoleType === undefined ? '' : `${i18n.language === 'en' ? selectedRoleType.name_en : selectedRoleType.name_nb}` - - return ( - <> - <Box sx={{ - paddingTop: '1rem', - paddingBottom: '1rem', - }}> - {t('registerWizardText.summaryContactInformation')} - </Box> - - <Box sx={{ typography: 'body2' }}> - {t('registerWizardText.summaryPage')} - </Box> - <Box sx={{ marginTop: '1rem', maxWidth: '50rem' }}> - <Box sx={{ - typography: 'subtitle2', - marginBottom: '0.5rem', - paddingLeft: '0.5rem', - bgcolor: 'primary.dark', - }}>{t('registerWizardText.contactInformation')}</Box> - - <Grid sx={{ typography: 'body2', paddingLeft: '0.5rem' }} container> - <Grid item xs={4}> - {t('input.fullName')} - </Grid> - <Grid item xs={8}> - {formData.first_name} {formData.last_name} - </Grid> - <Grid item xs={4}> - {t('input.email')} - </Grid> - <Grid item xs={8}> - {formData.email} - </Grid> - </Grid> - - <Box sx={{ - paddingTop: '1rem', - paddingBottom: '1rem', - }}> - {t('registerWizardText.summaryPeriod')} - </Box> - - <Table> - <TableHead sx={{ - paddingLeft: '0.5rem', - bgcolor: 'primary.dark', - }}> - - <TableRow> - <TableCell>{t('registerWizardText.guestRole')}</TableCell> - <TableCell>{t('registerWizardText.guestPeriod')}</TableCell> - <TableCell>{t('registerWizardText.guestDepartment')}</TableCell> - <TableCell>{t('input.comment')}</TableCell> - </TableRow> - </TableHead> - <TableBody> - <TableRow> - <TableCell>{roleTypeName}</TableCell> - <TableCell>{formData.role_start === null ? null : format(formData.role_start as Date, 'yyyy-MM-dd')} - {formData.role_end === null ? null : format(formData.role_end as Date, 'yyyy-MM-dd')}</TableCell> - <TableCell>{ousName}</TableCell> - <TableCell>{formData.comment}</TableCell> - </TableRow> - </TableBody> - </Table> - - {/* TODO For now just showing a heading to give the user some feedback */} - {submitState === SubmitState.SubmitSuccess && ( - <Box> - <h2>Submit success</h2> - </Box> - )} - - {submitState === SubmitState.SubmitFailure && ( - <Box> - <h2>Submit failure</h2> - </Box> - )} - </Box> - </> - ) - }, -) - -export default StepSummary diff --git a/frontend/src/routes/register/summaryFormMethods.ts b/frontend/src/routes/register/summaryFormMethods.ts deleted file mode 100644 index cae925ff66f791fe9157b5a811bdc7fa7b24ae0f..0000000000000000000000000000000000000000 --- a/frontend/src/routes/register/summaryFormMethods.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface SummaryFormMethods { - doSubmit: () => Promise<void> -} diff --git a/frontend/src/routes/register/formData.ts b/frontend/src/routes/sponsor/register/formData.ts similarity index 100% rename from frontend/src/routes/register/formData.ts rename to frontend/src/routes/sponsor/register/formData.ts diff --git a/frontend/src/routes/register/index.test.tsx b/frontend/src/routes/sponsor/register/index.test.tsx similarity index 100% rename from frontend/src/routes/register/index.test.tsx rename to frontend/src/routes/sponsor/register/index.test.tsx diff --git a/frontend/src/routes/register/index.tsx b/frontend/src/routes/sponsor/register/index.tsx similarity index 56% rename from frontend/src/routes/register/index.tsx rename to frontend/src/routes/sponsor/register/index.tsx index e7d1053e70baf38ffd8012e33f3c07fcac1a3c40..bab1d0613eed1a85ba8f9ca315c70acdfc968678 100644 --- a/frontend/src/routes/register/index.tsx +++ b/frontend/src/routes/sponsor/register/index.tsx @@ -5,15 +5,21 @@ import { Box, Button } from '@mui/material' import Page from 'components/page' import { useHistory } from 'react-router-dom' +import format from 'date-fns/format' import { RegisterFormData } from './formData' import StepSummary from './stepSummary' import StepPersonForm from './stepPersonForm' import { PersonFormMethods } from './personFormMethods' -import { SummaryFormMethods } from './summaryFormMethods' import SubmitState from './submitState' -import SponsorGuestButtons from '../components/sponsorGuestButtons' - - +import SponsorGuestButtons from '../../components/sponsorGuestButtons' +import { postJsonOpts } from '../../../utils' + +/** + * + * This component controls the invite process where the sponsor + * enters the initial information about a guest. + * + */ export default function StepRegistration() { const { t } = useTranslation(['common']) const [formData, setFormData] = useState<RegisterFormData>({ @@ -32,7 +38,6 @@ export default function StepRegistration() { const SUMMARY_STEP = 1 const [activeStep, setActiveStep] = useState(0) const personFormRef = useRef<PersonFormMethods>(null) - const summaryStepRef = useRef<SummaryFormMethods>(null) const [submitState, setSubmitState] = useState(SubmitState.NotSubmitted) const handleNext = () => { @@ -46,9 +51,44 @@ export default function StepRegistration() { } const registerGuest = () => { - if (summaryStepRef.current) { - summaryStepRef.current.doSubmit() + const payload = { + first_name: formData.first_name, + last_name: formData.last_name, + email: formData.email, + role: { + type: formData.role_type, + start_date: + formData.role_start === null + ? null + : format(formData.role_start as Date, 'yyyy-MM-dd'), + end_date: + formData.role_end === null + ? null + : format(formData.role_end as Date, 'yyyy-MM-dd'), + comments: formData.comment, + orgunit_id: formData.ou_id, + }, } + + console.log('submitting', JSON.stringify(payload)) + fetch('/api/ui/v1/invite/', postJsonOpts(payload)) + .then((res) => { + if (!res.ok) { + setSubmitState(SubmitState.SubmitFailure) + return null + } + return res.text() + }) + .then((result) => { + if (result !== null) { + console.log('result', result) + setSubmitState(SubmitState.SubmitSuccess) + } + }) + .catch((error) => { + console.log('error', error) + setSubmitState(SubmitState.SubmitFailure) + }) } const handleBack = () => { @@ -56,7 +96,7 @@ export default function StepRegistration() { } const handleForwardFromRegister = ( - updateFormData: RegisterFormData, + updateFormData: RegisterFormData ): void => { setFormData(updateFormData) setActiveStep((prevActiveStep) => prevActiveStep + 1) @@ -66,14 +106,6 @@ export default function StepRegistration() { history.push('/') } - const handleSubmitSuccess = () => { - setSubmitState(SubmitState.SubmitSuccess) - } - - const handleSubmitFailure = () => { - setSubmitState(SubmitState.SubmitFailure) - } - return ( <Page> <SponsorGuestButtons registerNewGuestActive /> @@ -86,21 +118,24 @@ export default function StepRegistration() { ref={personFormRef} /> )} - {activeStep === SUMMARY_STEP && ( - <StepSummary - formData={formData} - onSubmitSuccess={handleSubmitSuccess} - onSubmitFailure={handleSubmitFailure} - ref={summaryStepRef} - /> - )} + {activeStep === SUMMARY_STEP && <StepSummary formData={formData} />} </Box> - <Box sx={{ display: 'flex', flexDirection: 'row', pt: 2, color: 'primary.main', paddingBottom: '1rem' }}> + <Box + sx={{ + display: 'flex', + flexDirection: 'row', + pt: 2, + color: 'primary.main', + paddingBottom: '1rem', + }} + > {activeStep === REGISTER_STEP && ( - <Button data-testid='button-next' - sx={{ color: 'theme.palette.secondary', mr: 1 }} - onClick={handleNext}> + <Button + data-testid="button-next" + sx={{ color: 'theme.palette.secondary', mr: 1 }} + onClick={handleNext} + > {t('button.next')} </Button> )} @@ -132,6 +167,19 @@ export default function StepRegistration() { {t('button.cancel')} </Button> </Box> + + {/* TODO For now just showing a heading to give the user some feedback. Should probably go to a different page on success */} + {submitState === SubmitState.SubmitSuccess && ( + <Box> + <h2>Submit success</h2> + </Box> + )} + + {submitState === SubmitState.SubmitFailure && ( + <Box> + <h2>Submit failure</h2> + </Box> + )} </Page> ) } diff --git a/frontend/src/routes/register/personFormMethods.ts b/frontend/src/routes/sponsor/register/personFormMethods.ts similarity index 100% rename from frontend/src/routes/register/personFormMethods.ts rename to frontend/src/routes/sponsor/register/personFormMethods.ts diff --git a/frontend/src/routes/sponsor/register/stepPersonForm.tsx b/frontend/src/routes/sponsor/register/stepPersonForm.tsx new file mode 100644 index 0000000000000000000000000000000000000000..ca85cbc8165395f479f865d5eea931546d003ec7 --- /dev/null +++ b/frontend/src/routes/sponsor/register/stepPersonForm.tsx @@ -0,0 +1,258 @@ +import { + Box, + FormControl, + InputLabel, + MenuItem, + Select, + SelectChangeEvent, + Stack, + TextField, + Typography, +} from '@mui/material' +import { Controller, SubmitHandler, useForm } from 'react-hook-form' +import { DatePicker } from '@mui/lab' +import React, { + forwardRef, + Ref, + useEffect, + useImperativeHandle, + useState, +} from 'react' +import { useTranslation } from 'react-i18next' +import { RegisterFormData } from './formData' +import { PersonFormMethods } from './personFormMethods' +import useOus, { OuData } from '../../../hooks/useOus' +import useRoleTypes, { RoleTypeData } from '../../../hooks/useRoleTypes' +import { isValidEmail } from '../../../utils' + +interface StepPersonFormProperties { + nextHandler(formState: RegisterFormData): void + + formData: RegisterFormData +} + +const StepPersonForm = forwardRef( + (props: StepPersonFormProperties, ref: Ref<PersonFormMethods>) => { + const { i18n, t } = useTranslation(['common']) + const { nextHandler, formData } = props + const ous = useOus() + const [ouChoice, setOuChoice] = useState( + formData.ou_id ? formData.ou_id : '' + ) + const [selectedRoleType, setSelectedRoleType] = useState( + formData.role_type ? formData.role_type : '' + ) + const roleTypes = useRoleTypes() + + const roleTypeSort = () => (a: RoleTypeData, b: RoleTypeData) => { + if (i18n.language === 'en') { + return a.name_nb.localeCompare(b.name_nb) + } + return a.name_en.localeCompare(b.name_en) + } + + const enSort = (a: OuData, b: OuData) => { + if (a.en > b.en) { + return 1 + } + if (b.en > a.en) { + return -1 + } + return 0 + } + + const nbSort = (a: OuData, b: OuData) => { + if (a.nb > b.nb) { + return 1 + } + if (b.nb > a.nb) { + return -1 + } + return 0 + } + + const submit: SubmitHandler<RegisterFormData> = (data) => { + nextHandler(data) + } + + const { + register, + control, + handleSubmit, + formState: { errors }, + reset, + setValue, + } = useForm<RegisterFormData>() + const onSubmit = handleSubmit(submit) + + useEffect(() => { + reset(formData) + }, []) + + const handleOuChange = (event: SelectChangeEvent) => { + if (event.target.value) { + setOuChoice(event.target.value) + setValue('ou_id', parseInt(event.target.value, 10)) + } else { + setValue('ou_id', undefined) + } + } + + register('role_type', { + required: t<string>('validation.roleTypeRequired'), + }) + + const handleRoleTypeChange = (event: any) => { + setValue('role_type', event.target.value) + setSelectedRoleType(event.target.value) + } + + function doSubmit() { + return onSubmit() + } + + useImperativeHandle(ref, () => ({ doSubmit })) + + return ( + <> + <Typography + variant="h5" + sx={{ + paddingTop: '1rem', + paddingBottom: '1rem', + }} + > + {t('registerWizardText.registerContactInfo')} + </Typography> + <Typography sx={{ paddingBottom: '2rem' }}> + {t('registerWizardText.registerPage')} + </Typography> + <Box sx={{ maxWidth: '30rem' }}> + <form onSubmit={onSubmit}> + <Stack spacing={2}> + <TextField + id="firstName" + label={t('input.firstName')} + error={!!errors.first_name} + helperText={errors.first_name && errors.first_name.message} + {...register(`first_name`, { + required: t<string>('validation.firstNameRequired'), + })} + /> + <TextField + id="lastName" + label={t('input.lastName')} + error={!!errors.last_name} + helperText={errors.last_name && errors.last_name.message} + {...register(`last_name`, { + required: t<string>('validation.lastNameRequired'), + })} + inputProps={{ 'data-testid': 'lastName-input-field' }} + /> + <TextField + id="email" + label={t('input.email')} + error={!!errors.email} + helperText={errors.email && errors.email.message} + {...register(`email`, { + validate: isValidEmail, + })} + /> + + <Typography variant="h5" sx={{ paddingTop: '1rem' }}> + {t('registerWizardText.registerPeriod')} + </Typography> + <Typography sx={{ paddingBottom: '1rem' }}> + {t('registerWizardText.registerPeriodText')} + </Typography> + <FormControl fullWidth> + <InputLabel id="ou-select-label">{t('common:ou')}</InputLabel> + <Select + labelId="ou-select-label" + id="ou-select-label" + value={ouChoice?.toString()} + label={t('common:ou')} + onChange={handleOuChange} + > + {ous.length > 0 ? ( + ous + .sort(i18n.language === 'en' ? enSort : nbSort) + .map((ou) => ( + <MenuItem key={ou.id.toString()} value={ou.id}> + {i18n.language === 'en' ? ou.en : ou.nb} ({ou.id}) + </MenuItem> + )) + ) : ( + <></> + )} + </Select> + </FormControl> + + <TextField + id="roletype-select" + select + value={selectedRoleType} + error={!!errors.role_type} + label={t('input.roleType')} + onChange={handleRoleTypeChange} + > + {roleTypes.sort(roleTypeSort()).map((roleType) => ( + <MenuItem key={roleType.id.toString()} value={roleType.id}> + {i18n.language === 'en' + ? roleType.name_en + : roleType.name_nb} + </MenuItem> + ))} + </TextField> + + <Controller + name="role_start" + control={control} + render={({ field }) => ( + <DatePicker + mask="____-__-__" + label={t('input.roleStartDate')} + value={field.value} + inputFormat="yyyy-MM-dd" + onChange={(value) => { + field.onChange(value) + }} + renderInput={(params) => <TextField {...params} />} + /> + )} + /> + + <Controller + name="role_end" + control={control} + defaultValue={undefined} + render={({ field }) => ( + <DatePicker + mask="____-__-__" + label={t('input.roleEndDate')} + value={field.value} + inputFormat="yyyy-MM-dd" + onChange={(value) => { + field.onChange(value) + }} + renderInput={(params) => <TextField {...params} />} + /> + )} + /> + + <TextField + id="comment" + label={t('input.comment')} + multiline + rows={5} + {...register(`comment`)} + /> + </Stack> + </form> + </Box> + </> + ) + } +) + +export default StepPersonForm diff --git a/frontend/src/routes/sponsor/register/stepSummary.tsx b/frontend/src/routes/sponsor/register/stepSummary.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f01f865d476b9449e9655d05da2a5a6f82e30d58 --- /dev/null +++ b/frontend/src/routes/sponsor/register/stepSummary.tsx @@ -0,0 +1,139 @@ +import React, { forwardRef } from 'react' +import { useTranslation } from 'react-i18next' + +import { + Box, + Grid, + Table, + TableBody, + TableCell, + TableHead, + TableRow, +} from '@mui/material' + +import format from 'date-fns/format' +import i18n from 'i18next' +import { RegisterFormData } from './formData' +import useOus from '../../../hooks/useOus' +import useRoleTypes from '../../../hooks/useRoleTypes' + +interface StepSummaryProperties { + formData: RegisterFormData +} + +const StepSummary = forwardRef((props: StepSummaryProperties) => { + const { t } = useTranslation(['common']) + const { formData } = props + const ous = useOus() + const roleTypes = useRoleTypes() + + const selectedOus = ous.find((value) => value.id === formData.ou_id) + const ousName = + selectedOus === undefined + ? '' + : `${i18n.language === 'en' ? selectedOus.en : selectedOus.nb} (${ + selectedOus.id + })` + + // TODO Fix this confusing mix between use of id and identifier + const selectedRoleType = roleTypes.find( + (value) => + value.id === + (formData.role_type === undefined ? -1 : parseInt(formData.role_type, 10)) + ) + const roleTypeName = + selectedRoleType === undefined + ? '' + : `${ + i18n.language === 'en' + ? selectedRoleType.name_en + : selectedRoleType.name_nb + }` + + return ( + <> + <Box + sx={{ + paddingTop: '1rem', + paddingBottom: '1rem', + }} + > + {t('registerWizardText.summaryContactInformation')} + </Box> + + <Box sx={{ typography: 'body2' }}> + {t('registerWizardText.summaryPage')} + </Box> + <Box sx={{ marginTop: '1rem', maxWidth: '50rem' }}> + <Box + sx={{ + typography: 'subtitle2', + marginBottom: '0.5rem', + paddingLeft: '0.5rem', + bgcolor: 'primary.light', + }} + > + {t('registerWizardText.contactInformation')} + </Box> + + <Grid sx={{ typography: 'body2', paddingLeft: '0.5rem' }} container> + <Grid item xs={4}> + {t('input.fullName')} + </Grid> + <Grid item xs={8}> + {formData.first_name} {formData.last_name} + </Grid> + <Grid item xs={4}> + {t('input.email')} + </Grid> + <Grid item xs={8}> + {formData.email} + </Grid> + </Grid> + + <Box + sx={{ + paddingTop: '1rem', + paddingBottom: '1rem', + }} + > + {t('registerWizardText.summaryPeriod')} + </Box> + + <Table> + <TableHead + sx={{ + paddingLeft: '0.5rem', + bgcolor: 'primary.light', + }} + > + <TableRow> + <TableCell>{t('registerWizardText.guestRole')}</TableCell> + <TableCell>{t('registerWizardText.guestPeriod')}</TableCell> + <TableCell>{t('registerWizardText.guestDepartment')}</TableCell> + <TableCell>{t('input.comment')}</TableCell> + </TableRow> + </TableHead> + <TableBody> + <TableRow> + <TableCell>{roleTypeName}</TableCell> + <TableCell> + {formData.role_start === null + ? null + : format(formData.role_start as Date, 'yyyy-MM-dd')}{' '} + -{' '} + {formData.role_end === null + ? null + : format(formData.role_end as Date, 'yyyy-MM-dd')} + </TableCell> + <TableCell>{ousName}</TableCell> + <TableCell>{formData.comment}</TableCell> + </TableRow> + </TableBody> + </Table> + </Box> + </> + ) +}) + +export default StepSummary diff --git a/frontend/src/routes/register/submitState.ts b/frontend/src/routes/sponsor/register/submitState.ts similarity index 82% rename from frontend/src/routes/register/submitState.ts rename to frontend/src/routes/sponsor/register/submitState.ts index e0bdda9fff21cc73db52924ecb1d76219cc72e4f..a7d5c631e95c67d7c1b7554f341dbbefe679d7d3 100644 --- a/frontend/src/routes/register/submitState.ts +++ b/frontend/src/routes/sponsor/register/submitState.ts @@ -1,7 +1,7 @@ enum SubmitState { NotSubmitted, SubmitSuccess, - SubmitFailure + SubmitFailure, } export default SubmitState