diff --git a/apps/portal/src/app/features/licensing/pages/LicenseApplicationPage.tsx b/apps/portal/src/app/features/licensing/pages/LicenseApplicationPage.tsx index b341f1b5e..c459ed2a3 100644 --- a/apps/portal/src/app/features/licensing/pages/LicenseApplicationPage.tsx +++ b/apps/portal/src/app/features/licensing/pages/LicenseApplicationPage.tsx @@ -47,6 +47,7 @@ import { useResubmitApplicationMutation, useSubmitApplicationMutation, type FieldErrors, + type FormFieldConfig, type ValidationIssue, } from '@ema-platform/api'; import { getCountryCode, ModalFooter } from '@ema-platform/ui'; @@ -114,30 +115,53 @@ export function LicenseApplicationPage() { if (detail?.application?.formData) setDraft(detail.application.formData); }, [detail?.application?.id, detail?.application?.adjustmentRound]); - // Nationality is already on file from the profile's Address tab — carry it - // into whichever section the form config puts a `nationality` field in, - // rather than asking again. Only fills a blank; a value already on the - // draft (the applicant's own edit, or one the server saved) is left alone. + // Nationality and National ID (Fayda) number are already on file from the + // profile's Address tab — carry them into whichever section the form + // config puts those fields in, rather than asking again. Only fills a + // blank; a value already on the draft (the applicant's own edit, or one + // the server saved) is left alone. useEffect(() => { - const nationality = profile?.address?.nationality; - if (!nationality || !config) return; - const section = config.licenseType.formSchema.sections.find((s) => - s.fields.some((f) => f.key === 'nationality'), - ); - const field = section?.fields.find((f) => f.key === 'nationality'); - if (!section || !field) return; - // Profile stores the full country name; a SELECT field's options follow the - // CountrySelect convention of alpha-2 codes, so translate for that case. - const value = field.type === 'SELECT' ? (getCountryCode(nationality) ?? nationality) : nationality; - setDraft((prev) => - prev[section.key]?.nationality - ? prev - : { ...prev, [section.key]: { ...prev[section.key], nationality: value } }, - ); + const address = profile?.address; + if (!address || !config) return; + + setDraft((prev) => { + let next = prev; + const fill = ( + matchField: (label: string, key: string) => boolean, + toFieldValue: (field: FormFieldConfig) => unknown, + ) => { + for (const section of config.licenseType.formSchema.sections) { + const field = section.fields.find((f) => matchField(localized(f.label).toLowerCase(), f.key)); + if (!field) continue; + if (next[section.key]?.[field.key]) return; // already set — leave it + next = { ...next, [section.key]: { ...next[section.key], [field.key]: toFieldValue(field) } }; + return; + } + }; + + if (address.nationality) { + // Profile stores the full country name; a SELECT field's options + // follow the CountrySelect convention of alpha-2 codes. + fill( + (label, key) => key === 'nationality' || label.includes('nationality'), + (field) => + field.type === 'SELECT' ? (getCountryCode(address.nationality) ?? address.nationality) : address.nationality, + ); + } + if (address.idType === 'NID' && address.idNumber) { + fill( + (label, key) => + key === 'idNumber' || key === 'nationalId' || key === 'faydaNumber' || + label.includes('fayda') || label.includes('national id'), + () => address.idNumber, + ); + } + return next; + }); // Also re-run after the server seed effect (above) replaces `draft` // wholesale — that effect can resolve after this one, wiping the - // prefill back out since the server's own draft has no nationality yet. - }, [profile?.address?.nationality, config, detail?.application?.id, detail?.application?.formData]); + // prefill back out since the server's own draft has none of this yet. + }, [profile?.address, config, detail?.application?.id, detail?.application?.formData]); const application = detail?.application; const isAdjusting = application?.status === 'RESUBMIT_REQUIRED';