diff --git a/frontend/public/locales/en/common.json b/frontend/public/locales/en/common.json index 3c9cd85056c8e5f84788f59a62242ce88f471ff4..bf866efa5265ec601a931ea812f04c36ec741ac1 100644 --- a/frontend/public/locales/en/common.json +++ b/frontend/public/locales/en/common.json @@ -144,5 +144,11 @@ "confirmIdentityTitle": "Confirm?", "cancelInvitation": "Cancel invitation?", "cancelInvitationDescription": "Do you want to cancel the invitation?" + }, + "error": { + "invitationCreationFailedHeader": "Failed to create invite", + "errorStatusCode": "Status code: {{statusCode}} (<3>{{statusText}}</3>)", + "genericServerErrorBody": "The server reported:<1>{{errorBodyText}}</1>", + "contactHelp": "Contact help through the link in the footer if the problem persists." } } diff --git a/frontend/public/locales/nb/common.json b/frontend/public/locales/nb/common.json index dd1e76b002cd2e58f606573fff075ea15482cd42..290d8f21ff951f77004efb2acb04566af96c0c4f 100644 --- a/frontend/public/locales/nb/common.json +++ b/frontend/public/locales/nb/common.json @@ -144,5 +144,11 @@ "confirmIdentityTitle": "Bekrefte?", "cancelInvitation": "Kanseller invitasjon?", "cancelInvitationDescription": "Vil du kansellere invitasjonen?" + }, + "error": { + "invitationCreationFailedHeader": "Kunne ikke opprette invitasjon", + "errorStatusCode": "Statuskode: {{statusCode}} (<3>{{statusText}}</3>)", + "genericServerErrorBody": "Respons fra server:<1>{{errorBodyText}}</1>", + "contactHelp": "Kontakt hjelp via link i footer om problemet vedvarer." } } diff --git a/frontend/public/locales/nn/common.json b/frontend/public/locales/nn/common.json index c524def71a3783691f2c5d365711a8b602542296..b7beee8b36c12ab5006cfcc88af9857989ec992d 100644 --- a/frontend/public/locales/nn/common.json +++ b/frontend/public/locales/nn/common.json @@ -145,5 +145,11 @@ "confirmIdentityTitle": "Bekrefte?", "cancelInvitation": "Kanseller invitasjon?", "cancelInvitationDescription": "Vil du kansellere invitasjonen?" + }, + "error": { + "invitationCreationFailedHeader": "Kunne ikkje opprette invitasjon", + "errorStatusCode": "Statuskode: {{statusCode}} (<3>{{statusText}}</3>)", + "genericServerErrorBody": "Respons frå server:<1>{{errorBodyText}}</1>", + "contactHelp": "Kontakt hjelp via link i footer om problemet vedvarer." } } diff --git a/frontend/src/components/errorReport/index.tsx b/frontend/src/components/errorReport/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4aace3fff5168fe2edd63667db6240d5fc2420dc --- /dev/null +++ b/frontend/src/components/errorReport/index.tsx @@ -0,0 +1,43 @@ +import { Alert, AlertTitle } from '@mui/material' +import { Trans, useTranslation } from 'react-i18next' +import React from 'react' + +interface ErrorReportProps { + errorHeading: string + statusCode?: number + statusText?: string + errorBodyText?: string +} + +export default function ServerErrorReport({ + errorHeading, + statusCode, + statusText, + errorBodyText, +}: ErrorReportProps) { + const [t] = useTranslation(['common']) + return ( + <Alert severity="error"> + <AlertTitle>{errorHeading}</AlertTitle> + {statusCode !== undefined && ( + <Trans i18nKey="error.errorStatusCode" t={t}> + Status code: {{ statusCode }} (<strong>{{ statusText }}</strong>) + </Trans> + )} + <br /> + {errorBodyText !== undefined && ( + <Trans i18nKey="error.genericServerErrorBody" t={t}> + The server reported: + <blockquote>{{ errorBodyText }}</blockquote> + </Trans> + )} + {t('error.contactHelp')} + </Alert> + ) +} + +ServerErrorReport.defaultProps = { + statusCode: undefined, + statusText: undefined, + errorBodyText: undefined, +} diff --git a/frontend/src/routes/sponsor/register/stepRegistration.tsx b/frontend/src/routes/sponsor/register/stepRegistration.tsx index e7592ede61751bcfb9045c94864b1d1e6cea116e..3b7e98aed639820b29d584a3a034cb7c26ef19ca 100644 --- a/frontend/src/routes/sponsor/register/stepRegistration.tsx +++ b/frontend/src/routes/sponsor/register/stepRegistration.tsx @@ -14,6 +14,7 @@ import SubmitState from './submitState' import SponsorGuestButtons from '../../components/sponsorGuestButtons' import { submitJsonOpts } from '../../../utils' import StepSubmitSuccess from './stepSubmitSuccess' +import ServerErrorReport from '../../../components/errorReport' enum Steps { RegisterStep = 0, @@ -21,6 +22,12 @@ enum Steps { SuccessStep = 2, } +interface SubmitErrorData { + statusCode: number + statusText: string + bodyText: string +} + /** * * This component controls the invite process where the sponsor @@ -45,6 +52,7 @@ export default function StepRegistration() { const [activeStep, setActiveStep] = useState(0) const personFormRef = useRef<PersonFormMethods>(null) const [submitState, setSubmitState] = useState(SubmitState.NotSubmitted) + const [errorReport, setErrorReport] = useState<SubmitErrorData>() const handleNext = () => { if (activeStep === 0) { @@ -81,10 +89,18 @@ export default function StepRegistration() { fetch('/api/ui/v1/invite/', submitJsonOpts('POST', payload)) .then((res) => { if (!res.ok) { - setSubmitState(SubmitState.SubmitFailure) - return null + res.text().then((text) => { + setSubmitState(SubmitState.SubmitFailure) + setErrorReport({ + statusCode: res.status, + statusText: res.statusText, + bodyText: text, + }) + }) + } else { + return res.text() } - return res.text() + return null }) .then((result) => { if (result !== null) { @@ -186,12 +202,15 @@ export default function StepRegistration() { {activeStep === Steps.SuccessStep && <StepSubmitSuccess />} - {/* TODO For now just showing a heading to give the user some feedback */} - {submitState === SubmitState.SubmitFailure && ( - <Box> - <h2>Submit failure</h2> - </Box> - )} + {submitState === SubmitState.SubmitFailure && + errorReport !== undefined && ( + <ServerErrorReport + errorHeading={t('error.invitationCreationFailedHeader')} + statusCode={errorReport?.statusCode} + statusText={errorReport?.statusText} + errorBodyText={errorReport?.bodyText} + /> + )} </Page> ) }