feat: disable unavailable licenses in catalogue and add explanation with link to operations management

This commit is contained in:
estifanos
2026-08-28 07:38:47 +00:00
parent 82b316e90b
commit 7f69cb2cba
3 changed files with 50 additions and 11 deletions

View File

@@ -20,6 +20,7 @@ import {
IconBuildingWarehouse,
IconChevronRight,
IconFileText,
IconLock,
IconShieldOff,
IconShip,
IconTrendingUp,
@@ -277,8 +278,14 @@ function LicenseTypeCard({
withBorder
radius="md"
padding="md"
style={{ cursor: 'pointer', height: '100%' }}
onClick={() => onSelect(type)}
style={{
cursor: canApply ? 'pointer' : 'default',
height: '100%',
// Dimmed rather than hidden: browse-all exists so an applicant can see
// what else the authority issues. It just must not look actionable.
opacity: canApply ? 1 : 0.6,
}}
onClick={canApply ? () => onSelect(type) : undefined}
>
<Stack gap="xs" justify="space-between" h="100%">
<Box>
@@ -286,11 +293,19 @@ function LicenseTypeCard({
<Text fw={600} size="sm" lh={1.35}>
{localized(type.name)}
</Text>
<IconChevronRight
size={16}
color="var(--mantine-color-dimmed)"
style={{ flexShrink: 0, marginTop: 2 }}
/>
{canApply ? (
<IconChevronRight
size={16}
color="var(--mantine-color-dimmed)"
style={{ flexShrink: 0, marginTop: 2 }}
/>
) : (
<IconLock
size={16}
color="var(--mantine-color-dimmed)"
style={{ flexShrink: 0, marginTop: 2 }}
/>
)}
</Group>
{type.description && (
<Text size="xs" c="dimmed" mt={6} lineClamp={3}>
@@ -329,13 +344,33 @@ function LicenseTypeCard({
mt="sm"
size="xs"
variant="light"
color={canApply ? undefined : 'gray'}
disabled={!canApply}
rightSection={<IconArrowRight size={14} />}
>
{canApply
? t('licensing.catalogue.startApplication')
: t('licensing.catalogue.addToOperations')}
{t('licensing.catalogue.startApplication')}
</Button>
{/* A disabled button on its own only says "no". This says why, and
where to go about it — the licence is offered against a declared
mode of operation, and the server refuses a create for one the
applicant has not declared. */}
{!canApply && (
<Text size="xs" c="dimmed" mt={6} ta="center">
{t('licensing.catalogue.lockedHint')}{' '}
<Anchor
size="xs"
component="button"
type="button"
onClick={(event) => {
// The card is inert while locked, but the anchor inside it
// must not re-trigger anything if that ever changes.
event.stopPropagation();
onSelect(type);
}}
>
{t('licensing.catalogue.addToOperations')}
</Anchor>
</Text>
)}
</RequirePermission>
</Box>
</Stack>

View File

@@ -831,6 +831,8 @@ export const am: Translations = {
evaluationOnly: 'ግምገማ ብቻ',
startApplication: 'ማመልከቻ ጀምር',
addToOperations: 'ወደ ስራ ዘርፎቼ ጨምር',
lockedHint:
'ከተመዘገቡ የስራ ዘርፎችዎ ውስጥ ስላልሆነ እስካሁን ማመልከት አይችሉም።',
},
},

View File

@@ -831,6 +831,8 @@ export const en = {
evaluationOnly: 'Evaluation only',
startApplication: 'Start application',
addToOperations: 'Add to my operations',
lockedHint:
'Not one of your declared operations, so it cannot be applied for yet.',
},
},