mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-26 19:12:50 +00:00
- 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.
110 lines
2.9 KiB
TypeScript
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,
|
|
},
|
|
];
|
|
}
|