diff --git a/frontend/src/routes/sponsor/guest/newGuestRole/index.tsx b/frontend/src/routes/sponsor/guest/newGuestRole/index.tsx index f9671a6949817948f40270253c1959bfb17d3a97..fa5c8ef32560f4118331794d6ee69238109f7bfa 100644 --- a/frontend/src/routes/sponsor/guest/newGuestRole/index.tsx +++ b/frontend/src/routes/sponsor/guest/newGuestRole/index.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react' +import { useEffect, useState } from 'react' import { Controller, useForm } from 'react-hook-form' import { useTranslation } from 'react-i18next' import { Link, useNavigate, useParams } from 'react-router-dom' @@ -29,6 +29,11 @@ import { submitJsonOpts } from 'utils' import { useFeatureContext } from 'contexts/featureContext' import { availableInSearchEnabled } from 'appConfig' +import SubmitState from '../../register/submitState' +import ServerErrorReport, { + ServerErrorReportData, +} from '../../../../components/errorReport' + type AddRoleFormData = { orgunit: number type: string @@ -58,47 +63,11 @@ interface NewGuestRoleProps { reloadGuestInfo: () => void } -const postRole = async (formData: AddRoleFormData, pid: string) => { - const payload: AddRolePayload = { - orgunit: formData.orgunit, - person: pid, - type: formData.type, - end_date: format(formData.end_date as Date, 'yyyy-MM-dd'), - } - if (formData.start_date) { - payload.start_date = format(formData.start_date as Date, 'yyyy-MM-dd') - } - if (formData.contact_person_unit) { - payload.contact_person_unit = formData.contact_person_unit - } - if (formData.comments) { - payload.comments = formData.comments - } - if (availableInSearchEnabled && formData.available_in_search) { - payload.available_in_search = formData.available_in_search - } - - console.log('submitting', JSON.stringify(payload)) - fetch('/api/ui/v1/role', submitJsonOpts('POST', payload)) - .then((res) => { - if (!res.ok) { - console.log('result', res) - return null - } - console.log('result', res) - return res.text() - }) - .then((result) => { - if (result !== null) { - console.log('result', result) - } - }) - .catch((error) => { - console.log('error', error) - }) -} function NewGuestRole({ guest, reloadGuestInfo }: NewGuestRoleProps) { + + const [submitState, setSubmitState] = useState(SubmitState.NotSubmitted) + const { register, control, @@ -118,8 +87,12 @@ function NewGuestRole({ guest, reloadGuestInfo }: NewGuestRoleProps) { const navigate = useNavigate() const onSubmit = handleSubmit(async () => { await postRole(getValues(), pid) + reloadGuestInfo() - navigate(`/sponsor/guest/${pid}`) + + if (submitState == SubmitState.SubmitSuccess) { + navigate(`/sponsor/guest/${pid}`) + } }) const { ous } = useOus() @@ -130,6 +103,8 @@ function NewGuestRole({ guest, reloadGuestInfo }: NewGuestRoleProps) { const today = new Date() const [endDate, setEndDate] = useState<Date | null>(null) const [maxDate, setMaxDate] = useState(today) + const [submitErrorReport, setSubmitErrorReport] = + useState<ServerErrorReportData>() const todayPlusMaxDays = (roleTypeId?: number) => { if (roleTypeId) { @@ -184,6 +159,68 @@ function NewGuestRole({ guest, reloadGuestInfo }: NewGuestRoleProps) { </MenuItem> ) } + const postRole = async (formData: AddRoleFormData, pid: string) => { + const payload: AddRolePayload = { + orgunit: formData.orgunit, + person: pid, + type: formData.type, + end_date: format(formData.end_date as Date, 'yyyy-MM-dd'), + } + if (formData.start_date) { + payload.start_date = format(formData.start_date as Date, 'yyyy-MM-dd') + } + if (formData.contact_person_unit) { + payload.contact_person_unit = formData.contact_person_unit + } + if (formData.comments) { + payload.comments = formData.comments + } + if (availableInSearchEnabled && formData.available_in_search) { + payload.available_in_search = formData.available_in_search + } + + fetch('/api/ui/v1/role', submitJsonOpts('POST', payload)) + .then((res) => { + if (!res.ok) { + handleSubmitErrorResponse(res) + } else { + setSubmitState(SubmitState.SubmitSuccess) + } + }) + } + function handleSubmitErrorResponse(res: Response) { + // Try to extract data from body of error message + res + .text() + .then((text) => { + setSubmitState(SubmitState.SubmitFailure) + + // Some error responses have a code that is used to look up a translated text. + // Attempt to parse the message text and extract the code + const jsonResponse = JSON.parse(text) + const errorText = + jsonResponse.code === undefined + ? text + : t(`error.codes.${jsonResponse.code}`) + + setSubmitErrorReport({ + errorHeading: t('error.invitationCreationFailedHeader'), + statusCode: res.status, + statusText: res.statusText, + errorBodyText: errorText, + }) + }) + .catch(() => { + // Extracting data from body failed, just show an error message with no body text + setSubmitErrorReport({ + errorHeading: t('error.invitationCreationFailedHeader'), + statusCode: res.status, + statusText: res.statusText, + errorBodyText: undefined, + }) + setSubmitState(SubmitState.SubmitFailure) + }) + } const hasRoleTypeError = errors && errors.type && errors.type.type === 'required' const hasOuChoiceError = @@ -373,6 +410,15 @@ function NewGuestRole({ guest, reloadGuestInfo }: NewGuestRoleProps) { > {t('button.cancel')} </Button> + {submitState === SubmitState.SubmitFailure && + submitErrorReport !== undefined && ( + <ServerErrorReport + errorHeading={submitErrorReport?.errorHeading} + statusCode={submitErrorReport?.statusCode} + statusText={submitErrorReport?.statusText} + errorBodyText={submitErrorReport?.errorBodyText} + /> + )} </Stack> </form> </Page>