mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-26 19:12:50 +00:00
- Added VesselRegistrationApplicationPage for submitting new vessel registrations. - Created VesselRegistrationPage to list user's registrations and navigate to details. - Implemented VesselRegistrationStatusPage to display registration status and download certificates. - Integrated mock data for registrations and certificates. - Updated navigation and routing to include vessel registration paths. - Added translations for vessel registration in English and Amharic. - Documented the vessel registration workflow and API integration notes.
74 lines
9.1 KiB
Markdown
74 lines
9.1 KiB
Markdown
# Vessel Registration — mock implementation notes (for API integration)
|
|
|
|
Portal (owner-facing) + Backoffice (officer/manager-facing) built as **mock UI only**, matching each app's existing mock-driven review-workflow convention (same pattern as `docs/vessel-ownership-transfer.md`). No backend calls anywhere. This doc exists to make wiring the real API fast — it says exactly what to replace and where.
|
|
|
|
## Workflow
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
A["1. Vessel owner opens Vessel Registration"] --> B{"2. Select vessel category"}
|
|
B -->|Inland Waterway Vessel| C["3. Enter vessel details"]
|
|
B -->|Sea-going Vessel International| C
|
|
C --> D["4. Enter technical & ownership details"]
|
|
D --> E["5. Upload required documents"]
|
|
E --> F["6. Review application"]
|
|
F --> G["7. Submit application"]
|
|
G --> H["8. System sends confirmation notification\n(SMS + email)"]
|
|
H --> I["9. Officer reviews application\nin registration queue"]
|
|
I --> J{"10. Officer takes action"}
|
|
J -->|Under Review| I
|
|
J -->|Correction Required| K["11. Owner updates & resubmits"]
|
|
K --> I
|
|
J -->|Rejected| Z1["Terminal: Rejected\n(remarks visible to owner)"]
|
|
J -->|Approved| L["12. System generates certificates\n(1 for Inland, 4 for Sea-going)"]
|
|
L --> M["13. Owner downloads certificates"]
|
|
M --> N["14. System tracks renewal status\n(OK / Due Soon / Overdue)"]
|
|
N --> O["15. Manager views registration reports"]
|
|
```
|
|
|
|
Status lifecycle: `Pending → Under Review → (Correction Required → Resubmitted →)* → Approved | Rejected`. `Approved`/`Rejected` are terminal — no further officer action possible once reached.
|
|
|
|
## What exists
|
|
|
|
### Portal (`apps/portal/src/app/features/vessel-registration/`)
|
|
- `mock.ts` — types (`VesselCategory`, `RegistrationStatus`, `VesselRegistration`, …), reference data (`VESSEL_TYPES`, `ENGINE_TYPES`, `HULL_MATERIALS`, `REQUIRED_DOCS`, `CERTIFICATES` per category), `MOCK_REGISTRATIONS`, `addRegistration()`, `recordDownload()`
|
|
- `pages/VesselRegistrationPage.tsx` — list of the owner's registrations (`/vessel-registrations`)
|
|
- `pages/VesselRegistrationApplicationPage.tsx` — 5-step submit wizard: Category → Vessel Details → Technical & Ownership → Documents → Review (`/vessel-registrations/apply`)
|
|
- `pages/VesselRegistrationStatusPage.tsx` — status detail: timeline, renewal alert, officer remarks + resubmit, certificate downloads (`/vessel-registrations/:id`)
|
|
|
|
### Backoffice (`apps/backoffice/src/app/features/vessel-registration/`)
|
|
- `mock.ts` — separate types + `MOCK_REGISTRATIONS` (officer-side shape, includes `documents[]` and `correctionFields?`), `applyDecision()`, `generateCertificates()`
|
|
- `pages/VesselRegistrationQueuePage.tsx` — queue table, stats, search + 3 filters (status/category/renewal) (`/vessel-registrations`)
|
|
- `pages/VesselRegistrationReviewPage.tsx` — two-column review: vessel/technical/ownership info + documents/timeline/remarks/certificates; decision bar (Mark Under Review / Request Correction / Reject / Approve) (`/vessel-registrations/:id`)
|
|
- `pages/VesselRegistrationReportPage.tsx` — manager report: KPI cards, status distribution, vessel-type breakdown, recent-10 table, renewal-tracking table (`/vessel-registration-report`)
|
|
|
|
Each app defines its **own separate mock array** (codebase convention: no shared domain types in `libs/`), and they don't sync — submitting in portal does not appear in the backoffice queue. That's the main thing a real API fixes. The two `VesselRegistration` shapes are already close (both modeled on the same field set) but not identical — see below.
|
|
|
|
## Data shape mismatch to resolve
|
|
|
|
- **Portal `VesselRegistration`** has no `documents[]` array — uploaded files live only as transient `File[]` in the wizard's component state (`docs: Record<string, File[] | null>` in `VesselRegistrationApplicationPage.tsx`) and are **never persisted** to the mock record; only file names are shown in the review step. **Known gap**: when wiring the real POST, the upload payload needs to be sent and stored — today it's dropped after submit.
|
|
- **Backoffice `VesselRegistration`** has `documents: RegistrationDocument[]` (`{key, label, fileName, fileType}`) so the officer review page has something to show — this is invented/seeded mock data, not real uploads. The real API should standardize on the **backoffice shape** (documents as first-class persisted records) since it's the superset the officer review page needs.
|
|
- **Certificates**: portal's `RegistrationCertificate` has a `downloads` counter (incremented client-side via `recordDownload()`); backoffice's does not track downloads. Real API should own download-count as a server-side audit log, not a client counter.
|
|
- **Correction targeting**: only the backoffice shape has `correctionFields?: string[]` (officer picks which fields/docs need fixing via a `MultiSelect`). Portal has no corresponding "these are the fields you need to fix" UI on the status page beyond the free-text `remarks` — worth adding when the real API returns `correctionFields`, so the owner can be pointed at the exact fields.
|
|
- **Status enum**: portal has 5 statuses (`Pending | Under Review | Correction Required | Approved | Rejected`); backoffice has 6 (adds `Resubmitted`, distinct from `Correction Required`, for after the owner has acted). The real API should use the backoffice's 6-value enum — portal's status page should render `Resubmitted` (currently unhandled — it'll fall through to no special UI).
|
|
|
|
## Suggested API surface
|
|
|
|
- `POST /vessel-registrations` — submit. Multipart body: all wizard fields (see `VesselRegistration` in either `mock.ts` for the full field list) + document files keyed by the `REQUIRED_DOCS[category]` slot key. Replaces `addRegistration()` in portal's `mock.ts`.
|
|
- `GET /vessel-registrations?ownerId=:id` — portal's "My Registrations" list (`VesselRegistrationPage.tsx`).
|
|
- `GET /vessel-registrations/:id` — used by portal's status page and backoffice's review page alike (both key off the same id).
|
|
- `GET /vessel-registrations` (officer, all + filters: `status`, `category`, `renewal`, `q`) — backoffice queue (`VesselRegistrationQueuePage.tsx`); filtering can move server-side or stay client-side over the fetched page as today.
|
|
- `PATCH /vessel-registrations/:id` — officer decision. Body: `{ status: 'Under Review' | 'Correction Required' | 'Rejected' | 'Approved', remarks?: string, correctionFields?: string[] }`. Replaces `applyDecision()` in backoffice's `mock.ts`. Backend should enforce remarks-required for `Correction Required`/`Rejected` (UI already gates this client-side, but don't trust it alone).
|
|
- `POST /vessel-registrations/:id/resubmit` — owner resubmit after correction (portal's "Resubmit Application" button on `VesselRegistrationStatusPage.tsx`, currently just routes back to the wizard with no state carried over — real flow should prefill the wizard from the existing record and only require the flagged fields/docs).
|
|
- On `PATCH .../:id` with `status: 'Approved'`: backend generates certificate records per `CERTIFICATES[category]` (1 for Inland, 4 for Sea-going) — replaces `generateCertificates()` in backoffice's `mock.ts`.
|
|
- `GET /vessel-registrations/:id/certificates/:certId/download` — real file download + audit log entry, replacing the shared `DEMO_PDF` base64 placeholder used by both apps' download buttons.
|
|
- `GET /vessel-registration-reports/summary` — KPIs + status distribution + type breakdown for `VesselRegistrationReportPage.tsx` (or compute client-side from a full `GET /vessel-registrations` if volume stays low — current mock computes everything client-side from the in-memory array).
|
|
- Document storage: real upload + signed URL for View, and a real download endpoint — today `getDocUrl()` in `VesselRegistrationReviewPage.tsx` (backoffice) fakes it with a hardcoded base64 PDF / placehold.co image, same pattern as the vessel-transfer feature.
|
|
- SMS/email: triggered server-side on submit and on every status change — UI currently just shows a toast claiming this happened (`notify.success('... SMS and email ...')`); no actual send anywhere in either app.
|
|
|
|
## Where to swap mock for real calls
|
|
|
|
- Portal: `apps/portal/src/app/features/vessel-registration/mock.ts` (whole file), plus the `useState`/local reads of `MOCK_REGISTRATIONS` in all three page files, and the transient `File[]` state in `VesselRegistrationApplicationPage.tsx` (needs to become a real multipart upload on submit).
|
|
- Backoffice: `apps/backoffice/src/app/features/vessel-registration/mock.ts` (whole file), plus the direct `applyDecision(record, ...)` / `generateCertificates(record)` mutations in `VesselRegistrationReviewPage.tsx` (swap for a mutation call + refetch/cache-invalidate), and the client-side aggregation in `VesselRegistrationReportPage.tsx` (swap for the summary endpoint above, or keep as a derived selector over cached query data).
|
|
- Both apps already have an RTK Query base (`@ema-platform/api` → `baseApi.injectEndpoints`, see `apps/portal/src/app/features/payment/api/payment-api.ts` or `apps/backoffice/src/app/features/certification/api/certification-api.ts`) — follow that pattern rather than the ad-hoc `useApiQuery`/`useApiMutation` escape hatch.
|