'use client'; import Link from 'next/link'; import { useQuery } from '@tanstack/react-query'; import { apiFetch } from '../../../lib/api'; import { useSession } from '../../../components/session-provider'; interface Document { id: string; filename: string; classification: string; expiresAt: string | null; ocrStatus: string | null; createdAt: string; } interface Contract { id: string; title: string; contractType: string; status: string; endDate: string | null; } const B = '/dashboard'; function daysUntil(dateStr: string): number { return Math.ceil((new Date(dateStr).getTime() - Date.now()) / 86400_000); } function ExpiryBadge({ days }: { days: number }) { if (days < 0) return EXPIRAT {Math.abs(days)}z; if (days <= 7) return {days}z; if (days <= 30) return {days}z; return {days}z; } export default function ExpirationsPage() { const { activeTenant } = useSession(); const tenantId = activeTenant?.tenantId ?? ''; const { data: docs = [], isLoading: docsLoading } = useQuery({ queryKey: ['docs-exp', tenantId], queryFn: () => apiFetch('/v1/documents?limit=200', { tenantId }), enabled: Boolean(tenantId), staleTime: 120_000, }); const { data: contracts = [], isLoading: cLoading } = useQuery({ queryKey: ['contracts-exp', tenantId], queryFn: () => apiFetch('/v1/contracts?status=active', { tenantId }), enabled: Boolean(tenantId), staleTime: 120_000, }); const now = new Date(); const in90 = new Date(now.getTime() + 90 * 86400_000); const expiringDocs = docs .filter((d) => d.expiresAt && new Date(d.expiresAt) <= in90) .sort((a, b) => new Date(a.expiresAt!).getTime() - new Date(b.expiresAt!).getTime()); const expiringContracts = contracts .filter((c) => c.endDate && new Date(c.endDate) <= in90) .sort((a, b) => new Date(a.endDate!).getTime() - new Date(b.endDate!).getTime()); const totalExpiring = expiringDocs.length + expiringContracts.length; const critical = expiringDocs.filter((d) => daysUntil(d.expiresAt!) <= 7).length + expiringContracts.filter((c) => daysUntil(c.endDate!) <= 7).length; const isLoading = docsLoading || cLoading; return (

Expirări

{isLoading ? 'Se încarcă…' : `${totalExpiring} expirări în 90 zile${critical > 0 ? ` · ${critical} critice` : ''}`}

{!isLoading && totalExpiring === 0 && (

Nicio expirare în următoarele 90 zile.

)} {!isLoading && totalExpiring > 0 && ( <> {/* Summary chips */}
{[ { label: 'Azi–7 zile', count: expiringDocs.filter((d) => daysUntil(d.expiresAt!) <= 7).length + expiringContracts.filter((c) => daysUntil(c.endDate!) <= 7).length, cls: 'text-signal-danger bg-signal-danger/5 border-signal-danger/20' }, { label: '8–30 zile', count: expiringDocs.filter((d) => { const n = daysUntil(d.expiresAt!); return n > 7 && n <= 30; }).length + expiringContracts.filter((c) => { const n = daysUntil(c.endDate!); return n > 7 && n <= 30; }).length, cls: 'text-signal-warn bg-signal-warn/5 border-signal-warn/20' }, { label: '31–90 zile', count: expiringDocs.filter((d) => daysUntil(d.expiresAt!) > 30).length + expiringContracts.filter((c) => daysUntil(c.endDate!) > 30).length, cls: 'text-ink-faint bg-muted/30 border-border/50' }, ].map(({ label, count, cls }) => count > 0 ? (

{count}

{label}

) : null)}
{/* Expiring contracts */} {expiringContracts.length > 0 && (

Contracte

Administrează →
{expiringContracts.map((c) => { const days = daysUntil(c.endDate!); return (

{c.title}

{c.contractType}

{c.endDate}

); })}
)} {/* Expiring documents */} {expiringDocs.length > 0 && (

Documente

Bibliotecă →
{expiringDocs.map((d) => { const days = daysUntil(d.expiresAt!); return (

{d.filename}

{d.classification}

{d.expiresAt?.slice(0, 10)}

); })}
)} )}
); }