diff --git a/src/components/App.stories.jsx b/src/components/App.stories.jsx index d2f33b0cd..19ca4c49b 100644 --- a/src/components/App.stories.jsx +++ b/src/components/App.stories.jsx @@ -113,6 +113,7 @@ const render = args => { explanationTemplate: '

Toelichtingssjabloon...

', submissionAllowed: args['submissionAllowed'], hideNonApplicableSteps: args['hideNonApplicableSteps'], + submissionLimitReached: args['form.submissionLimitReached'], steps: args['steps'], }); return ; @@ -409,3 +410,19 @@ export const SeveralStepsInMobileViewport = { }, }, }; + +export const MaximumSubmissionsReached = { + render, + decorators: [LayoutDecorator], + args: { + 'form.submissionLimitReached': true, + }, +}; + +export const MaximumSubmissionsNotReached = { + render, + decorators: [LayoutDecorator], + args: { + 'form.submissionLimitReached': false, + }, +}; diff --git a/src/components/Errors/ErrorBoundary.jsx b/src/components/Errors/ErrorBoundary.jsx index db66a834d..ef6309ce7 100644 --- a/src/components/Errors/ErrorBoundary.jsx +++ b/src/components/Errors/ErrorBoundary.jsx @@ -4,6 +4,7 @@ import {FormattedMessage, useIntl} from 'react-intl'; import Body from 'components/Body'; import Card from 'components/Card'; +import FormMaximumSubmissions from 'components/FormMaximumSubmissions'; import Link from 'components/Link'; import MaintenanceMode from 'components/MaintenanceMode'; import {PermissionDenied, ServiceUnavailable, UnprocessableEntity} from 'errors'; @@ -138,21 +139,28 @@ const UnprocessableEntityError = ({wrapper: Wrapper, error}) => { UnprocessableEntityError.propTypes = GenericError.propTypes; const ServiceUnavailableError = ({wrapper: Wrapper, error}) => { - if (error.code !== 'form-maintenance') { + if (!['form-maintenance', 'form-maximum-submissions'].includes(error.code)) { return ; } // handle maintenance mode forms - return ( - - } - /> - ); + if (error.code === 'form-maintenance') { + return ( + + } + /> + ); + } + + // handle submission limit forms + if (error.code === 'form-maximum-submissions') { + return ; + } }; // map the error class to the component to render it diff --git a/src/components/FormMaximumSubmissions.jsx b/src/components/FormMaximumSubmissions.jsx new file mode 100644 index 000000000..5e7bd70da --- /dev/null +++ b/src/components/FormMaximumSubmissions.jsx @@ -0,0 +1,17 @@ +import React from 'react'; +import {FormattedMessage} from 'react-intl'; + +import ErrorMessage from 'components/Errors/ErrorMessage'; + +const FormMaximumSubmissions = () => { + return ( + + + + ); +}; + +export default FormMaximumSubmissions; diff --git a/src/components/FormStart/index.jsx b/src/components/FormStart/index.jsx index d0713c563..d2c42eca4 100644 --- a/src/components/FormStart/index.jsx +++ b/src/components/FormStart/index.jsx @@ -6,6 +6,7 @@ import {useAsync} from 'react-use'; import Body from 'components/Body'; import Card from 'components/Card'; import ExistingSubmissionOptions from 'components/ExistingSubmissionOptions'; +import FormMaximumSubmissions from 'components/FormMaximumSubmissions'; import {LiteralsProvider} from 'components/Literal'; import Loader from 'components/Loader'; import LoginOptions from 'components/LoginOptions'; @@ -112,6 +113,7 @@ const FormStart = ({form, submission, onFormStart, onDestroySession, initialData return ( + {form.submissionLimitReached ? : null} {userIsFormDesigner && form.maintenanceMode && } {!!authErrors ? : null} diff --git a/src/i18n/compiled/en.json b/src/i18n/compiled/en.json index 9e339b390..57369b270 100644 --- a/src/i18n/compiled/en.json +++ b/src/i18n/compiled/en.json @@ -2127,6 +2127,12 @@ "value": "Abort submission" } ], + "uPtko4": [ + { + "type": 0, + "value": "Unfortunately, this form is no longer available for submissions." + } + ], "uZBPwA": [ { "type": 0, diff --git a/src/i18n/compiled/nl.json b/src/i18n/compiled/nl.json index 627ec0d88..d1b913dc1 100644 --- a/src/i18n/compiled/nl.json +++ b/src/i18n/compiled/nl.json @@ -2131,6 +2131,12 @@ "value": "Afbreken" } ], + "uPtko4": [ + { + "type": 0, + "value": "Unfortunately, this form is no longer available for submissions." + } + ], "uZBPwA": [ { "type": 0, diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 357439cf0..f45c3e209 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -1009,6 +1009,11 @@ "description": "Button label to abort submission", "originalDefault": "Abort submission" }, + "uPtko4": { + "defaultMessage": "Unfortunately, this form is no longer available for submissions.", + "description": "Maximum form submissions error message", + "originalDefault": "Unfortunately, this form is no longer available for submissions." + }, "uZBPwA": { "defaultMessage": "Number must be {exact, select, true {exactly equal to} other {{inclusive, select, true {less than or equal to} other {less than}}} } {maximum}.", "description": "ZOD 'too_big' error message, for numbers", diff --git a/src/i18n/messages/nl.json b/src/i18n/messages/nl.json index ba1fddba7..afafa0561 100644 --- a/src/i18n/messages/nl.json +++ b/src/i18n/messages/nl.json @@ -1021,6 +1021,11 @@ "description": "Button label to abort submission", "originalDefault": "Abort submission" }, + "uPtko4": { + "defaultMessage": "Unfortunately, this form is no longer available for submissions.", + "description": "Maximum form submissions error message", + "originalDefault": "Unfortunately, this form is no longer available for submissions." + }, "uZBPwA": { "defaultMessage": "Het getal moet {exact, select, true {exact gelijk aan} other {{inclusive, select, true {minder dan of gelijk aan} other {minder dan}}} } {maximum} zijn.", "description": "ZOD 'too_big' error message, for numbers",