diff --git a/apps/portal/src/app/features/seaman-book/pages/SeamanBookApplicationPage.tsx b/apps/portal/src/app/features/seaman-book/pages/SeamanBookApplicationPage.tsx index e71f1df71..48c0a150e 100644 --- a/apps/portal/src/app/features/seaman-book/pages/SeamanBookApplicationPage.tsx +++ b/apps/portal/src/app/features/seaman-book/pages/SeamanBookApplicationPage.tsx @@ -38,29 +38,12 @@ import { notify } from '@ema-platform/ui'; // Steps // --------------------------------------------------------------------------- const STEPS = [ - { label: 'BST Certificates' }, + { label: 'Relevant Certificate' }, { label: 'Medical Certificate' }, { label: 'Payment' }, { label: 'Review & Submit' }, ]; -// --------------------------------------------------------------------------- -// BST slots -// --------------------------------------------------------------------------- -interface BSTSlot { - key: string; - label: string; - short: string; - refreshYears: number; -} - -const BST_SLOTS: BSTSlot[] = [ - { key: 'pst', short: 'PST', label: 'Personal Survival Techniques (PST)', refreshYears: 5 }, - { key: 'fpff', short: 'FPFF', label: 'Fire Prevention & Fire Fighting (FPFF)', refreshYears: 5 }, - { key: 'efa', short: 'EFA', label: 'Elementary First Aid (EFA)', refreshYears: 0 }, - { key: 'pssr', short: 'PSSR', label: 'Personal Safety & Social Responsibility (PSSR)',refreshYears: 0 }, - { key: 'shp', short: 'SHPT', label: 'Sexual Harassment Prevention Training (SHPT)', refreshYears: 0 }, -]; // --------------------------------------------------------------------------- // Fee table — Seaman Book + BTC shown separately, paid together @@ -137,71 +120,6 @@ function ReviewRow({ label, value }: { label: string; value: string }) { ); } -// --------------------------------------------------------------------------- -// BST upload card -// --------------------------------------------------------------------------- -function BSTCard({ slot, certNumber, onCertNumber, issuer, onIssuer, issueDate, onIssueDate, expiryDate, onExpiryDate, file, onFile, resetRef }: { - slot: BSTSlot; - certNumber: string; onCertNumber: (v: string) => void; - issuer: string; onIssuer: (v: string) => void; - issueDate: string; onIssueDate: (v: string) => void; - expiryDate: string; onExpiryDate: (v: string) => void; - file: File | null; onFile: (f: File | null) => void; - resetRef: React.MutableRefObject<(() => void) | null>; -}) { - const isComplete = !!file && !!certNumber.trim() && !!issuer.trim() && !!issueDate; - return ( - - - - - -
- - {slot.short} - * - {isComplete && Done} - - {slot.label} -
-
- - onCertNumber(e.currentTarget.value)} /> - onIssuer(e.currentTarget.value)} /> - 0 ? 2 : 1} spacing="xs"> - onIssueDate(e.currentTarget.value)} /> - {slot.refreshYears > 0 && ( - onExpiryDate(e.currentTarget.value)} /> - )} - - {file ? ( - - - {file.name} - - - ) : ( - - {(props) => ( - - )} - - )} - -
- ); -} // --------------------------------------------------------------------------- // Main page @@ -212,13 +130,13 @@ export function SeamanBookApplicationPage() { const [completed, setCompleted] = useState([]); const [submitting, setSubmitting] = useState(false); - // BST - const [bstData, setBstData] = useState>(() => - Object.fromEntries(BST_SLOTS.map((s) => [s.key, { certNumber: '', issuer: '', issueDate: '', expiryDate: '', file: null }])) - ); - const bstResetRefs = useRef void) | null>>({}); - const updateBst = (key: string, field: string, value: string | File | null) => - setBstData((prev) => ({ ...prev, [key]: { ...prev[key], [field]: value } })); + // Relevant Certificate + const [relCertNumber, setRelCertNumber] = useState(''); + const [relIssuer, setRelIssuer] = useState(''); + const [relIssueDate, setRelIssueDate] = useState(''); + const [relExpiryDate, setRelExpiryDate] = useState(''); + const [relFile, setRelFile] = useState(null); + const relResetRef = useRef<() => void>(null); // Medical const [medCertNumber, setMedCertNumber] = useState(''); @@ -236,15 +154,12 @@ export function SeamanBookApplicationPage() { const payResetRef = useRef<() => void>(null); // Validation - const bstComplete = BST_SLOTS.every((s) => { - const d = bstData[s.key]; - return !!d.file && !!d.certNumber.trim() && !!d.issuer.trim() && !!d.issueDate; - }); + const relComplete = !!relFile && !!relCertNumber.trim() && !!relIssuer.trim() && !!relIssueDate && !!relExpiryDate; const medComplete = !!medFile && !!medCertNumber.trim() && !!medIssuer.trim() && !!medIssueDate && !!medExpiryDate; const payComplete = !!paymentMethod && !!paymentRef.trim() && !!paymentDate; const canNext = () => { - if (active === 0) return bstComplete; + if (active === 0) return relComplete; if (active === 1) return medComplete; if (active === 2) return payComplete; return true; @@ -306,52 +221,87 @@ export function SeamanBookApplicationPage() { Step {active + 1} of {STEPS.length} - {/* ── Step 1: BST ─────────────────────────────────────────────── */} + {/* ── Step 1: Relevant Certificate ────────────────────────────── */} {active === 0 && ( }> - Upload all 5 Basic Safety Training certificates. These training certificates issued by approved institutions are different from the EMA-issued BTC — they are the prerequisite for your BTC. + Upload your relevant certificate issued by an EMA-approved training institution. This is the prerequisite for your Basic Training Certificate (BTC). - + - {BST_SLOTS.map((slot) => { - const d = bstData[slot.key]; - const rRef = { current: bstResetRefs.current[slot.key] ?? null }; - return ( - updateBst(slot.key, 'certNumber', v)} - issuer={d.issuer} - onIssuer={(v) => updateBst(slot.key, 'issuer', v)} - issueDate={d.issueDate} - onIssueDate={(v) => updateBst(slot.key, 'issueDate', v)} - expiryDate={d.expiryDate} - onExpiryDate={(v) => updateBst(slot.key, 'expiryDate', v)} - file={d.file} - onFile={(f) => updateBst(slot.key, 'file', f)} - resetRef={rRef} - /> - ); - })} + setRelCertNumber(e.currentTarget.value)} + /> + setRelIssuer(e.currentTarget.value)} + /> - - Upload Progress - - {BST_SLOTS.map((slot) => { - const done = !!bstData[slot.key].file && !!bstData[slot.key].certNumber; - return ( - - {done ? : ( - - )} - {slot.short} - - ); - })} - - + + setRelIssueDate(e.currentTarget.value)} + /> + setRelExpiryDate(e.currentTarget.value)} + /> + + + + + + + +
+ Relevant Certificate * + PDF, JPG or PNG — max 5MB +
+
+ {relFile ? ( + + + {relFile.name} + + + ) : ( + + {(props) => ( + + )} + + )} +
)} @@ -587,23 +537,13 @@ export function SeamanBookApplicationPage() { - BST Certificates + Relevant Certificate - {BST_SLOTS.map((slot) => { - const d = bstData[slot.key]; - return ( -
- - - {slot.short} - - {d.certNumber || '—'} - {d.issuer || '—'} - Issued: {d.issueDate || '—'} - {d.file && {d.file.name}} -
- ); - })} + + + + +