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

@@ -0,0 +1,2 @@
export * from './seafarer.types';
export * from './seafarer-api';

View File

@@ -0,0 +1,188 @@
import { baseApi } from '../../base-api';
import type {
CreateMedicalCertificate,
CreateSeaServiceRecord,
MedicalCertificate,
SeaServiceRecord,
SeaTimeSummary,
SeafarerStatus,
} from './seafarer.types';
const TAGS = ['SeaServiceRecord', 'MedicalCertificate'] as const;
const listTag = (type: (typeof TAGS)[number]) => ({ type, id: 'LIST' }) as const;
/**
* The seafarer's evidence shelf: sea-service records and medical
* certificates (modules 05/06). Registration itself rides the licensing
* endpoints — a SEAFARER_REGISTRATION application through `licensingApi`.
*/
export const seafarerApi = baseApi
.enhanceEndpoints({ addTagTypes: TAGS })
.injectEndpoints({
endpoints: (builder) => ({
// ---------------------------------------------------------- sea service
getMySeaServiceRecords: builder.query<SeaServiceRecord[], void>({
query: () => ({ url: '/sea-service-records/mine' }),
providesTags: () => [listTag('SeaServiceRecord')],
}),
getSeaServiceForProfile: builder.query<SeaServiceRecord[], string>({
query: (profileId) => ({
url: `/sea-service-records/profile/${profileId}`,
}),
providesTags: () => [listTag('SeaServiceRecord')],
}),
createSeaServiceRecord: builder.mutation<
SeaServiceRecord,
CreateSeaServiceRecord
>({
query: (body) => ({ url: '/sea-service-records', method: 'POST', body }),
invalidatesTags: (_r, error) =>
error ? [] : [listTag('SeaServiceRecord')],
}),
updateSeaServiceRecord: builder.mutation<
SeaServiceRecord,
{ id: string; body: Partial<CreateSeaServiceRecord> }
>({
query: ({ id, body }) => ({
url: `/sea-service-records/${id}`,
method: 'PUT',
body,
}),
invalidatesTags: (_r, error) =>
error ? [] : [listTag('SeaServiceRecord')],
}),
deleteSeaServiceRecord: builder.mutation<unknown, string>({
query: (id) => ({ url: `/sea-service-records/${id}`, method: 'DELETE' }),
invalidatesTags: (_r, error) =>
error ? [] : [listTag('SeaServiceRecord')],
}),
// -------------------------------------------------------------- medical
getMyMedicalCertificates: builder.query<MedicalCertificate[], void>({
query: () => ({ url: '/medical-certificates/mine' }),
providesTags: () => [listTag('MedicalCertificate')],
}),
getMedicalForProfile: builder.query<MedicalCertificate[], string>({
query: (profileId) => ({
url: `/medical-certificates/profile/${profileId}`,
}),
providesTags: () => [listTag('MedicalCertificate')],
}),
createMedicalCertificate: builder.mutation<
MedicalCertificate,
CreateMedicalCertificate
>({
query: (body) => ({ url: '/medical-certificates', method: 'POST', body }),
invalidatesTags: (_r, error) =>
error ? [] : [listTag('MedicalCertificate')],
}),
updateMedicalCertificate: builder.mutation<
MedicalCertificate,
{ id: string; body: Partial<CreateMedicalCertificate> }
>({
query: ({ id, body }) => ({
url: `/medical-certificates/${id}`,
method: 'PUT',
body,
}),
invalidatesTags: (_r, error) =>
error ? [] : [listTag('MedicalCertificate')],
}),
deleteMedicalCertificate: builder.mutation<unknown, string>({
query: (id) => ({ url: `/medical-certificates/${id}`, method: 'DELETE' }),
invalidatesTags: (_r, error) =>
error ? [] : [listTag('MedicalCertificate')],
}),
// -------------------------------------------------------- verification
getPendingSeaService: builder.query<SeaServiceRecord[], void>({
query: () => ({ url: '/sea-service-records/pending' }),
providesTags: () => [listTag('SeaServiceRecord')],
}),
getPendingMedical: builder.query<MedicalCertificate[], void>({
query: () => ({ url: '/medical-certificates/pending' }),
providesTags: () => [listTag('MedicalCertificate')],
}),
verifySeaServiceRecord: builder.mutation<
SeaServiceRecord,
{ id: string; outcome: 'VERIFIED' | 'REJECTED'; remark?: string }
>({
query: ({ id, ...body }) => ({
url: `/sea-service-records/${id}/verify`,
method: 'POST',
body,
}),
invalidatesTags: (_r, error) =>
error ? [] : [listTag('SeaServiceRecord')],
}),
verifyMedicalCertificate: builder.mutation<
MedicalCertificate,
{ id: string; outcome: 'VERIFIED' | 'REJECTED'; remark?: string }
>({
query: ({ id, ...body }) => ({
url: `/medical-certificates/${id}/verify`,
method: 'POST',
body,
}),
invalidatesTags: (_r, error) =>
error ? [] : [listTag('MedicalCertificate')],
}),
getMySeaTime: builder.query<SeaTimeSummary, void>({
query: () => ({ url: '/sea-service-records/mine/sea-time' }),
providesTags: () => [listTag('SeaServiceRecord')],
}),
getSeaTimeForProfile: builder.query<SeaTimeSummary, string>({
query: (profileId) => ({
url: `/sea-service-records/profile/${profileId}/sea-time`,
}),
providesTags: () => [listTag('SeaServiceRecord')],
}),
// ----------------------------------------------- registry (backoffice)
/** US-SEA-013: suspend, reinstate or close with a mandatory reason. */
updateSeafarerStatus: builder.mutation<
unknown,
{ profileId: string; status: SeafarerStatus; reason: string }
>({
query: ({ profileId, ...body }) => ({
url: `/profiles/${profileId}/seafarer-status`,
method: 'POST',
body,
}),
}),
}),
});
export const {
useGetPendingSeaServiceQuery,
useGetPendingMedicalQuery,
useVerifySeaServiceRecordMutation,
useVerifyMedicalCertificateMutation,
useGetMySeaTimeQuery,
useGetSeaTimeForProfileQuery,
useGetMySeaServiceRecordsQuery,
useGetSeaServiceForProfileQuery,
useCreateSeaServiceRecordMutation,
useUpdateSeaServiceRecordMutation,
useDeleteSeaServiceRecordMutation,
useGetMyMedicalCertificatesQuery,
useGetMedicalForProfileQuery,
useCreateMedicalCertificateMutation,
useUpdateMedicalCertificateMutation,
useDeleteMedicalCertificateMutation,
useUpdateSeafarerStatusMutation,
} = seafarerApi;

