Add onboarding form fields to companies + directors (visual + editable)
PB: 15 fields on ysterbaard_companies (financial_year_end_month, authorised_shares, structured physical/postal address, company_cell_phone, public_officer_name, company_secretary_name), 11 fields on ysterbaard_directors (date_of_birth, structured residential/postal address). App: types widened in lib/types.ts. EditEntityModal rebuilt with full address sections (line 1, line 2, town/city, SA province dropdown, postal code), DOB, company-level fields, financial year end month, authorised shares, public officer, company secretary. View pages: structured address blocks now show labeled fields (line 1, line 2, town/city, province, postal code) on both /companies/[id] and /directors/[id].
This commit is contained in:
parent
4066c1c43c
commit
9bd35898a2
4 changed files with 577 additions and 6 deletions
|
|
@ -250,17 +250,98 @@ export default async function CompanyDetailPage({ params }: Props) {
|
|||
<section data-od-id="company-addresses" className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="bg-surface border border-border rounded-lg p-6">
|
||||
<h2 className="text-lg font-semibold text-fg mb-3">Physical address</h2>
|
||||
<p className="text-sm text-fg-2 whitespace-pre-line break-words leading-relaxed">{text(company.physical_address)}</p>
|
||||
{company.physical_address ? (
|
||||
<p className="text-sm text-fg-2 whitespace-pre-line break-words leading-relaxed">{text(company.physical_address)}</p>
|
||||
) : null}
|
||||
<div className="mt-3 grid grid-cols-1 gap-px bg-border border border-border-soft rounded-md overflow-hidden">
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Address line 1</p>
|
||||
<p className="text-sm text-fg">{text(company.physical_address_line_1)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Address line 2</p>
|
||||
<p className="text-sm text-fg">{text(company.physical_address_line_2)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Town / city</p>
|
||||
<p className="text-sm text-fg">{text(company.physical_town_city)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Province</p>
|
||||
<p className="text-sm text-fg">{text(company.physical_province)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Postal code</p>
|
||||
<p className="text-sm text-fg font-mono">{text(company.physical_postal_code)}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-surface border border-border rounded-lg p-6">
|
||||
<h2 className="text-lg font-semibold text-fg mb-3">Postal address</h2>
|
||||
<p className="text-sm text-fg-2 whitespace-pre-line break-words leading-relaxed">{text(company.postal_address)}</p>
|
||||
{company.postal_address ? (
|
||||
<p className="text-sm text-fg-2 whitespace-pre-line break-words leading-relaxed">{text(company.postal_address)}</p>
|
||||
) : null}
|
||||
<div className="mt-3 grid grid-cols-1 gap-px bg-border border border-border-soft rounded-md overflow-hidden">
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Address line 1</p>
|
||||
<p className="text-sm text-fg">{text(company.postal_address_line_1)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Address line 2</p>
|
||||
<p className="text-sm text-fg">{text(company.postal_address_line_2)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Town / city</p>
|
||||
<p className="text-sm text-fg">{text(company.postal_town_city)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Province</p>
|
||||
<p className="text-sm text-fg">{text(company.postal_province)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Postal code</p>
|
||||
<p className="text-sm text-fg font-mono">{text(company.postal_postal_code)}</p>
|
||||
</div>
|
||||
</div>
|
||||
{company.company_email ? (
|
||||
<div className="mt-3 pt-3 border-t border-border-soft">
|
||||
<p className="text-xs uppercase tracking-[0.08em] text-muted font-semibold mb-1">Email</p>
|
||||
<a href={`mailto:${company.company_email}`} className="text-sm text-accent hover:underline">{text(company.company_email)}</a>
|
||||
</div>
|
||||
) : null}
|
||||
{company.company_cell_phone ? (
|
||||
<div className="mt-3 pt-3 border-t border-border-soft">
|
||||
<p className="text-xs uppercase tracking-[0.08em] text-muted font-semibold mb-1">Cell phone</p>
|
||||
<p className="text-sm text-fg-2">{text(company.company_cell_phone)}</p>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Company details (added 2026-08-18) */}
|
||||
<section data-od-id="company-details" className="bg-surface border border-border rounded-lg p-6 md:p-8">
|
||||
<h2 className="text-xl font-semibold text-fg mb-4">Company details</h2>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-px bg-border border border-border rounded-md overflow-hidden">
|
||||
<div className="bg-surface p-4">
|
||||
<p className="text-xs text-muted font-semibold mb-1">Public officer</p>
|
||||
<p className="text-sm text-fg">{text(company.public_officer_name)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-4">
|
||||
<p className="text-xs text-muted font-semibold mb-1">Company secretary</p>
|
||||
<p className="text-sm text-fg">{text(company.company_secretary_name)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-4">
|
||||
<p className="text-xs text-muted font-semibold mb-1">Financial year end</p>
|
||||
<p className="text-sm text-fg">
|
||||
{company.financial_year_end_month
|
||||
? new Date(2000, company.financial_year_end_month - 1, 1).toLocaleString("en", { month: "long" })
|
||||
: "—"}
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-surface p-4">
|
||||
<p className="text-xs text-muted font-semibold mb-1">Authorised shares</p>
|
||||
<p className="text-sm text-fg font-mono">{company.authorised_shares ? company.authorised_shares.toLocaleString() : "—"}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
|
|||
|
|
@ -142,6 +142,15 @@ export default async function DirectorDetailPage({ params }: Props) {
|
|||
) : null}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-xs uppercase tracking-[0.08em] text-muted font-semibold mb-1">
|
||||
Date of birth
|
||||
</p>
|
||||
<p className="text-base text-fg">
|
||||
{formatDate(director.date_of_birth)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-xs uppercase tracking-[0.08em] text-muted font-semibold mb-1">
|
||||
Telephone
|
||||
|
|
@ -151,6 +160,19 @@ export default async function DirectorDetailPage({ params }: Props) {
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-xs uppercase tracking-[0.08em] text-muted font-semibold mb-1">
|
||||
Email
|
||||
</p>
|
||||
<p className="text-base text-fg">
|
||||
{director.email ? (
|
||||
<a href={`mailto:${director.email}`} className="text-accent hover:underline">{text(director.email)}</a>
|
||||
) : (
|
||||
<span className="text-muted">—</span>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-xs uppercase tracking-[0.08em] text-muted font-semibold mb-1">
|
||||
First seen
|
||||
|
|
@ -170,6 +192,70 @@ export default async function DirectorDetailPage({ params }: Props) {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* Addresses (added 2026-08-18) */}
|
||||
<div className="border-t border-border-soft pt-6 flex flex-col gap-4">
|
||||
<div>
|
||||
<p className="text-xs uppercase tracking-[0.08em] text-muted font-semibold mb-2">
|
||||
Residential address
|
||||
</p>
|
||||
{director.residential_address ? (
|
||||
<p className="text-sm text-fg-2 whitespace-pre-line break-words leading-relaxed mb-2">{text(director.residential_address)}</p>
|
||||
) : null}
|
||||
<div className="grid grid-cols-1 gap-px bg-border border border-border-soft rounded-md overflow-hidden">
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Address line 1</p>
|
||||
<p className="text-sm text-fg">{text(director.residential_address_line_1)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Address line 2</p>
|
||||
<p className="text-sm text-fg">{text(director.residential_address_line_2)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Town / city</p>
|
||||
<p className="text-sm text-fg">{text(director.residential_town_city)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Province</p>
|
||||
<p className="text-sm text-fg">{text(director.residential_province)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Postal code</p>
|
||||
<p className="text-sm text-fg font-mono">{text(director.residential_postal_code)}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs uppercase tracking-[0.08em] text-muted font-semibold mb-2">
|
||||
Postal address
|
||||
</p>
|
||||
{director.postal_address ? (
|
||||
<p className="text-sm text-fg-2 whitespace-pre-line break-words leading-relaxed mb-2">{text(director.postal_address)}</p>
|
||||
) : null}
|
||||
<div className="grid grid-cols-1 gap-px bg-border border border-border-soft rounded-md overflow-hidden">
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Address line 1</p>
|
||||
<p className="text-sm text-fg">{text(director.postal_address_line_1)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Address line 2</p>
|
||||
<p className="text-sm text-fg">{text(director.postal_address_line_2)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Town / city</p>
|
||||
<p className="text-sm text-fg">{text(director.postal_town_city)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Province</p>
|
||||
<p className="text-sm text-fg">{text(director.postal_province)}</p>
|
||||
</div>
|
||||
<div className="bg-surface p-3">
|
||||
<p className="text-xs text-muted font-semibold mb-0.5">Postal code</p>
|
||||
<p className="text-sm text-fg font-mono">{text(director.postal_postal_code)}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-border-soft pt-6 grid grid-cols-3 gap-3">
|
||||
<div>
|
||||
<p className="text-3xl font-bold text-fg tabular-nums leading-none">
|
||||
|
|
|
|||
|
|
@ -19,6 +19,19 @@ interface Director {
|
|||
postal_address?: string | null;
|
||||
director_type?: string | null;
|
||||
notes?: string | null;
|
||||
// ─── Structured address fields (added 2026-08-18) ───
|
||||
residential_address?: string | null;
|
||||
residential_address_line_1?: string | null;
|
||||
residential_address_line_2?: string | null;
|
||||
residential_town_city?: string | null;
|
||||
residential_province?: string | null;
|
||||
residential_postal_code?: string | null;
|
||||
postal_address_line_1?: string | null;
|
||||
postal_address_line_2?: string | null;
|
||||
postal_town_city?: string | null;
|
||||
postal_province?: string | null;
|
||||
postal_postal_code?: string | null;
|
||||
date_of_birth?: string | null;
|
||||
}
|
||||
|
||||
interface Company {
|
||||
|
|
@ -40,6 +53,23 @@ interface Company {
|
|||
sars_vat_returns_period?: number | null;
|
||||
sars_paye_return_period?: number | null;
|
||||
groups?: string[] | null;
|
||||
// ─── Structured address fields (added 2026-08-18) ───
|
||||
physical_address_line_1?: string | null;
|
||||
physical_address_line_2?: string | null;
|
||||
physical_town_city?: string | null;
|
||||
physical_province?: string | null;
|
||||
physical_postal_code?: string | null;
|
||||
postal_address_line_1?: string | null;
|
||||
postal_address_line_2?: string | null;
|
||||
postal_town_city?: string | null;
|
||||
postal_province?: string | null;
|
||||
postal_postal_code?: string | null;
|
||||
// ─── Company-level fields (added 2026-08-18) ───
|
||||
financial_year_end_month?: number | null;
|
||||
authorised_shares?: number | null;
|
||||
company_cell_phone?: string | null;
|
||||
public_officer_name?: string | null;
|
||||
company_secretary_name?: string | null;
|
||||
}
|
||||
|
||||
interface GroupOption {
|
||||
|
|
@ -48,6 +78,18 @@ interface GroupOption {
|
|||
description?: string | null;
|
||||
}
|
||||
|
||||
const SA_PROVINCES = [
|
||||
"Eastern Cape",
|
||||
"Free State",
|
||||
"Gauteng",
|
||||
"KwaZulu-Natal",
|
||||
"Limpopo",
|
||||
"Mpumalanga",
|
||||
"Northern Cape",
|
||||
"North West",
|
||||
"Western Cape",
|
||||
];
|
||||
|
||||
interface Props {
|
||||
entity: "director" | "company";
|
||||
/** Original record data for pre-filling the form */
|
||||
|
|
@ -72,6 +114,18 @@ export default function EditEntityModal({ entity, record, open, onClose, onAfter
|
|||
const [postalAddress, setPostalAddress] = useState("");
|
||||
const [directorType, setDirectorType] = useState("");
|
||||
const [notes, setNotes] = useState("");
|
||||
// Director structured address fields (added 2026-08-18)
|
||||
const [dateOfBirth, setDateOfBirth] = useState("");
|
||||
const [resAddr1, setResAddr1] = useState("");
|
||||
const [resAddr2, setResAddr2] = useState("");
|
||||
const [resTown, setResTown] = useState("");
|
||||
const [resProvince, setResProvince] = useState("");
|
||||
const [resPostalCode, setResPostalCode] = useState("");
|
||||
const [postAddr1, setPostAddr1] = useState("");
|
||||
const [postAddr2, setPostAddr2] = useState("");
|
||||
const [postTown, setPostTown] = useState("");
|
||||
const [postProvince, setPostProvince] = useState("");
|
||||
const [postPostalCode, setPostPostalCode] = useState("");
|
||||
|
||||
// Company fields
|
||||
const [enterpriseNo, setEnterpriseNo] = useState("");
|
||||
|
|
@ -82,6 +136,23 @@ export default function EditEntityModal({ entity, record, open, onClose, onAfter
|
|||
const [postalAddressCo, setPostalAddressCo] = useState("");
|
||||
const [companyEmail, setCompanyEmail] = useState("");
|
||||
const [notesCo, setNotesCo] = useState("");
|
||||
// Company structured address fields (added 2026-08-18)
|
||||
const [physAddr1, setPhysAddr1] = useState("");
|
||||
const [physAddr2, setPhysAddr2] = useState("");
|
||||
const [physTown, setPhysTown] = useState("");
|
||||
const [physProvince, setPhysProvince] = useState("");
|
||||
const [physPostalCode, setPhysPostalCode] = useState("");
|
||||
const [postCoAddr1, setPostCoAddr1] = useState("");
|
||||
const [postCoAddr2, setPostCoAddr2] = useState("");
|
||||
const [postCoTown, setPostCoTown] = useState("");
|
||||
const [postCoProvince, setPostCoProvince] = useState("");
|
||||
const [postCoPostalCode, setPostCoPostalCode] = useState("");
|
||||
// Company-level fields (added 2026-08-18)
|
||||
const [financialYearEndMonth, setFinancialYearEndMonth] = useState("");
|
||||
const [authorisedShares, setAuthorisedShares] = useState("");
|
||||
const [companyCellPhone, setCompanyCellPhone] = useState("");
|
||||
const [publicOfficerName, setPublicOfficerName] = useState("");
|
||||
const [companySecretaryName, setCompanySecretaryName] = useState("");
|
||||
// SARS fields
|
||||
const [sarsLoginUsername, setSarsLoginUsername] = useState("");
|
||||
const [sarsLoginPassword, setSarsLoginPassword] = useState("");
|
||||
|
|
@ -110,6 +181,17 @@ export default function EditEntityModal({ entity, record, open, onClose, onAfter
|
|||
setPostalAddress(d.postal_address ?? "");
|
||||
setDirectorType(d.director_type ?? "");
|
||||
setNotes(d.notes ?? "");
|
||||
setDateOfBirth(d.date_of_birth ?? "");
|
||||
setResAddr1(d.residential_address_line_1 ?? "");
|
||||
setResAddr2(d.residential_address_line_2 ?? "");
|
||||
setResTown(d.residential_town_city ?? "");
|
||||
setResProvince(d.residential_province ?? "");
|
||||
setResPostalCode(d.residential_postal_code ?? "");
|
||||
setPostAddr1(d.postal_address_line_1 ?? "");
|
||||
setPostAddr2(d.postal_address_line_2 ?? "");
|
||||
setPostTown(d.postal_town_city ?? "");
|
||||
setPostProvince(d.postal_province ?? "");
|
||||
setPostPostalCode(d.postal_postal_code ?? "");
|
||||
} else {
|
||||
const c = record as Company;
|
||||
setEnterpriseNo(c.enterprise_no ?? "");
|
||||
|
|
@ -120,6 +202,21 @@ export default function EditEntityModal({ entity, record, open, onClose, onAfter
|
|||
setPostalAddressCo(c.postal_address ?? "");
|
||||
setCompanyEmail(c.company_email ?? "");
|
||||
setNotesCo(c.notes ?? "");
|
||||
setPhysAddr1(c.physical_address_line_1 ?? "");
|
||||
setPhysAddr2(c.physical_address_line_2 ?? "");
|
||||
setPhysTown(c.physical_town_city ?? "");
|
||||
setPhysProvince(c.physical_province ?? "");
|
||||
setPhysPostalCode(c.physical_postal_code ?? "");
|
||||
setPostCoAddr1(c.postal_address_line_1 ?? "");
|
||||
setPostCoAddr2(c.postal_address_line_2 ?? "");
|
||||
setPostCoTown(c.postal_town_city ?? "");
|
||||
setPostCoProvince(c.postal_province ?? "");
|
||||
setPostCoPostalCode(c.postal_postal_code ?? "");
|
||||
setFinancialYearEndMonth(c.financial_year_end_month != null ? String(c.financial_year_end_month) : "");
|
||||
setAuthorisedShares(c.authorised_shares != null ? String(c.authorised_shares) : "");
|
||||
setCompanyCellPhone(c.company_cell_phone ?? "");
|
||||
setPublicOfficerName(c.public_officer_name ?? "");
|
||||
setCompanySecretaryName(c.company_secretary_name ?? "");
|
||||
setSarsLoginUsername(c.sars_login_username ?? "");
|
||||
setSarsLoginPassword(c.sars_login_password ?? "");
|
||||
setSarsPayeNo(c.sars_paye_no ?? "");
|
||||
|
|
@ -167,6 +264,18 @@ export default function EditEntityModal({ entity, record, open, onClose, onAfter
|
|||
if (postalAddress.trim()) fields.postal_address = postalAddress.trim();
|
||||
if (directorType.trim()) fields.director_type = directorType.trim();
|
||||
if (notes.trim()) fields.notes = notes.trim();
|
||||
// Structured address fields (added 2026-08-18)
|
||||
if (dateOfBirth.trim()) fields.date_of_birth = dateOfBirth.trim();
|
||||
if (resAddr1.trim()) fields.residential_address_line_1 = resAddr1.trim();
|
||||
if (resAddr2.trim()) fields.residential_address_line_2 = resAddr2.trim();
|
||||
if (resTown.trim()) fields.residential_town_city = resTown.trim();
|
||||
if (resProvince.trim()) fields.residential_province = resProvince.trim();
|
||||
if (resPostalCode.trim()) fields.residential_postal_code = resPostalCode.trim();
|
||||
if (postAddr1.trim()) fields.postal_address_line_1 = postAddr1.trim();
|
||||
if (postAddr2.trim()) fields.postal_address_line_2 = postAddr2.trim();
|
||||
if (postTown.trim()) fields.postal_town_city = postTown.trim();
|
||||
if (postProvince.trim()) fields.postal_province = postProvince.trim();
|
||||
if (postPostalCode.trim()) fields.postal_postal_code = postPostalCode.trim();
|
||||
} else {
|
||||
if (!enterpriseNo.trim() || !enterpriseName.trim()) {
|
||||
setError("Enterprise number and name are required.");
|
||||
|
|
@ -181,12 +290,33 @@ export default function EditEntityModal({ entity, record, open, onClose, onAfter
|
|||
if (postalAddressCo.trim()) fields.postal_address = postalAddressCo.trim();
|
||||
if (companyEmail.trim()) fields.company_email = companyEmail.trim();
|
||||
if (notesCo.trim()) fields.notes = notesCo.trim();
|
||||
// Structured address fields (added 2026-08-18)
|
||||
if (physAddr1.trim()) fields.physical_address_line_1 = physAddr1.trim();
|
||||
if (physAddr2.trim()) fields.physical_address_line_2 = physAddr2.trim();
|
||||
if (physTown.trim()) fields.physical_town_city = physTown.trim();
|
||||
if (physProvince.trim()) fields.physical_province = physProvince.trim();
|
||||
if (physPostalCode.trim()) fields.physical_postal_code = physPostalCode.trim();
|
||||
if (postCoAddr1.trim()) fields.postal_address_line_1 = postCoAddr1.trim();
|
||||
if (postCoAddr2.trim()) fields.postal_address_line_2 = postCoAddr2.trim();
|
||||
if (postCoTown.trim()) fields.postal_town_city = postCoTown.trim();
|
||||
if (postCoProvince.trim()) fields.postal_province = postCoProvince.trim();
|
||||
if (postCoPostalCode.trim()) fields.postal_postal_code = postCoPostalCode.trim();
|
||||
// Company-level fields (added 2026-08-18)
|
||||
if (financialYearEndMonth !== "" || (record as Company).financial_year_end_month != null) {
|
||||
fields.financial_year_end_month = financialYearEndMonth !== "" ? Number(financialYearEndMonth) : 0;
|
||||
}
|
||||
if (authorisedShares !== "" || (record as Company).authorised_shares != null) {
|
||||
fields.authorised_shares = authorisedShares !== "" ? Number(authorisedShares) : 0;
|
||||
}
|
||||
if (companyCellPhone.trim()) fields.company_cell_phone = companyCellPhone.trim();
|
||||
if (publicOfficerName.trim()) fields.public_officer_name = publicOfficerName.trim();
|
||||
if (companySecretaryName.trim()) fields.company_secretary_name = companySecretaryName.trim();
|
||||
if (sarsLoginUsername.trim()) fields.sars_login_username = sarsLoginUsername.trim();
|
||||
if (sarsLoginPassword.trim()) fields.sars_login_password = sarsLoginPassword.trim();
|
||||
if (sarsPayeNo.trim()) fields.sars_paye_no = sarsPayeNo.trim();
|
||||
if (sarsVatNo.trim()) fields.sars_vat_no = sarsVatNo.trim();
|
||||
if (sarsTaxNo.trim()) fields.sars_tax_number = sarsTaxNo.trim();
|
||||
// Period fields: store the selected numeric value as string (PocketBase number field accepts string->number conversion)
|
||||
// Period fields
|
||||
const vatPeriod = sarsVatReturnsPeriod;
|
||||
const payePeriod = sarsPayeReturnPeriod;
|
||||
if (vatPeriod !== "" || (record as Company).sars_vat_returns_period != null) {
|
||||
|
|
@ -215,6 +345,9 @@ export default function EditEntityModal({ entity, record, open, onClose, onAfter
|
|||
}
|
||||
};
|
||||
|
||||
const monthNames = ["January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"];
|
||||
|
||||
return (
|
||||
<div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm p-4"
|
||||
|
|
@ -275,6 +408,13 @@ export default function EditEntityModal({ entity, record, open, onClose, onAfter
|
|||
maxLength={13} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-fg mb-1.5" htmlFor="edit-dob">Date of birth <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-dob" type="date" value={dateOfBirth}
|
||||
onChange={(e) => setDateOfBirth(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-fg mb-1.5" htmlFor="edit-tel">Telephone <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
|
|
@ -291,12 +431,100 @@ export default function EditEntityModal({ entity, record, open, onClose, onAfter
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-fg mb-1.5" htmlFor="edit-postal">Postal address <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<label className="block text-sm font-semibold text-fg mb-1.5" htmlFor="edit-postal">Postal address <span className="text-xs text-muted font-normal">(optional, free-text)</span></label>
|
||||
<textarea id="edit-postal" value={postalAddress} rows={2}
|
||||
onChange={(e) => setPostalAddress(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg resize-none focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
|
||||
{/* Structured residential address (added 2026-08-18) */}
|
||||
<div className="border-t border-border pt-4 mt-2">
|
||||
<p className="text-sm font-semibold text-fg mb-3">Residential address <span className="text-xs text-muted font-normal">(structured)</span></p>
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-res1">Address line 1 <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-res1" type="text" value={resAddr1}
|
||||
onChange={(e) => setResAddr1(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-res2">Address line 2 <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-res2" type="text" value={resAddr2}
|
||||
onChange={(e) => setResAddr2(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-restown">Town / city <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-restown" type="text" value={resTown}
|
||||
onChange={(e) => setResTown(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-resprov">Province <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<select id="edit-resprov" value={resProvince}
|
||||
onChange={(e) => setResProvince(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent">
|
||||
<option value="">— select —</option>
|
||||
{SA_PROVINCES.map((p) => (
|
||||
<option key={p} value={p}>{p}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-reszip">Postal code <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-reszip" type="text" value={resPostalCode}
|
||||
onChange={(e) => setResPostalCode(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg font-mono focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Structured postal address (added 2026-08-18) */}
|
||||
<div className="border-t border-border pt-4 mt-2">
|
||||
<p className="text-sm font-semibold text-fg mb-3">Postal address <span className="text-xs text-muted font-normal">(structured)</span></p>
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-post1">Address line 1 <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-post1" type="text" value={postAddr1}
|
||||
onChange={(e) => setPostAddr1(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-post2">Address line 2 <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-post2" type="text" value={postAddr2}
|
||||
onChange={(e) => setPostAddr2(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-posttown">Town / city <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-posttown" type="text" value={postTown}
|
||||
onChange={(e) => setPostTown(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-postprov">Province <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<select id="edit-postprov" value={postProvince}
|
||||
onChange={(e) => setPostProvince(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent">
|
||||
<option value="">— select —</option>
|
||||
{SA_PROVINCES.map((p) => (
|
||||
<option key={p} value={p}>{p}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-postzip">Postal code <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-postzip" type="text" value={postPostalCode}
|
||||
onChange={(e) => setPostPostalCode(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg font-mono focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-fg mb-1.5" htmlFor="edit-type">Director type <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-type" type="text" value={directorType}
|
||||
|
|
@ -347,19 +575,107 @@ export default function EditEntityModal({ entity, record, open, onClose, onAfter
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-fg mb-1.5" htmlFor="edit-phys">Physical address <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<label className="block text-sm font-semibold text-fg mb-1.5" htmlFor="edit-phys">Physical address <span className="text-xs text-muted font-normal">(optional, free-text)</span></label>
|
||||
<textarea id="edit-phys" value={physicalAddress} rows={2}
|
||||
onChange={(e) => setPhysicalAddress(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg resize-none focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-fg mb-1.5" htmlFor="edit-postalco">Postal address <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<label className="block text-sm font-semibold text-fg mb-1.5" htmlFor="edit-postalco">Postal address <span className="text-xs text-muted font-normal">(optional, free-text)</span></label>
|
||||
<textarea id="edit-postalco" value={postalAddressCo} rows={2}
|
||||
onChange={(e) => setPostalAddressCo(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg resize-none focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
|
||||
{/* Structured physical address (added 2026-08-18) */}
|
||||
<div className="border-t border-border pt-4 mt-2">
|
||||
<p className="text-sm font-semibold text-fg mb-3">Physical address <span className="text-xs text-muted font-normal">(structured)</span></p>
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-phys1">Address line 1 <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-phys1" type="text" value={physAddr1}
|
||||
onChange={(e) => setPhysAddr1(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-phys2">Address line 2 <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-phys2" type="text" value={physAddr2}
|
||||
onChange={(e) => setPhysAddr2(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-phystown">Town / city <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-phystown" type="text" value={physTown}
|
||||
onChange={(e) => setPhysTown(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-physprov">Province <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<select id="edit-physprov" value={physProvince}
|
||||
onChange={(e) => setPhysProvince(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent">
|
||||
<option value="">— select —</option>
|
||||
{SA_PROVINCES.map((p) => (
|
||||
<option key={p} value={p}>{p}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-physzip">Postal code <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-physzip" type="text" value={physPostalCode}
|
||||
onChange={(e) => setPhysPostalCode(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg font-mono focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Structured postal address (added 2026-08-18) */}
|
||||
<div className="border-t border-border pt-4 mt-2">
|
||||
<p className="text-sm font-semibold text-fg mb-3">Postal address <span className="text-xs text-muted font-normal">(structured)</span></p>
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-postco1">Address line 1 <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-postco1" type="text" value={postCoAddr1}
|
||||
onChange={(e) => setPostCoAddr1(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-postco2">Address line 2 <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-postco2" type="text" value={postCoAddr2}
|
||||
onChange={(e) => setPostCoAddr2(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-postcotown">Town / city <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-postcotown" type="text" value={postCoTown}
|
||||
onChange={(e) => setPostCoTown(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-postcoprov">Province <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<select id="edit-postcoprov" value={postCoProvince}
|
||||
onChange={(e) => setPostCoProvince(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent">
|
||||
<option value="">— select —</option>
|
||||
{SA_PROVINCES.map((p) => (
|
||||
<option key={p} value={p}>{p}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-postcozip">Postal code <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-postcozip" type="text" value={postCoPostalCode}
|
||||
onChange={(e) => setPostCoPostalCode(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg font-mono focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-fg mb-1.5" htmlFor="edit-emailco">Company email <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-emailco" type="email" value={companyEmail}
|
||||
|
|
@ -368,6 +684,56 @@ export default function EditEntityModal({ entity, record, open, onClose, onAfter
|
|||
placeholder="company@example.com" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-fg mb-1.5" htmlFor="edit-cellco">Company cell phone <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-cellco" type="tel" value={companyCellPhone}
|
||||
onChange={(e) => setCompanyCellPhone(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
|
||||
{/* Company-level fields (added 2026-08-18) */}
|
||||
<div className="border-t border-border pt-4 mt-2">
|
||||
<p className="text-sm font-semibold text-fg mb-3">Company details</p>
|
||||
<div className="space-y-3">
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-fye">Financial year end <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<select id="edit-fye" value={financialYearEndMonth}
|
||||
onChange={(e) => setFinancialYearEndMonth(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent">
|
||||
<option value="">— select —</option>
|
||||
{monthNames.map((m, i) => (
|
||||
<option key={i + 1} value={String(i + 1)}>{m}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-shares">Authorised shares <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<select id="edit-shares" value={authorisedShares}
|
||||
onChange={(e) => setAuthorisedShares(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent">
|
||||
<option value="">— select —</option>
|
||||
<option value="100">100</option>
|
||||
<option value="1000">1,000</option>
|
||||
<option value="10000">10,000</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-officer">Public officer <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-officer" type="text" value={publicOfficerName}
|
||||
onChange={(e) => setPublicOfficerName(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-fg-2 mb-1.5" htmlFor="edit-secretary">Company secretary <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<input id="edit-secretary" type="text" value={companySecretaryName}
|
||||
onChange={(e) => setCompanySecretaryName(e.target.value)}
|
||||
className="w-full rounded-lg border border-border bg-surface-warm px-3 py-2.5 text-sm text-fg focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-fg mb-1.5" htmlFor="edit-notesco">Notes <span className="text-xs text-muted font-normal">(optional)</span></label>
|
||||
<textarea id="edit-notesco" value={notesCo} rows={2}
|
||||
|
|
|
|||
38
lib/types.ts
38
lib/types.ts
|
|
@ -26,6 +26,22 @@ export interface YsterbaardDirector {
|
|||
first_seen: string | null; // ISO date
|
||||
last_checked: string | null; // ISO date
|
||||
notes: string | null;
|
||||
// ─── Structured address fields (added 2026-08-18 from onboarding form) ───
|
||||
/** Flat address — back-compat. Use line_1 + line_2 + town_city + province + postal_code. */
|
||||
residential_address: string | null;
|
||||
residential_address_line_1: string | null;
|
||||
residential_address_line_2: string | null;
|
||||
residential_town_city: string | null;
|
||||
residential_province: string | null;
|
||||
residential_postal_code: string | null;
|
||||
postal_address: string | null;
|
||||
postal_address_line_1: string | null;
|
||||
postal_address_line_2: string | null;
|
||||
postal_town_city: string | null;
|
||||
postal_province: string | null;
|
||||
postal_postal_code: string | null;
|
||||
/** ISO date string YYYY-MM-DD. */
|
||||
date_of_birth: string | null;
|
||||
created: string;
|
||||
updated: string;
|
||||
}
|
||||
|
|
@ -77,6 +93,28 @@ export interface YsterbaardCompany {
|
|||
physical_address_normalized: string | null;
|
||||
postal_address_normalized: string | null;
|
||||
company_email: string | null;
|
||||
// ─── Structured address fields (added 2026-08-18 from onboarding form) ───
|
||||
physical_address_line_1: string | null;
|
||||
physical_address_line_2: string | null;
|
||||
physical_town_city: string | null;
|
||||
physical_province: string | null;
|
||||
physical_postal_code: string | null;
|
||||
postal_address_line_1: string | null;
|
||||
postal_address_line_2: string | null;
|
||||
postal_town_city: string | null;
|
||||
postal_province: string | null;
|
||||
postal_postal_code: string | null;
|
||||
// ─── Company-level fields (added 2026-08-18 from onboarding form) ───
|
||||
/** 1-12, month when the company financial year ends. */
|
||||
financial_year_end_month: number | null;
|
||||
/** Total number of authorised shares (e.g. 100 or 1000). */
|
||||
authorised_shares: number | null;
|
||||
/** Company cell phone (different from director mobile). */
|
||||
company_cell_phone: string | null;
|
||||
/** SARS "Public Officer" — typically the accountant / responsible person. */
|
||||
public_officer_name: string | null;
|
||||
/** Company secretary name. */
|
||||
company_secretary_name: string | null;
|
||||
sars_tax_number: string | null;
|
||||
uif_registration_number: string | null;
|
||||
compensation_fund_registration_number: string | null;
|
||||
|
|
|
|||
Loading…
Reference in a new issue