diff --git a/shared-helpers/src/locales/ar.json b/shared-helpers/src/locales/ar.json index 1d0c36a483..827c56b2aa 100644 --- a/shared-helpers/src/locales/ar.json +++ b/shared-helpers/src/locales/ar.json @@ -574,6 +574,7 @@ "listings.annualIncome": "٪ {الدخل} في السنة", "listings.annualIncomeRange": "٪ {from} إلى٪ {to} سنويًا", "listings.applicationAddress": "تبوك", + "listings.applicationAlreadySubmitted": "لقد تم تقديم هذا الطلب بالفعل.", "listings.applicationDeadline": "تاريخ استحقاق الطلب", "listings.applicationDropOffQuestion": "هل يمكن إسقاط الطلبات؟", "listings.applicationDueTime": "وقت التقديم", diff --git a/shared-helpers/src/locales/bn.json b/shared-helpers/src/locales/bn.json index 55c5161842..342abbf526 100644 --- a/shared-helpers/src/locales/bn.json +++ b/shared-helpers/src/locales/bn.json @@ -570,6 +570,7 @@ "listings.annualIncome": "%{আয়} প্রতি বছর", "listings.annualIncomeRange": "%{থেকে} থেকে %{থেকে} প্রতি বছর", "listings.applicationAddress": "ঠিকানা", + "listings.applicationAlreadySubmitted": "এই আবেদনটি ইতিমধ্যেই জমা দেওয়া হয়েছে।", "listings.applicationDeadline": "আবেদনের শেষ তারিখ", "listings.applicationDropOffQuestion": "আবেদন কি বাদ দেওয়া যাবে?", "listings.applicationDueTime": "আবেদনের নির্ধারিত সময়", diff --git a/shared-helpers/src/locales/es.json b/shared-helpers/src/locales/es.json index 731808e2a1..18b30e40c9 100644 --- a/shared-helpers/src/locales/es.json +++ b/shared-helpers/src/locales/es.json @@ -579,6 +579,7 @@ "listings.allUnits": "Todas las viviendas", "listings.allUnitsReservedFor": "Todas las viviendas reservadas para %{type}", "listings.annualIncome": "%{income} al año", + "listings.applicationAlreadySubmitted": "Ya ha enviado una solicitud para este listado.", "listings.applicationDeadline": "Fecha límite de solicitud", "listings.applicationFCFS": "Atención por orden de llegada", "listings.applicationFee": "Cargo de solicitud", @@ -587,7 +588,7 @@ "listings.applicationPerApplicantAgeDescription": "por solicitante de 18 años o más", "listings.applications": "Solicitudes", "listings.applicationsClosed": "Solicitudes cerradas", - "listings.applicationsClosedRedirect": "Esta lista ya no acepta solicitudes.", + "listings.applicationsClosedRedirect": "Esta solicitud ya ha sido enviada.", "listings.apply.applicationWillBeAvailableOn": "La solicitud podrá ser descargada y recogida el %{openDate}", "listings.apply.applyOnline": "Haga su solicitud por Internet", "listings.apply.downloadApplication": "Descargar la Solicitud", diff --git a/shared-helpers/src/locales/general.json b/shared-helpers/src/locales/general.json index 0823359cac..51242eb970 100644 --- a/shared-helpers/src/locales/general.json +++ b/shared-helpers/src/locales/general.json @@ -570,6 +570,7 @@ "listings.allUnits": "All Units", "listings.allUnitsReservedFor": "All units reserved for %{type}", "listings.annualIncome": "%{income} per year", + "listings.applicationAlreadySubmitted": "This application has already been submitted.", "listings.applicationDeadline": "Application Due Date", "listings.applicationFCFS": "First Come First Serve", "listings.applicationFee": "Application Fee", diff --git a/shared-helpers/src/locales/tl.json b/shared-helpers/src/locales/tl.json index a507ab6779..c31c0f49e1 100644 --- a/shared-helpers/src/locales/tl.json +++ b/shared-helpers/src/locales/tl.json @@ -574,6 +574,7 @@ "listings.allUnits": "Lahat ng Unit", "listings.allUnitsReservedFor": "Ang lahat ng unit ay nakareserba para sa %{type}", "listings.annualIncome": "%{income} kada taon", + "listings.applicationAlreadySubmitted": "Nagsumite ka na ng aplikasyon para sa listahang ito.", "listings.applicationDeadline": "Due Date ng Application", "listings.applicationFCFS": "Kung Sino Ang Mauna Ay Siyang Makakakuha", "listings.applicationFee": "Bayad sa Application", @@ -582,7 +583,7 @@ "listings.applicationPerApplicantAgeDescription": "bawat aplikante na edad 18 at mas matanda", "listings.applications": "Mga Application", "listings.applicationsClosed": "Mga Isinarang Application", - "listings.applicationsClosedRedirect": "Ang listahang ito ay hindi na tumatanggap ng mga aplikasyon.", + "listings.applicationsClosedRedirect": "Naisumite na ang application na ito.", "listings.apply.applicationWillBeAvailableOn": "Magiging available ang application para i-download at kunin sa %{openDate}", "listings.apply.applyOnline": "Mag-apply Online", "listings.apply.downloadApplication": "I-download ang Application", diff --git a/shared-helpers/src/locales/vi.json b/shared-helpers/src/locales/vi.json index 982e2dc633..89eeefdbf3 100644 --- a/shared-helpers/src/locales/vi.json +++ b/shared-helpers/src/locales/vi.json @@ -575,6 +575,7 @@ "listings.allUnits": "Tất cả các Căn nhà", "listings.allUnitsReservedFor": "Tất cả các căn nhà được dành cho %{type}", "listings.annualIncome": "%{income} mỗi năm", + "listings.applicationAlreadySubmitted": "Bạn đã nộp đơn đăng ký cho danh sách này.", "listings.applicationDeadline": "Hạn nộp Đơn ghi danh", "listings.applicationFCFS": "Ai Nộp đơn Trước Được Nhận trước", "listings.applicationFee": "Lệ phí Ghi danh", @@ -583,7 +584,7 @@ "listings.applicationPerApplicantAgeDescription": "mỗi ứng viên từ 18 tuổi trở lên", "listings.applications": "Đơn đăng ký", "listings.applicationsClosed": "Ngừng nhận Đơn ghi danh", - "listings.applicationsClosedRedirect": "Danh sách này không còn chấp nhận các ứng dụng.", + "listings.applicationsClosedRedirect": "Đơn này đã được nộp rồi.", "listings.apply.applicationWillBeAvailableOn": "Đơn ghi danh sẽ có sẵn để tải xuống và tới nhận vào %{openDate}", "listings.apply.applyOnline": "Ghi danh Trực tuyến", "listings.apply.downloadApplication": "Tải xuống Đơn ghi danh", diff --git a/shared-helpers/src/locales/zh.json b/shared-helpers/src/locales/zh.json index a8415e8611..4d02420025 100644 --- a/shared-helpers/src/locales/zh.json +++ b/shared-helpers/src/locales/zh.json @@ -575,6 +575,7 @@ "listings.allUnits": "所有單位", "listings.allUnitsReservedFor": "保留給 %{type} 的所有單位", "listings.annualIncome": "每年 %{income}", + "listings.applicationAlreadySubmitted": "您已經提交了此清單的申請。", "listings.applicationDeadline": "申請截止日期", "listings.applicationFCFS": "先申請先服務", "listings.applicationFee": "申請費", @@ -583,7 +584,7 @@ "listings.applicationPerApplicantAgeDescription": "每位年滿 18 歲的申請人", "listings.applications": "申請", "listings.applicationsClosed": "申請期限已經結束", - "listings.applicationsClosedRedirect": "此房源不再接受申请。", + "listings.applicationsClosedRedirect": "此申請已經提交。", "listings.apply.applicationWillBeAvailableOn": "申請表將可供下載,亦可在 %{openDate} 領取", "listings.apply.applyOnline": "線上申請", "listings.apply.downloadApplication": "下載申請表", diff --git a/sites/public/src/pages/applications/review/terms.tsx b/sites/public/src/pages/applications/review/terms.tsx index 9f4d2e8c7f..a7330c800c 100644 --- a/sites/public/src/pages/applications/review/terms.tsx +++ b/sites/public/src/pages/applications/review/terms.tsx @@ -10,6 +10,7 @@ import { pushGtmEvent, AuthContext, listingSectionQuestions, + useToastyRef, } from "@bloom-housing/shared-helpers" import FormsLayout from "../../../layouts/forms" import { useFormConductor } from "../../../lib/hooks" @@ -27,6 +28,7 @@ const ApplicationTerms = () => { const router = useRouter() const { conductor, application, listing } = useFormConductor("terms") const { applicationsService, profile } = useContext(AuthContext) + const toastyRef = useToastyRef() const [apiError, setApiError] = useState(false) const [submitting, setSubmitting] = useState(false) @@ -42,47 +44,50 @@ const ApplicationTerms = () => { // eslint-disable-next-line @typescript-eslint/unbound-method const { register, handleSubmit, errors } = useForm() const onSubmit = (data) => { - setSubmitting(true) - const acceptedTerms = data.agree === "agree" - conductor.currentStep.save({ acceptedTerms }) - application.acceptedTerms = acceptedTerms - application.completedSections = 6 + // blocks multiple clicks and previously submitted applications + if (!submitting && !application.confirmationCode) { + setSubmitting(true) + const acceptedTerms = data.agree === "agree" + conductor.currentStep.save({ acceptedTerms }) + application.acceptedTerms = acceptedTerms + application.completedSections = 6 - if (application?.programs?.length) { - untranslateMultiselectQuestion(application.programs, listing) - } - if (application?.preferences?.length) { - untranslateMultiselectQuestion(application.preferences, listing) - } + if (application?.programs?.length) { + untranslateMultiselectQuestion(application.programs, listing) + } + if (application?.preferences?.length) { + untranslateMultiselectQuestion(application.preferences, listing) + } - applicationsService - .submit({ - body: { - ...application, - reviewStatus: ApplicationReviewStatusEnum.pending, - listings: { - id: listing.id, - }, - appUrl: window.location.origin, - ...(profile && { - user: { - id: profile.id, + applicationsService + .submit({ + body: { + ...application, + reviewStatus: ApplicationReviewStatusEnum.pending, + listings: { + id: listing.id, }, - }), - // TODO remove this once this call is changed to the new backend - }, - }) - .then((result) => { - conductor.currentStep.save({ confirmationCode: result.confirmationCode }) - return router.push("/applications/review/confirmation") - }) - .catch((err) => { - setSubmitting(false) - setApiError(true) - window.scrollTo(0, 0) - console.error(`Error creating application: ${err}`) - throw err - }) + appUrl: window.location.origin, + ...(profile && { + user: { + id: profile.id, + }, + }), + // TODO remove this once this call is changed to the new backend + }, + }) + .then((result) => { + conductor.currentStep.save({ confirmationCode: result.confirmationCode }) + return router.push("/applications/review/confirmation") + }) + .catch((err) => { + setSubmitting(false) + setApiError(true) + window.scrollTo(0, 0) + console.error(`Error creating application: ${err}`) + throw err + }) + } } const agreeField = [ @@ -111,6 +116,16 @@ const ApplicationTerms = () => { } }, [listing]) + useEffect(() => { + if (application.confirmationCode && router.isReady) { + const { addToast } = toastyRef.current + addToast(t("listings.applicationAlreadySubmitted"), { variant: "alert" }) + profile + ? void router.push(`/${router.locale}/account/applications`) + : void router.push(`/${router.locale}/listing/${listing.id}/${listing.urlSlug}`) + } + }, [application, listing, profile, router, toastyRef]) + useEffect(() => { pushGtmEvent({ event: "pageView",