import { useState } from 'react'; import { ActionIcon, Alert, Badge, Button, Card, Divider, Group, Modal, NumberInput, Paper, Select, SimpleGrid, Stack, Switch, Table, Text, TextInput, ThemeIcon, Title, rem, } from '@mantine/core'; import { IconBook2, IconCertificate, IconCheck, IconCreditCard, IconEdit, IconId, IconInfoCircle, IconShieldCheck, } from '@tabler/icons-react'; import { notify } from '@ema-platform/ui'; // --------------------------------------------------------------------------- // Types // --------------------------------------------------------------------------- interface CertFee { id: string; certType: string; icon: typeof IconBook2; color: string; description: string; fees: { label: string; amount: number; editable: boolean }[]; enabled: boolean; } interface PaymentMethod { id: string; name: string; shortName: string; accountNumber: string; accountName: string; instructions: string; enabled: boolean; } // --------------------------------------------------------------------------- // Initial state // --------------------------------------------------------------------------- const INITIAL_CERT_FEES: CertFee[] = [ { id: 'seaman-book', certType: 'Seaman Book', icon: IconBook2, color: 'blue', description: 'Official EMA seafarer identification book — valid 5 years', fees: [ { label: 'Application Fee', amount: 500, editable: true }, { label: 'Document Verification Fee',amount: 200, editable: true }, ], enabled: true, }, { id: 'btc', certType: 'Basic Training Certificate (BTC)', icon: IconCertificate, color: 'teal', description: 'EMA-issued BTC certifying all 5 basic safety training courses — valid 5 years', fees: [ { label: 'Application Fee', amount: 300, editable: true }, { label: 'Document Verification Fee',amount: 100, editable: true }, ], enabled: true, }, { id: 'bsid', certType: 'BSID (Biometric Seafarer ID)', icon: IconId, color: 'violet', description: 'Biometric Seafarer Identity Document — valid 5 years', fees: [ { label: 'Application Fee', amount: 100, editable: true }, { label: 'Card Production Fee', amount: 150, editable: true }, ], enabled: true, }, { id: 'certificate', certType: 'Certificate (CoC / CoP)', icon: IconShieldCheck, color: 'orange', description: 'Certificate of Competency or Certificate of Proficiency under STCW', fees: [ { label: 'Application Fee', amount: 800, editable: true }, { label: 'Examination Fee', amount: 400, editable: true }, { label: 'Certificate Issuance Fee', amount: 200, editable: true }, ], enabled: true, }, ]; const INITIAL_PAYMENT_METHODS: PaymentMethod[] = [ { id: 'cbe', name: 'Commercial Bank of Ethiopia', shortName: 'CBE', accountNumber: '1000123456789', accountName: 'EMA Maritime Authority', instructions: 'Transfer the exact fee amount. Use your full name as the transfer description.', enabled: true, }, { id: 'telebirr', name: 'Telebirr (Ethio Telecom)', shortName: 'Telebirr', accountNumber: '+251 11 551 0000', accountName: 'EMA Maritime Authority', instructions: 'Send to Telebirr number. Screenshot your confirmation and upload it with your application.', enabled: true, }, ]; // --------------------------------------------------------------------------- // Fee edit modal // --------------------------------------------------------------------------- function FeeEditModal({ cert, opened, onClose, onSave, }: { cert: CertFee | null; opened: boolean; onClose: () => void; onSave: (id: string, fees: CertFee['fees']) => void; }) { const [fees, setFees] = useState(cert?.fees ?? []); const handleOpen = () => setFees(cert?.fees ?? []); return ( Edit Fees — {cert?.certType}} size="md" radius="lg" onTransitionEnd={() => { if (opened) handleOpen(); }} > }> Changes take effect on new applications immediately. Existing applications retain the fee at time of submission. {fees.map((fee, i) => ( setFees((prev) => prev.map((f, idx) => idx === i ? { ...f, amount: Number(v) || 0 } : f)) } /> ))} Total ETB {fees.reduce((s, f) => s + f.amount, 0).toFixed(2)} ); } // --------------------------------------------------------------------------- // Payment method edit modal // --------------------------------------------------------------------------- function MethodEditModal({ method, opened, onClose, onSave, }: { method: PaymentMethod | null; opened: boolean; onClose: () => void; onSave: (updated: PaymentMethod) => void; }) { const [form, setForm] = useState(method ?? INITIAL_PAYMENT_METHODS[0]); const set = (k: keyof PaymentMethod, v: string) => setForm((p) => ({ ...p, [k]: v })); return ( Edit Payment Method — {method?.shortName}} size="md" radius="lg" onTransitionEnd={() => { if (opened && method) setForm(method); }} > set('accountNumber', e.currentTarget.value)} /> set('accountName', e.currentTarget.value)} /> set('instructions', e.currentTarget.value)} /> ); } // --------------------------------------------------------------------------- // Main page // --------------------------------------------------------------------------- export function PaymentConfigPage() { const [certFees, setCertFees] = useState(INITIAL_CERT_FEES); const [methods, setMethods] = useState(INITIAL_PAYMENT_METHODS); const [editingCert, setEditingCert] = useState(null); const [editingMethod, setEditingMethod] = useState(null); const totalCombined = certFees .filter((c) => c.enabled) .flatMap((c) => c.fees) .reduce((s, f) => s + f.amount, 0); const handleSaveFees = (id: string, fees: CertFee['fees']) => { setCertFees((prev) => prev.map((c) => c.id === id ? { ...c, fees } : c)); notify.success('Fees updated successfully.'); }; const handleToggleCert = (id: string) => { setCertFees((prev) => prev.map((c) => c.id === id ? { ...c, enabled: !c.enabled } : c)); }; const handleSaveMethod = (updated: PaymentMethod) => { setMethods((prev) => prev.map((m) => m.id === updated.id ? updated : m)); notify.success('Payment method updated.'); }; const handleToggleMethod = (id: string) => { setMethods((prev) => prev.map((m) => m.id === id ? { ...m, enabled: !m.enabled } : m)); }; return ( {/* Header */}
Payment Configuration Manage certificate fees and accepted payment methods shown to applicants
Combined Total: ETB {totalCombined.toFixed(2)}
{/* Fee summary table */} Certificate Fees Click Edit to change fee amounts {['Certificate Type', 'Fee Breakdown', 'Total', 'Status', ''].map((h) => ( {h} ))} {certFees.map((cert) => { const CertIcon = cert.icon; const total = cert.fees.reduce((s, f) => s + f.amount, 0); return (
{cert.certType} {cert.description}
{cert.fees.map((f) => ( {f.label}: ETB {f.amount.toFixed(2)} ))} ETB {total.toFixed(2)} handleToggleCert(cert.id)} size="sm" color="teal" label={cert.enabled ? 'Active' : 'Disabled'} /> setEditingCert(cert)}>
); })}
Grand Total (all active) ETB {totalCombined.toFixed(2)}
{/* Payment methods */} Accepted Payment Methods {methods.map((method) => (
{method.name} {method.enabled ? 'Active' : 'Disabled'}
handleToggleMethod(method.id)} size="sm" color="teal" /> setEditingMethod(method)}>
Account / Number {method.accountNumber} Account Name {method.accountName} {method.instructions}
))}
{/* Fee edit modal */} setEditingCert(null)} onSave={handleSaveFees} /> {/* Method edit modal */} setEditingMethod(null)} onSave={handleSaveMethod} />
); }