diff --git a/apps/backoffice/src/app/features/certificate-designer/components/DesignerToolbar.tsx b/apps/backoffice/src/app/features/certificate-designer/components/DesignerToolbar.tsx index 3a8296005..4ab644bc6 100644 --- a/apps/backoffice/src/app/features/certificate-designer/components/DesignerToolbar.tsx +++ b/apps/backoffice/src/app/features/certificate-designer/components/DesignerToolbar.tsx @@ -14,6 +14,8 @@ interface Props { onRankChange: (id: string | null) => void; /** Shown for context only; edited on Certificate Requirements → Behaviour. */ validityMonths: number; + /** Non-null when the type is configured in days rather than months. */ + validityDays?: number | null; canEdit: boolean; onNewVersion: () => void; } @@ -27,6 +29,7 @@ export function DesignerToolbar({ rankId, onRankChange, validityMonths, + validityDays, canEdit, onNewVersion, }: Props) { @@ -75,11 +78,15 @@ export function DesignerToolbar({ {typeId && ( - {t('designer.validityYears', 'Valid for (years)')} + {t('designer.validity', 'Valid for')} - {Number((validityMonths / 12).toFixed(2))} + {validityDays != null + ? t('designer.validityDays', '{{count}} days', { count: validityDays }) + : t('designer.validityMonths', '{{count}} months', { + count: validityMonths, + })} {t('designer.validityEditedOn', '— set on Certificate Requirements → Behaviour')} diff --git a/apps/backoffice/src/app/features/certificate-designer/pages/CertificateDesignerPage.tsx b/apps/backoffice/src/app/features/certificate-designer/pages/CertificateDesignerPage.tsx index 8f5597f49..b46d68689 100644 --- a/apps/backoffice/src/app/features/certificate-designer/pages/CertificateDesignerPage.tsx +++ b/apps/backoffice/src/app/features/certificate-designer/pages/CertificateDesignerPage.tsx @@ -163,6 +163,7 @@ export function CertificateDesignerPage() { draft.setSelectedId(null); }} validityMonths={selectedType?.validityMonths ?? 12} + validityDays={selectedType?.validityDays ?? null} canEdit={canEdit} onNewVersion={startNewVersion} /> diff --git a/apps/backoffice/src/app/features/certificate-requirements/components/BehaviorTab.tsx b/apps/backoffice/src/app/features/certificate-requirements/components/BehaviorTab.tsx index 6acfd90b4..d756d1d38 100644 --- a/apps/backoffice/src/app/features/certificate-requirements/components/BehaviorTab.tsx +++ b/apps/backoffice/src/app/features/certificate-requirements/components/BehaviorTab.tsx @@ -38,6 +38,7 @@ interface Draft { minSeaTimeDays: number | null; capitalThreshold: number | null; validityMonths: number; + validityDays: number | null; renewalWindowDays: number; expiryReminderDays: number[]; requiresOperatorMode: boolean; @@ -66,6 +67,7 @@ function toDraft(licenseType: LicenseType): Draft { ? null : Number(licenseType.capitalThreshold), validityMonths: licenseType.validityMonths ?? 12, + validityDays: licenseType.validityDays ?? null, renewalWindowDays: licenseType.renewalWindowDays ?? 60, expiryReminderDays: licenseType.expiryReminderDays ?? [60, 30, 7], requiresOperatorMode: licenseType.requiresOperatorMode ?? true, @@ -266,25 +268,52 @@ export function BehaviorTab({ licenseType }: { licenseType: LicenseType }) {
- {/* Stored in months, edited in years: a licence term is a number of - years to everyone who works with one. Half-years stay expressible. */} - - set('validityMonths', Math.round(Number(v || 0) * 12) || draft.validityMonths) - } - min={0.5} - max={20} - step={0.5} - decimalScale={1} - allowNegative={false} - disabled={!canEdit} - /> + {/* Amount + unit rather than a years box that silently divides by 12: + the seed says `validityMonths: 12` and this now says "12 Months", + so the two read the same. Months advance the calendar (issued on + the 31st, expires on the 31st); days are for terms shorter than a + month can express. */} + + { + const next = typeof v === 'number' ? v : 0; + if (!next) return; + if (draft.validityDays !== null) set('validityDays', next); + else set('validityMonths', next); + }} + // Matches the server's ranges, so the box cannot offer a value the + // save would reject: 1–3650 days, or 6–240 months. + min={draft.validityDays !== null ? 1 : 6} + max={draft.validityDays !== null ? 3650 : 240} + allowNegative={false} + disabled={!canEdit} + flex={1} + /> +