feat: add account type synchronization to operations form based on selected license types

This commit is contained in:
estifanos
2026-08-18 11:23:30 +00:00
parent 581eac7466
commit 2257989821
3 changed files with 57 additions and 3 deletions

View File

@@ -20,6 +20,7 @@ import {
useGetMyOperatorTypesQuery,
useUpdateMyOperatorTypesMutation,
} from '@ema-platform/api';
import { useUpdateMyAccountTypeMutation } from '@ema-platform/auth';
import { notify, ModalFooter } from '@ema-platform/ui';
import { useDateDisplayer } from '@ema-platform/shared';
@@ -35,6 +36,29 @@ const PERSONAL_REGISTRATION_KEYS = [
'VESSEL_REGISTRATION',
];
/**
* Declared modes -> portal account type.
*
* The account type is what the server computes portal permissions from, and
* therefore what decides which services appear in the sidebar at all. Modes
* of operation grant nothing on their own: an applicant who declared
* "freight forwarder" here was still left on the seafarer default and never
* saw the logistics or vessel entries.
*
* One type per account against a multi-select, so the widest capability wins:
* a company representative who also sails still needs the company services,
* and the seafarer side stays reachable through their own registration.
*/
function accountTypeFor(keys: string[]): string | null {
if (keys.some((key) => !PERSONAL_REGISTRATION_KEYS.includes(key))) {
// Historical enum value for the logistics company representative.
return 'FRIGHTER';
}
if (keys.includes('VESSEL_REGISTRATION')) return 'VESSEL_OWNER';
if (keys.includes('SEAFARER_REGISTRATION')) return 'SEAFARER';
return null;
}
/**
* The applicant's modes of operation — what they do, and therefore which
* licences the portal offers them.
@@ -58,6 +82,7 @@ export function OperationsFormContent({
const { data: catalogue, isLoading: loadingTypes } = useGetLicenseTypesQuery();
const { data: mine, isLoading: loadingMine } = useGetMyOperatorTypesQuery();
const [save, { isLoading: saving }] = useUpdateMyOperatorTypesMutation();
const [setAccountType] = useUpdateMyAccountTypeMutation();
const localized = useLocalized();
const declaredIds = useMemo(
@@ -118,14 +143,25 @@ export function OperationsFormContent({
async function persist() {
try {
await save({ licenseTypeIds: selected }).unwrap();
const selectedKeys = options
.filter((t) => selected.includes(t.id))
.map((t) => t.key);
const type = accountTypeFor(selectedKeys);
if (type) {
// Refused for a registered seafarer, whose type the authority owns
// (`registered_seafarer_type_is_fixed`), and for staff. The modes are
// already stored either way, so a refusal here is not the applicant's
// problem to see.
await setAccountType({ type }).unwrap().catch(() => undefined);
}
setConfirmingRemoval(false);
notify.success(
t('profileOperations.updateSuccessBody'),
t('profileOperations.updateSuccessTitle'),
);
onSaved?.(
options.filter((t) => selected.includes(t.id)).map((t) => t.key),
);
onSaved?.(selectedKeys);
} catch (err) {
notify.error(extractErrorMessage(err), t('profileOperations.updateErrorTitle'));
}