feat: split director residential and postal addresses into structured fields
This commit is contained in:
parent
8f26181514
commit
4c0a256d63
4 changed files with 132 additions and 25 deletions
|
|
@ -115,7 +115,19 @@ export async function POST(
|
|||
inactive_companies: 0,
|
||||
first_seen: new Date().toISOString().slice(0, 10),
|
||||
last_checked: new Date().toISOString().slice(0, 10),
|
||||
notes: `Created from onboarding submission ${submission.reference_no}. Residential: ${d.residential_address}; Postal: ${d.postal_address}; Email: ${d.email}; DOB: ${d.date_of_birth}.`,
|
||||
residential_address_line_1: d.residential_address_line_1?.trim() ?? "",
|
||||
residential_address_line_2: d.residential_address_line_2?.trim() ?? "",
|
||||
residential_town_city: d.residential_town_city?.trim() ?? "",
|
||||
residential_province: d.residential_province?.trim() ?? "",
|
||||
residential_postal_code: d.residential_postal_code?.trim() ?? "",
|
||||
postal_address_line_1: d.postal_address_line_1?.trim() ?? "",
|
||||
postal_address_line_2: d.postal_address_line_2?.trim() ?? "",
|
||||
postal_town_city: d.postal_town_city?.trim() ?? "",
|
||||
postal_province: d.postal_province?.trim() ?? "",
|
||||
postal_postal_code: d.postal_postal_code?.trim() ?? "",
|
||||
email: d.email?.trim() ?? "",
|
||||
date_of_birth: d.date_of_birth ?? "",
|
||||
notes: `Created from onboarding submission ${submission.reference_no}. Email: ${d.email}; DOB: ${d.date_of_birth}.`,
|
||||
});
|
||||
created.push(created_rec.id);
|
||||
} catch (err) {
|
||||
|
|
|
|||
|
|
@ -98,8 +98,14 @@ function validateDirector(d: OnboardingDirectorPayload): string | null {
|
|||
if (!d.surname?.trim()) return "Director surname required";
|
||||
if (!/^\d{13}$/.test(d.id_no ?? "")) return "Director ID must be 13 digits";
|
||||
if (!d.date_of_birth) return "Director date of birth required";
|
||||
if (!d.residential_address?.trim()) return "Director residential address required";
|
||||
if (!d.postal_address?.trim()) return "Director postal address required";
|
||||
if (!d.residential_address_line_1?.trim()) return "Director residential address line 1 required";
|
||||
if (!d.residential_town_city?.trim()) return "Director residential town/city required";
|
||||
if (!d.residential_province?.trim()) return "Director residential province required";
|
||||
if (!d.residential_postal_code?.trim()) return "Director residential postal code required";
|
||||
if (!d.postal_address_line_1?.trim()) return "Director postal address line 1 required";
|
||||
if (!d.postal_town_city?.trim()) return "Director postal town/city required";
|
||||
if (!d.postal_province?.trim()) return "Director postal province required";
|
||||
if (!d.postal_postal_code?.trim()) return "Director postal postal code required";
|
||||
if (!d.email?.trim()) return "Director email required";
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,17 @@ function blankDirector(): OnboardingDirector {
|
|||
id_no: "",
|
||||
date_of_birth: "",
|
||||
residential_address: "",
|
||||
residential_address_line_1: "",
|
||||
residential_address_line_2: "",
|
||||
residential_town_city: "",
|
||||
residential_province: "",
|
||||
residential_postal_code: "",
|
||||
postal_address: "",
|
||||
postal_address_line_1: "",
|
||||
postal_address_line_2: "",
|
||||
postal_town_city: "",
|
||||
postal_province: "",
|
||||
postal_postal_code: "",
|
||||
cell_phone: "",
|
||||
email: ""
|
||||
};
|
||||
|
|
@ -149,8 +159,14 @@ function validateDirector(d: OnboardingDirector): string[] {
|
|||
const idErr = validateIdNo(d.id_no);
|
||||
if (idErr) errs.push(idErr);
|
||||
if (!d.date_of_birth) errs.push("Date of birth required");
|
||||
if (!d.residential_address.trim()) errs.push("Residential address required");
|
||||
if (!d.postal_address.trim()) errs.push("Postal address required");
|
||||
if (!d.residential_address_line_1.trim()) errs.push("Residential address line 1 required");
|
||||
if (!d.residential_town_city.trim()) errs.push("Residential town/city required");
|
||||
if (!d.residential_province.trim()) errs.push("Residential province required");
|
||||
if (!d.residential_postal_code.trim()) errs.push("Residential postal code required");
|
||||
if (!d.postal_address_line_1.trim()) errs.push("Postal address line 1 required");
|
||||
if (!d.postal_town_city.trim()) errs.push("Postal town/city required");
|
||||
if (!d.postal_province.trim()) errs.push("Postal province required");
|
||||
if (!d.postal_postal_code.trim()) errs.push("Postal postal code required");
|
||||
if (!d.cell_phone.trim()) errs.push("Cell phone required");
|
||||
const emailErr = validateEmail(d.email);
|
||||
if (emailErr) errs.push(emailErr);
|
||||
|
|
@ -864,24 +880,75 @@ function DirectorsStep({
|
|||
</Field>
|
||||
</div>
|
||||
|
||||
<Field label="Residential address" required>
|
||||
<textarea
|
||||
className={INPUT_CLS + " min-h-[80px] resize-y"}
|
||||
value={dir.residential_address}
|
||||
onChange={(e) => onUpdate(dir.ui_key, { residential_address: e.target.value })}
|
||||
placeholder="12 Beach Road, Sea Point, Cape Town, 8005"
|
||||
required
|
||||
/>
|
||||
</Field>
|
||||
<Field label="Postal address" required>
|
||||
<textarea
|
||||
className={INPUT_CLS + " min-h-[80px] resize-y"}
|
||||
value={dir.postal_address}
|
||||
onChange={(e) => onUpdate(dir.ui_key, { postal_address: e.target.value })}
|
||||
placeholder="PO Box 1234, Cape Town, 8000"
|
||||
required
|
||||
/>
|
||||
</Field>
|
||||
<div className="space-y-1">
|
||||
<p className="text-xs font-semibold text-muted uppercase tracking-wider">Residential address</p>
|
||||
<Field label="Address line 1" required>
|
||||
<input className={INPUT_CLS} value={dir.residential_address_line_1}
|
||||
onChange={(e) => onUpdate(dir.ui_key, { residential_address_line_1: e.target.value })}
|
||||
placeholder="12 Beach Road" required />
|
||||
</Field>
|
||||
<Field label="Address line 2">
|
||||
<input className={INPUT_CLS} value={dir.residential_address_line_2}
|
||||
onChange={(e) => onUpdate(dir.ui_key, { residential_address_line_2: e.target.value })}
|
||||
placeholder="Sea Point" />
|
||||
</Field>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<Field label="Town / City" required>
|
||||
<input className={INPUT_CLS} value={dir.residential_town_city}
|
||||
onChange={(e) => onUpdate(dir.ui_key, { residential_town_city: e.target.value })}
|
||||
placeholder="Cape Town" required />
|
||||
</Field>
|
||||
<Field label="Province" required>
|
||||
<select className={INPUT_CLS} value={dir.residential_province}
|
||||
onChange={(e) => onUpdate(dir.ui_key, { residential_province: e.target.value })} required>
|
||||
<option value="">Select province</option>
|
||||
{["Eastern Cape","Free State","Gauteng","KwaZulu-Natal","Limpopo","Mpumalanga","Northern Cape","North West","Western Cape"].map(p => (
|
||||
<option key={p} value={p}>{p}</option>
|
||||
))}
|
||||
</select>
|
||||
</Field>
|
||||
</div>
|
||||
<Field label="Postal code" required>
|
||||
<input className={INPUT_CLS} value={dir.residential_postal_code}
|
||||
onChange={(e) => onUpdate(dir.ui_key, { residential_postal_code: e.target.value })}
|
||||
placeholder="8005" required />
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<p className="text-xs font-semibold text-muted uppercase tracking-wider">Postal address <span className="text-muted font-normal normal-case">(leave blank if same as residential)</span></p>
|
||||
<Field label="Address line 1">
|
||||
<input className={INPUT_CLS} value={dir.postal_address_line_1}
|
||||
onChange={(e) => onUpdate(dir.ui_key, { postal_address_line_1: e.target.value })}
|
||||
placeholder="PO Box 1234" />
|
||||
</Field>
|
||||
<Field label="Address line 2">
|
||||
<input className={INPUT_CLS} value={dir.postal_address_line_2}
|
||||
onChange={(e) => onUpdate(dir.ui_key, { postal_address_line_2: e.target.value })}
|
||||
placeholder="Cape Town" />
|
||||
</Field>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<Field label="Town / City">
|
||||
<input className={INPUT_CLS} value={dir.postal_town_city}
|
||||
onChange={(e) => onUpdate(dir.ui_key, { postal_town_city: e.target.value })}
|
||||
placeholder="Cape Town" />
|
||||
</Field>
|
||||
<Field label="Province">
|
||||
<select className={INPUT_CLS} value={dir.postal_province}
|
||||
onChange={(e) => onUpdate(dir.ui_key, { postal_province: e.target.value })}>
|
||||
<option value="">Select province</option>
|
||||
{["Eastern Cape","Free State","Gauteng","KwaZulu-Natal","Limpopo","Mpumalanga","Northern Cape","North West","Western Cape"].map(p => (
|
||||
<option key={p} value={p}>{p}</option>
|
||||
))}
|
||||
</select>
|
||||
</Field>
|
||||
</div>
|
||||
<Field label="Postal code">
|
||||
<input className={INPUT_CLS} value={dir.postal_postal_code}
|
||||
onChange={(e) => onUpdate(dir.ui_key, { postal_postal_code: e.target.value })}
|
||||
placeholder="8000" />
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
<DocUploadBlock
|
||||
directorKey={dir.ui_key}
|
||||
|
|
@ -1217,8 +1284,20 @@ function ReviewStep({
|
|||
<SummaryRow label="Date of birth" value={d.date_of_birth || "—"} />
|
||||
<SummaryRow label="Cell phone" value={d.cell_phone || "—"} />
|
||||
<SummaryRow label="Email" value={d.email || "—"} />
|
||||
<SummaryRow label="Residential" value={d.residential_address || "—"} />
|
||||
<SummaryRow label="Postal" value={d.postal_address || "—"} />
|
||||
<SummaryRow label="Residential address" value={[
|
||||
d.residential_address_line_1,
|
||||
d.residential_address_line_2,
|
||||
d.residential_town_city,
|
||||
d.residential_province,
|
||||
d.residential_postal_code,
|
||||
].filter(Boolean).join(", ") || "—"} />
|
||||
<SummaryRow label="Postal address" value={[
|
||||
d.postal_address_line_1,
|
||||
d.postal_address_line_2,
|
||||
d.postal_town_city,
|
||||
d.postal_province,
|
||||
d.postal_postal_code,
|
||||
].filter(Boolean).join(", ") || "—"} />
|
||||
<SummaryRow
|
||||
label="ID document"
|
||||
value={docs.some((doc) => doc.directorKey === d.ui_key && doc.kind === "id") ? "Uploaded" : "Missing"}
|
||||
|
|
|
|||
10
lib/types.ts
10
lib/types.ts
|
|
@ -141,7 +141,17 @@ export interface OnboardingDirector {
|
|||
id_no: string;
|
||||
date_of_birth: string; // YYYY-MM-DD
|
||||
residential_address: string;
|
||||
residential_address_line_1: string;
|
||||
residential_address_line_2: string;
|
||||
residential_town_city: string;
|
||||
residential_province: string;
|
||||
residential_postal_code: string;
|
||||
postal_address: string;
|
||||
postal_address_line_1: string;
|
||||
postal_address_line_2: string;
|
||||
postal_town_city: string;
|
||||
postal_province: string;
|
||||
postal_postal_code: string;
|
||||
cell_phone: string;
|
||||
email: string;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue