Workflow-App/Workflow/components/DirectorForm.tsx

163 lines
7.3 KiB
TypeScript
Raw Normal View History

// components/DirectorForm.tsx
// Renders a single director's form including Section 69 questions.
"use client";
import type { DirectorInput, Section69 } from "@/lib/wizard-types";
interface Props {
director: DirectorInput;
onUpdate: (patch: Partial<DirectorInput>) => void;
index: number;
}
const S69_QUESTIONS: { key: keyof Section69; label: string }[] = [
{ key: "q1_probation", label: "Are you a person who has been placed under probation by a court in terms of section 162, or in terms of section 47 of the Close Corporations Act, 1984?" },
{ key: "q2_court_prohibited", label: "Has a court prohibited you to be a director, or declared you to be delinquent in terms of section 162, or in terms of section 47 of the Close Corporations Act, 1984?" },
{ key: "q3_unrehabilitated_insolvent", label: "Are you an unrehabilitated insolvent?" },
{ key: "q4_public_regulation", label: "Are you prohibited in terms of any public regulation to be a director of the company?" },
{ key: "q5_removed_from_office", label: "Were you removed from an office of trust, on the grounds of misconduct involving dishonesty?" },
{ key: "q6_convicted_offence", label: "Were you convicted, in the Republic or elsewhere, and imprisoned without the option of a fine, or fined more than the prescribed amount, for theft, fraud, forgery, perjury or an offence?" },
];
function FormField({ label, hint, children }: { label: string; hint?: string; children: React.ReactNode }) {
return (
<div className="space-y-1.5">
<label className="text-sm font-semibold text-fg">{label}</label>
{children}
{hint && <p className="text-xs text-muted">{hint}</p>}
</div>
);
}
function YesNoButtons({ value, onChange }: { value: boolean | null; onChange: (v: boolean | null) => void }) {
return (
<div className="flex gap-2 mt-1">
{([true, false] as const).map((opt) => (
<button
key={String(opt)}
type="button"
onClick={() => onChange(value === opt ? null : opt)}
className={
"px-4 py-1.5 rounded text-sm font-semibold border transition-colors " +
(value === opt
? opt ? "bg-success text-success-on border-transparent" : "bg-danger text-danger-on border-transparent"
: "bg-surface border-border text-muted hover:text-fg")
}
>
{opt ? "Yes" : "No"}
</button>
))}
</div>
);
}
export default function DirectorForm({ director: d, onUpdate, index }: Props) {
const updateS69 = (key: keyof Section69, value: boolean | null) => {
onUpdate({ section69: { ...d.section69, [key]: value } });
};
return (
<div className="border border-border rounded-lg overflow-hidden mb-6 last:mb-0">
<div className="bg-surface-warm border-b border-border px-5 py-3">
<p className="text-sm font-bold text-fg">Director {index + 1}</p>
</div>
<div className="p-5 space-y-5">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<FormField label="First names">
<input
className="w-full bg-surface border border-border rounded px-3 py-2 text-sm text-fg placeholder-muted focus:outline-none focus:border-accent transition-colors"
placeholder="e.g. Stephanus Johannes"
value={d.first_names}
onChange={(e) => onUpdate({ first_names: e.target.value })}
/>
</FormField>
<FormField label="Surname">
<input
className="w-full bg-surface border border-border rounded px-3 py-2 text-sm text-fg placeholder-muted focus:outline-none focus:border-accent transition-colors"
placeholder="e.g. van der Merwe"
value={d.surname}
onChange={(e) => onUpdate({ surname: e.target.value })}
/>
</FormField>
<FormField label="SA ID number">
<input
type="tel"
className="w-full bg-surface border border-border rounded px-3 py-2 text-sm text-fg placeholder-muted focus:outline-none focus:border-accent transition-colors"
placeholder="13-digit SA ID"
maxLength={13}
value={d.id_no}
onChange={(e) => onUpdate({ id_no: e.target.value })}
/>
</FormField>
<FormField label="Date of birth">
<input
type="date"
className="w-full bg-surface border border-border rounded px-3 py-2 text-sm text-fg focus:outline-none focus:border-accent transition-colors"
value={d.date_of_birth}
onChange={(e) => onUpdate({ date_of_birth: e.target.value })}
/>
</FormField>
</div>
<FormField label="Residential address">
<textarea
rows={2}
className="w-full bg-surface border border-border rounded px-3 py-2 text-sm text-fg placeholder-muted focus:outline-none focus:border-accent transition-colors resize-none"
placeholder="Physical residential address"
value={d.residential_address}
onChange={(e) => onUpdate({ residential_address: e.target.value })}
/>
</FormField>
<FormField label="Postal address" hint="Leave blank if same as residential address">
<textarea
rows={2}
className="w-full bg-surface border border-border rounded px-3 py-2 text-sm text-fg placeholder-muted focus:outline-none focus:border-accent transition-colors resize-none"
placeholder="Postal address"
value={d.postal_address}
onChange={(e) => onUpdate({ postal_address: e.target.value })}
/>
</FormField>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<FormField label="Cell phone">
<input
type="tel"
className="w-full bg-surface border border-border rounded px-3 py-2 text-sm text-fg placeholder-muted focus:outline-none focus:border-accent transition-colors"
placeholder="e.g. 0821234567"
value={d.cell_phone}
onChange={(e) => onUpdate({ cell_phone: e.target.value })}
/>
</FormField>
<FormField label="Email address">
<input
type="email"
className="w-full bg-surface border border-border rounded px-3 py-2 text-sm text-fg placeholder-muted focus:outline-none focus:border-accent transition-colors"
placeholder="unique@email.com"
value={d.email}
onChange={(e) => onUpdate({ email: e.target.value })}
/>
</FormField>
</div>
<div className="border-t border-border pt-5">
<p className="text-sm font-semibold text-fg mb-4">
Section 69 — Companies Act 71 of 2008
</p>
<div className="space-y-4">
{S69_QUESTIONS.map((q) => (
<div key={q.key} className="flex flex-col sm:flex-row sm:items-start sm:gap-4">
<div className="sm:w-2/3 text-sm text-fg leading-relaxed pt-0.5">{q.label}</div>
<div className="sm:w-1/3 flex-shrink-0">
<YesNoButtons value={d.section69[q.key]} onChange={(v) => updateS69(q.key, v)} />
</div>
</div>
))}
</div>
</div>
</div>
</div>
);
}