From e39f80941ec17fa023a80ed93d5baab1c1937a27 Mon Sep 17 00:00:00 2001 From: fitse-yotor Date: Tue, 28 Jul 2026 14:46:06 +0300 Subject: [PATCH] feat: add Shipping Agent License Renewal and Waiver Application pages - Implement ShippingAgentLicenseRenewalPage for submitting renewal documents with file uploads. - Create WaiverApplicationPage for multi-step waiver application process, including document uploads and review. - Add WaiverPage to display application status and details, including waiver letter download functionality. - Introduce document handling components and validation for required fields in both applications. --- .../pages/CombinedLicenseQueuePage.tsx | 419 +++++++++++ .../pages/CombinedLicenseReviewPage.tsx | 306 ++++++++ .../FreightForwarderLicenseQueuePage.tsx | 418 +++++++++++ .../FreightForwarderLicenseReviewPage.tsx | 297 ++++++++ .../pages/JointInvestmentLicenseQueuePage.tsx | 414 ++++++++++ .../JointInvestmentLicenseReviewPage.tsx | 269 +++++++ .../pages/LogisticsHeadDashboardPage.tsx | 183 +++++ .../mto-license/pages/MtoLicenseQueuePage.tsx | 422 +++++++++++ .../pages/MtoLicenseReviewPage.tsx | 323 ++++++++ .../pages/ShippingAgentLicenseQueuePage.tsx | 419 +++++++++++ .../pages/ShippingAgentLicenseReviewPage.tsx | 300 ++++++++ .../features/waiver/pages/WaiverQueuePage.tsx | 452 +++++++++++ .../waiver/pages/WaiverReviewPage.tsx | 361 +++++++++ apps/backoffice/src/app/i18n/locales/am.ts | 7 + apps/backoffice/src/app/i18n/locales/en.ts | 7 + .../src/app/layouts/BackofficeLayout.tsx | 11 + apps/backoffice/src/app/router/index.tsx | 26 + .../pages/CombinedLicenseApplicationPage.tsx | 461 ++++++++++++ .../pages/CombinedLicensePage.tsx | 218 ++++++ .../pages/CombinedLicenseRenewalPage.tsx | 146 ++++ ...FreightForwarderLicenseApplicationPage.tsx | 434 +++++++++++ .../pages/FreightForwarderLicensePage.tsx | 215 ++++++ .../FreightForwarderLicenseRenewalPage.tsx | 144 ++++ .../JointInvestmentLicenseApplicationPage.tsx | 549 ++++++++++++++ .../pages/JointInvestmentLicensePage.tsx | 186 +++++ .../JointInvestmentLicenseRenewalPage.tsx | 36 + .../pages/LogisticsDashboardPage.tsx | 164 ++++ .../pages/MtoLicenseApplicationPage.tsx | 705 ++++++++++++++++++ .../mto-license/pages/MtoLicensePage.tsx | 230 ++++++ .../pages/MtoLicenseRenewalPage.tsx | 151 ++++ .../ShippingAgentLicenseApplicationPage.tsx | 484 ++++++++++++ .../pages/ShippingAgentLicensePage.tsx | 216 ++++++ .../pages/ShippingAgentLicenseRenewalPage.tsx | 146 ++++ .../waiver/pages/WaiverApplicationPage.tsx | 494 ++++++++++++ .../app/features/waiver/pages/WaiverPage.tsx | 219 ++++++ apps/portal/src/app/i18n/locales/am.ts | 7 + apps/portal/src/app/i18n/locales/en.ts | 7 + apps/portal/src/app/layouts/PortalLayout.tsx | 18 + apps/portal/src/app/router.tsx | 36 + 39 files changed, 9900 insertions(+) create mode 100644 apps/backoffice/src/app/features/combined-license/pages/CombinedLicenseQueuePage.tsx create mode 100644 apps/backoffice/src/app/features/combined-license/pages/CombinedLicenseReviewPage.tsx create mode 100644 apps/backoffice/src/app/features/freight-forwarder-license/pages/FreightForwarderLicenseQueuePage.tsx create mode 100644 apps/backoffice/src/app/features/freight-forwarder-license/pages/FreightForwarderLicenseReviewPage.tsx create mode 100644 apps/backoffice/src/app/features/joint-investment-license/pages/JointInvestmentLicenseQueuePage.tsx create mode 100644 apps/backoffice/src/app/features/joint-investment-license/pages/JointInvestmentLicenseReviewPage.tsx create mode 100644 apps/backoffice/src/app/features/logistics-head/pages/LogisticsHeadDashboardPage.tsx create mode 100644 apps/backoffice/src/app/features/mto-license/pages/MtoLicenseQueuePage.tsx create mode 100644 apps/backoffice/src/app/features/mto-license/pages/MtoLicenseReviewPage.tsx create mode 100644 apps/backoffice/src/app/features/shipping-agent-license/pages/ShippingAgentLicenseQueuePage.tsx create mode 100644 apps/backoffice/src/app/features/shipping-agent-license/pages/ShippingAgentLicenseReviewPage.tsx create mode 100644 apps/backoffice/src/app/features/waiver/pages/WaiverQueuePage.tsx create mode 100644 apps/backoffice/src/app/features/waiver/pages/WaiverReviewPage.tsx create mode 100644 apps/portal/src/app/features/combined-license/pages/CombinedLicenseApplicationPage.tsx create mode 100644 apps/portal/src/app/features/combined-license/pages/CombinedLicensePage.tsx create mode 100644 apps/portal/src/app/features/combined-license/pages/CombinedLicenseRenewalPage.tsx create mode 100644 apps/portal/src/app/features/freight-forwarder-license/pages/FreightForwarderLicenseApplicationPage.tsx create mode 100644 apps/portal/src/app/features/freight-forwarder-license/pages/FreightForwarderLicensePage.tsx create mode 100644 apps/portal/src/app/features/freight-forwarder-license/pages/FreightForwarderLicenseRenewalPage.tsx create mode 100644 apps/portal/src/app/features/joint-investment-license/pages/JointInvestmentLicenseApplicationPage.tsx create mode 100644 apps/portal/src/app/features/joint-investment-license/pages/JointInvestmentLicensePage.tsx create mode 100644 apps/portal/src/app/features/joint-investment-license/pages/JointInvestmentLicenseRenewalPage.tsx create mode 100644 apps/portal/src/app/features/logistics-dashboard/pages/LogisticsDashboardPage.tsx create mode 100644 apps/portal/src/app/features/mto-license/pages/MtoLicenseApplicationPage.tsx create mode 100644 apps/portal/src/app/features/mto-license/pages/MtoLicensePage.tsx create mode 100644 apps/portal/src/app/features/mto-license/pages/MtoLicenseRenewalPage.tsx create mode 100644 apps/portal/src/app/features/shipping-agent-license/pages/ShippingAgentLicenseApplicationPage.tsx create mode 100644 apps/portal/src/app/features/shipping-agent-license/pages/ShippingAgentLicensePage.tsx create mode 100644 apps/portal/src/app/features/shipping-agent-license/pages/ShippingAgentLicenseRenewalPage.tsx create mode 100644 apps/portal/src/app/features/waiver/pages/WaiverApplicationPage.tsx create mode 100644 apps/portal/src/app/features/waiver/pages/WaiverPage.tsx diff --git a/apps/backoffice/src/app/features/combined-license/pages/CombinedLicenseQueuePage.tsx b/apps/backoffice/src/app/features/combined-license/pages/CombinedLicenseQueuePage.tsx new file mode 100644 index 000000000..e3390ab11 --- /dev/null +++ b/apps/backoffice/src/app/features/combined-license/pages/CombinedLicenseQueuePage.tsx @@ -0,0 +1,419 @@ +import { useEffect, useRef, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useApiMutation } from '@ema-platform/api'; +import { + ActionIcon, + Badge, + Button, + Card, + Drawer, + Group, + Modal, + Paper, + Select, + SimpleGrid, + Stack, + Table, + Text, + Textarea, + TextInput, + ThemeIcon, + Title, +} from '@mantine/core'; +import { + IconCheck, + IconCircleCheck, + IconEye, + IconSearch, + IconShip, + IconX, + IconAlertCircle, +} from '@tabler/icons-react'; +import { notify } from '@ema-platform/ui'; + +// --------------------------------------------------------------------------- +// Types & constants +// --------------------------------------------------------------------------- +export type LicenseStatus = + | 'Submitted' + | 'Under Review' + | 'Under Evaluation' + | 'Approved' + | 'Resubmit Required' + | 'Rejected' + | 'Payment Pending' + | 'Payment Confirmed' + | 'Certificate Issued'; + +export interface CombinedLicenseApplication { + id: string; + companyName: string; + tinNumber: string; + commercialRegNumber: string; + businessAddress: string; + bankName: string; + capitalAmount: number; + status: LicenseStatus; + submittedDate: string; + approvalDate: string | null; + expiryDate: string | null; + remarks: string; + docsComplete: boolean; +} + +export const MOCK_COMBINED_APPLICATIONS: CombinedLicenseApplication[] = [ + { + id: 'CFS-2024-001', + companyName: 'Blue Nile Shipping & Forwarding PLC', + tinNumber: 'TIN-0098231', + commercialRegNumber: 'CR-902341', + businessAddress: 'Addis Ababa, Bole Sub-city', + bankName: 'Commercial Bank of Ethiopia', + capitalAmount: 2200000, + status: 'Under Evaluation', + submittedDate: '2024-03-14', + approvalDate: null, + expiryDate: null, + remarks: 'Terminal agreement and transit staff certificates under review.', + docsComplete: true, + }, + { + id: 'CFS-2024-002', + companyName: 'Red Sea Gateway Logistics Ltd', + tinNumber: 'TIN-0071122', + commercialRegNumber: 'CR-813457', + businessAddress: 'Dire Dawa', + bankName: 'Dashen Bank', + capitalAmount: 1650000, + status: 'Submitted', + submittedDate: '2024-04-05', + approvalDate: null, + expiryDate: null, + remarks: '', + docsComplete: false, + }, + { + id: 'CFS-2023-017', + companyName: 'Tana Maritime & Forwarding PLC', + tinNumber: 'TIN-0045690', + commercialRegNumber: 'CR-704128', + businessAddress: 'Addis Ababa, Kirkos Sub-city', + bankName: 'Awash Bank', + capitalAmount: 2500000, + status: 'Certificate Issued', + submittedDate: '2023-10-12', + approvalDate: '2023-11-08', + expiryDate: '2024-11-08', + remarks: 'All requirements verified. Certificate issued.', + docsComplete: true, + }, +]; + +export const STATUS_COLOR: Record = { + Draft: 'gray', + Submitted: 'blue', + 'Under Review': 'yellow', + 'Under Evaluation': 'yellow', + Approved: 'teal', + 'Resubmit Required': 'orange', + Rejected: 'red', + 'Payment Pending': 'grape', + 'Payment Confirmed': 'indigo', + 'Certificate Issued': 'green', +}; + +// --------------------------------------------------------------------------- +// Detail drawer +// --------------------------------------------------------------------------- +function ApplicationDrawer({ + app, + opened, + onClose, + onAction, + onFullReview, +}: { + app: CombinedLicenseApplication | null; + opened: boolean; + onClose: () => void; + onAction: (id: string, action: 'approve' | 'reject' | 'resubmit', remarks: string) => void; + onFullReview: (id: string) => void; +}) { + const [remarks, setRemarks] = useState(''); + const [confirmModal, setConfirmModal] = useState<'approve' | 'reject' | 'resubmit' | null>(null); + + if (!app) return null; + + const isTerminal = app.status === 'Rejected' || app.status === 'Certificate Issued'; + + const submit = (action: 'approve' | 'reject' | 'resubmit') => { + onAction(app.id, action, remarks); + setRemarks(''); + setConfirmModal(null); + onClose(); + }; + + return ( + <> + + + + + + Company Information + + {[ + { label: 'Company Name', value: app.companyName }, + { label: 'TIN Number', value: app.tinNumber }, + { label: 'Commercial Reg. No.', value: app.commercialRegNumber }, + { label: 'Business Address', value: app.businessAddress }, + { label: 'Bank Letter Amount', value: `${app.capitalAmount.toLocaleString()} ETB` }, + { label: 'Submitted', value: app.submittedDate }, + ].map((r) => ( +
+ {r.label} + {r.value || '—'} +
+ ))} +
+
+ + + Document Checklist + + {[ + { label: 'Shipping Company Agreement', ok: app.docsComplete }, + { label: 'Bank Letter (≥ 1.5M ETB)', ok: app.docsComplete }, + { label: 'Vehicle Libre / Rental Agreement', ok: app.docsComplete }, + { label: 'Office Title Deed / Rental Agreement', ok: app.docsComplete }, + { label: 'Terminal Agreement / Title Deed', ok: app.docsComplete }, + { label: '2 Qualified Transit Employees (ERB Certificates)', ok: app.docsComplete }, + ].map((item) => ( + + + {item.ok ? : } + + {item.label} + + ))} + + + + + + Current Status + {app.status} + + {app.remarks && {app.remarks}} + + + {!isTerminal && ( + + Officer Remarks +