fix(admin-ui): корректные бейджи в истории — future/active/expired по реальному времени
Раньше любую запись с validTo<9999 помечал 'закрыта'. Но запись с validTo в будущем — не закрытая, а либо ЗАПЛАНИРОВАННАЯ (validFrom > now), либо АКТИВНАЯ (validFrom <= now < validTo). User видел 'закрыта' на v3 которая ещё не настала. Теперь: - future: validFrom > now → бейдж 'запланирована' (info), точка orbit/horizon - active: validFrom <= now < validTo → бейдж 'активна' (success) если не latest - expired: validTo <= now → 'закрыта' (neutral), точка пустая - latest active: 'текущая' (primary), точка ultramarain Бессрочная запись (validTo year>=9999) больше не показывает 'действует до:' — у бессрочной нет конечной даты, отображение его смущало. i18n: новые ключи history.active / history.scheduled (RU/EN).
This commit is contained in:
@@ -35,33 +35,50 @@ export const RecordHistoryDrawer = ({ open, onClose, dictionaryName, businessKey
|
||||
<ol className="relative border-l-2 border-regolith pl-5 space-y-4">
|
||||
{data.map((rec, idx) => {
|
||||
const isLatest = idx === 0
|
||||
const closed = new Date(rec.validTo).getFullYear() < 9999
|
||||
// Нумерация по позиции в timeline: total..1, новая запись = total.
|
||||
// rec.version (JPA optimistic lock) растёт на UPDATE и у нескольких
|
||||
// закрытых может совпасть → дубли в UI. Index — стабильный 1-based счётчик.
|
||||
const displayVersion = data.length - idx
|
||||
const now = new Date()
|
||||
const from = new Date(rec.validFrom)
|
||||
const to = new Date(rec.validTo)
|
||||
const farFuture = to.getFullYear() >= 9999
|
||||
// Статус по реальному времени:
|
||||
// future — validFrom ещё впереди (запланирована)
|
||||
// active — сейчас в её диапазоне
|
||||
// expired — validTo уже прошла (закрыта)
|
||||
const status = from > now
|
||||
? 'future'
|
||||
: !farFuture && to <= now
|
||||
? 'expired'
|
||||
: 'active'
|
||||
return (
|
||||
<li key={rec.id} className="relative">
|
||||
<span
|
||||
className={`absolute -left-[27px] top-1 h-3 w-3 rounded-full border-2 ${
|
||||
isLatest
|
||||
isLatest && status === 'active'
|
||||
? 'bg-ultramarain border-ultramarain'
|
||||
: closed
|
||||
? 'bg-white border-carbon/40'
|
||||
: 'bg-aurora border-aurora'
|
||||
: status === 'future'
|
||||
? 'bg-orbit border-horizon'
|
||||
: status === 'expired'
|
||||
? 'bg-white border-carbon/40'
|
||||
: 'bg-aurora border-aurora'
|
||||
}`}
|
||||
/>
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<span className="text-sm font-primary text-ultramarain">v{displayVersion}</span>
|
||||
{isLatest && <Badge variant="primary">{t('history.current')}</Badge>}
|
||||
{!isLatest && closed && <Badge variant="neutral">{t('history.closed')}</Badge>}
|
||||
{isLatest && status === 'active' && (
|
||||
<Badge variant="primary">{t('history.current')}</Badge>
|
||||
)}
|
||||
{status === 'future' && <Badge variant="info">{t('history.scheduled')}</Badge>}
|
||||
{status === 'expired' && <Badge variant="neutral">{t('history.closed')}</Badge>}
|
||||
{status === 'active' && !isLatest && (
|
||||
<Badge variant="success">{t('history.active')}</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-2xs text-carbon/70 space-y-0.5">
|
||||
<div>
|
||||
<span className="font-mono">{t('history.validFrom')}:</span>{' '}
|
||||
{new Date(rec.validFrom).toLocaleString()}
|
||||
</div>
|
||||
{closed && (
|
||||
{!farFuture && (
|
||||
<div>
|
||||
<span className="font-mono">{t('history.validTo')}:</span>{' '}
|
||||
{new Date(rec.validTo).toLocaleString()}
|
||||
|
||||
Reference in New Issue
Block a user