Adding more functionalities for all the license types

This commit is contained in:
Mulu Mehari
2026-08-07 11:50:07 +03:00
parent 35fb817b4b
commit 7c968c7093
66 changed files with 6468 additions and 3518 deletions

View File

@@ -308,6 +308,39 @@ export const licensingApi = baseApi
}),
// ------------------------------------------------------------ licences
/**
* Public QR-code verification (US-PORTAL-008). No auth required —
* the endpoint returns only what a verifier needs to trust the
* document, never the holder's contact details.
*/
verifyCertificate: builder.query<
{
valid: boolean;
reason?: string;
certificateNumber?: string;
licenseType?: string | null;
companyName?: string | null;
issueDate?: string;
expiryDate?: string;
status?: string;
},
string
>({
query: (code) => ({ url: `/licenses/verify/${code}` }),
}),
/** The licence register for enforcement officers. */
getLicenses: builder.query<
Paginated<IssuedLicense>,
{ search?: string } | void
>({
query: (args) => ({
url: '/licenses',
params: args?.search ? { search: args.search } : undefined,
}),
providesTags: () => [listTag('License')],
}),
getMyLicenses: builder.query<Paginated<IssuedLicense>, void>({
query: () => ({ url: '/licenses/mine' }),
providesTags: () => [listTag('License')],
@@ -693,12 +726,24 @@ export const licensingApi = baseApi
recordInspectionResult: builder.mutation<
Inspection,
{ inspectionId: string; applicationId: string; result: 'PASSED' | 'FAILED'; findings: string }
{
inspectionId: string;
applicationId: string;
result: 'PASSED' | 'FAILED';
findings: string;
/** Structured per-item outcomes (office, warehouse, vehicles, …). */
checklist?: {
key: string;
label: string;
outcome: 'PASS' | 'FAIL' | 'NEEDS_CORRECTION';
note?: string;
}[];
}
>({
query: ({ inspectionId, result, findings }) => ({
query: ({ inspectionId, result, findings, checklist }) => ({
url: `/inspections/${inspectionId}/result`,
method: 'PATCH',
body: { result, findings },
body: { result, findings, ...(checklist?.length ? { checklist } : {}) },
}),
invalidatesTags: (_r, error, { applicationId }) =>
error ? [] : [itemTag('LicenseApplication', applicationId), listTag('Inspection')],
@@ -724,6 +769,7 @@ export const licensingApi = baseApi
});
export const {
useVerifyCertificateQuery,
useGetLicenseTypesQuery,
useGetLicenseCategoriesQuery,
useUpdateLicenseFeesMutation,
@@ -736,6 +782,7 @@ export const {
useBypassPaymentMutation,
useGetPaymentCapabilitiesQuery,
useGetMyLicensesQuery,
useGetLicensesQuery,
useGetCertificateUrlMutation,
useGetApplicationPaymentQuery,
usePatchSectionMutation,

View File

@@ -18,7 +18,13 @@ const BASE_API_URL =
* attach them to, and nothing can be lost if the browser closes mid-wizard.
*/
export async function uploadDocument(params: {
ownerType: 'APPLICATION' | 'APPLICATION_STAFF' | 'INSPECTION' | 'LICENSE';
ownerType:
| 'APPLICATION'
| 'APPLICATION_STAFF'
| 'INSPECTION'
| 'LICENSE'
| 'SEA_SERVICE_RECORD'
| 'MEDICAL_CERTIFICATE';
ownerId: string;
documentKey: string;
file: File;
@@ -210,6 +216,14 @@ export interface WizardStep {
export function buildWizardSteps(
sections: FormSectionConfig[],
formData: Record<string, Record<string, unknown>>,
options?: {
/**
* Whether this licence type has staff-role requirements at all. Types
* without any (seafarer registration) skip the Staff step entirely
* instead of showing an empty page.
*/
hasStaff?: boolean;
},
): WizardStep[] {
const visible = [...sections]
.filter((section) => conditionHolds(section.showWhen, formData))
@@ -259,7 +273,9 @@ export function buildWizardSteps(
return [
...formSteps,
{ key: 'staff', label: 'Staff', kind: 'staff', sections: [] },
...(options?.hasStaff === false
? []
: [{ key: 'staff', label: 'Staff', kind: 'staff', sections: [] } as WizardStep]),
{ key: 'documents', label: 'Documents', kind: 'documents', sections: [] },
{ key: 'review', label: 'Review', kind: 'review', sections: reviewSections },
];

View File

@@ -77,7 +77,8 @@ export interface FormSectionConfig {
export type LicenseCategory =
| 'CARGO_FREIGHT'
| 'SHIPPING_AGENCY'
| 'INVESTMENT';
| 'INVESTMENT'
| 'MARITIME_PERSONNEL';
export interface LicenseCategoryDefinition {
key: LicenseCategory;
@@ -119,6 +120,12 @@ export interface LicenseType {
inspectionRequired: boolean;
issuesCertificate: boolean;
renewalEnabled: boolean;
/**
* False for person-centric registrations (seafarer): they are open to any
* authenticated applicant, live outside the operator catalogue, and have
* their own entry points.
*/
requiresOperatorMode: boolean;
formSchema: { sections: FormSectionConfig[] };
isActive: boolean;
/** Display order set by EMA; lower comes first. */