diff --git a/apps/backoffice/src/app/features/license-review/config/actions.ts b/apps/backoffice/src/app/features/license-review/config/actions.ts index 8026cff66..cb18c5ca2 100644 --- a/apps/backoffice/src/app/features/license-review/config/actions.ts +++ b/apps/backoffice/src/app/features/license-review/config/actions.ts @@ -1,5 +1,4 @@ import type { ApplicationDetail, LicenseStatus } from '@ema-platform/api'; -import { LICENSE_PERMISSIONS as PERMISSIONS } from '@ema-platform/auth'; /** * Where an action is rendered. One tier per action, decided here rather than @@ -31,10 +30,11 @@ export type ActionId = | 'reject' | 'schedule-exam' | 'confirm-payment' + | 'schedule-issuance' + | 'issue-certificate' | 'print' | 'copy-link' | 'download-documents' - | 'generate-certificate' | 'audit-trail'; export interface ActionDefinition { @@ -211,6 +211,28 @@ export const ACTIONS: ActionDefinition[] = [ emphasis: 'filled', color: 'teal', }, + { + id: 'schedule-issuance', + tier: 'primary', + labelKey: 'review.actions.scheduleIssuance', + // Only reachable for a license type with `requiresIssuanceScheduling` — + // everything else cascades straight to CERTIFICATE_ISSUED and never + // shows PAYMENT_CONFIRMED with this action available (the server's + // `availableEvents` omits it there, same as the rest of this list). + from: ['PAYMENT_CONFIRMED'], + permissions: ['can:schedule:license-issuance'], + emphasis: 'filled', + color: 'cyan', + }, + { + id: 'issue-certificate', + tier: 'primary', + labelKey: 'review.actions.issueCertificate', + from: ['SCHEDULED'], + permissions: ['can:issue:license-certificate'], + emphasis: 'filled', + color: 'teal', + }, // ------------------------------------------------------------ secondary { id: 'print', tier: 'secondary', labelKey: 'review.actions.print' }, @@ -220,13 +242,6 @@ export const ACTIONS: ActionDefinition[] = [ tier: 'secondary', labelKey: 'review.actions.downloadDocuments', }, - { - id: 'generate-certificate', - tier: 'secondary', - labelKey: 'review.actions.generateCertificate', - from: ['CERTIFICATE_ISSUED'], - permissions: [PERMISSIONS.VIEW_APPLICATIONS], - }, { id: 'audit-trail', tier: 'secondary', labelKey: 'review.actions.auditTrail' }, ]; @@ -280,6 +295,8 @@ const WORKFLOW_EVENT_IDS = new Set([ 'request-adjustment', 'reject', 'confirm-payment', + 'schedule-issuance', + 'issue-certificate', ]); /** diff --git a/apps/backoffice/src/app/features/license-review/pages/LicenseQueuePage/index.tsx b/apps/backoffice/src/app/features/license-review/pages/LicenseQueuePage/index.tsx index 86806fca0..41ba5fd9e 100644 --- a/apps/backoffice/src/app/features/license-review/pages/LicenseQueuePage/index.tsx +++ b/apps/backoffice/src/app/features/license-review/pages/LicenseQueuePage/index.tsx @@ -33,7 +33,9 @@ import { useTranslation } from "react-i18next"; import { STATUS_LABELS, extractErrorMessage, + familyLabels, localized, + resolveFamilyKind, useClaimApplicationMutation, useGetAllApplicationsQuery, useGetAssignedToMeQuery, @@ -326,6 +328,19 @@ export function LicenseQueuePage() { onHelp: () => setHelpOpen(true), }); + // Deep-linked by type (`/licence-review/type/:typeCode`), so the queue + // title/labels read "Certificate applications" for a CoC queue and + // "Document applications" for a Seaman Book queue rather than always + // "Licence applications" — the All/Mine views have no single type and stay + // on the licence-flavoured default, matching today's behaviour. + const queueLabels = familyLabels(resolveFamilyKind(typeCode)); + const queueTitle = typeCode + ? t("queue.titleByFamily", { + family: queueLabels.typeLabel, + defaultValue: `${queueLabels.typeLabel} applications`, + }) + : t("queue.title", "Licence applications"); + const allSelected = items.length > 0 && selected.length === items.length; const sortIcon = urlFilter.sortDir === "DESC" ? ( @@ -390,7 +405,7 @@ export function LicenseQueuePage() {
- {t("queue.title", "Licence applications")} + {queueTitle} {typeCode && ( {t(`nav.type${typeCode}`, { defaultValue: typeCode })} @@ -474,7 +489,7 @@ export function LicenseQueuePage() { /> {!typeCode && (