Files
emaui/apps/backoffice/src/app/features/license-register/pages/LicenseRegisterPage/columns.tsx
Nati 6852fc86c6 feat: implement permission-based access control across various pages and components
- Added RequirePermission component to manage access based on user permissions.
- Integrated permission checks in MySeaRecordsPage, SeafarerRegistrationPage, VesselRegistrationPage, WaiverPage, and PortalLayout.
- Updated router to enforce permissions for specific routes.
- Introduced PORTAL_PERMISSIONS and LICENSE_PERMISSIONS constants for consistent permission management.
- Enhanced usePermissions hook to fetch permissions from the server and determine access rights.
- Refactored UI components to conditionally render based on user permissions, improving security and user experience.
2026-08-13 12:58:11 +00:00

110 lines
2.9 KiB
TypeScript

import { Badge, Button, Text, Tooltip } from '@mantine/core';
import { IconShieldCog } from '@tabler/icons-react';
import type { AdvancedColumn } from '@ema-platform/ui';
import type { Bilingual, IssuedLicense } from '@ema-platform/api';
import { LICENSE_PERMISSIONS, RequirePermission } from '@ema-platform/auth';
const LICENSE_STATUS_COLORS: Record<string, string> = {
ACTIVE: 'green',
EXPIRED: 'yellow',
SUSPENDED: 'orange',
CANCELLED: 'red',
SUPERSEDED: 'gray',
};
export type LifecycleAction = 'suspend' | 'revoke' | 'reinstate';
/** Which lifecycle actions make sense from each current status. */
export function actionsFor(license: IssuedLicense): LifecycleAction[] {
switch (license.status) {
case 'ACTIVE':
case 'EXPIRED':
return ['suspend', 'revoke'];
case 'SUSPENDED':
return ['reinstate', 'revoke'];
default:
return [];
}
}
export function licenseRegisterColumns(
localized: (value: Bilingual | undefined) => string,
showDate: (date: string | null | undefined) => string,
handlers: { onStatus: (license: IssuedLicense) => void },
): AdvancedColumn<IssuedLicense>[] {
return [
{
header: 'Certificate №',
cell: ({ row }) => (
<Text size="sm" ff="monospace" fw={600}>
{row.original.certificateNumber}
</Text>
),
},
{
header: 'Type',
cell: ({ row }) => (
<Text size="sm">{localized(row.original.licenseType?.name)}</Text>
),
},
{
header: 'Holder',
cell: ({ row }) => <Text size="sm">{row.original.companyName ?? '—'}</Text>,
},
{
header: 'Issued',
cell: ({ row }) => (
<Text size="sm" c="dimmed">
{showDate(row.original.issueDate)}
</Text>
),
},
{
header: 'Expires',
cell: ({ row }) => (
<Text size="sm" c="dimmed">
{showDate(row.original.expiryDate)}
</Text>
),
},
{
header: 'Status',
cell: ({ row }) => (
<Badge
size="sm"
variant="light"
color={LICENSE_STATUS_COLORS[row.original.status] ?? 'gray'}
>
{row.original.status}
</Badge>
),
},
{
header: '',
label: 'Actions',
align: 'right',
cell: ({ row }) =>
actionsFor(row.original).length > 0 ? (
<RequirePermission
anyOf={[
LICENSE_PERMISSIONS.SUSPEND_LICENSE,
LICENSE_PERMISSIONS.CANCEL_LICENSE,
]}
hideOnly
>
<Tooltip label="Suspend / revoke / reinstate">
<Button
size="compact-xs"
variant="subtle"
leftSection={<IconShieldCog size={14} />}
onClick={() => handlers.onStatus(row.original)}
>
Status
</Button>
</Tooltip>
</RequirePermission>
) : null,
},
];
}