View File

@@ -0,0 +1,78 @@
export type SeafarerRecordStatus = 'SUBMITTED' | 'VERIFIED' | 'REJECTED';
export type MedicalFitness = 'FIT' | 'FIT_WITH_RESTRICTIONS' | 'UNFIT';
export type SeafarerDepartment = 'DECK' | 'ENGINE' | 'CATERING';
export type SeafarerStatus = 'ACTIVE' | 'INACTIVE' | 'PENDING' | 'SUSPENDED';
/** One engagement aboard one vessel (US-SSM-001). */
/** Denormalised owner summary, present on the verification queues. */
export interface SeafarerProfileSummary {
id: string;
firstName: string | null;
middleName: string | null;
lastName: string | null;
seafarerNumber?: string | null;
}
export interface SeaServiceRecord {
id: string;
profileId: string;
profile?: SeafarerProfileSummary;
vesselName: string;
imoNumber: string | null;
vesselType: string | null;
flagState: string | null;
grossTonnage: string | number | null;
rank: string;
engagementDate: string;
dischargeDate: string;
dutiesDescription: string | null;
status: SeafarerRecordStatus;
verifiedById: string | null;
verifiedAt: string | null;
verificationRemark: string | null;
createdAt: string;
}
export interface CreateSeaServiceRecord {
vesselName: string;
imoNumber?: string;
vesselType?: string;
flagState?: string;
grossTonnage?: number;
rank: string;
engagementDate: string;
dischargeDate: string;
dutiesDescription?: string;
}
/** An STCW medical fitness certificate (US-SSM-006). */
export interface MedicalCertificate {
id: string;
profileId: string;
profile?: SeafarerProfileSummary;
issuerName: string;
certificateNumber: string | null;
issueDate: string;
expiryDate: string;
fitnessStatus: MedicalFitness;
restrictions: string | null;
status: SeafarerRecordStatus;
verifiedById: string | null;
verifiedAt: string | null;
verificationRemark: string | null;
createdAt: string;
}
export interface CreateMedicalCertificate {
issuerName: string;
certificateNumber?: string;
issueDate: string;
expiryDate: string;
fitnessStatus?: MedicalFitness;
restrictions?: string;
}
export interface SeaTimeSummary {
totalDays: number;
verifiedRecords: number;
}