feat(registratura): AC validity 12/24 months + reminder config in Ghid termene
- Add ACValidityPeriod type (12 | 24) and validityMonths field to ACValidityTracking - Replace hardcoded 12-month validity with configurable dropdown (12/24 luni) - Update computed dates, reminder counter, and tooltip to use selected period - Add "Configurare remindere si alerte" section in Ghid termene with: - Threshold table (urgent 5z, depasit 0z, CU alert 30z, AC monthly, prelungire 45z lucr, anuntare 10z cal, transmitere 1z) - Pause/resume explanation for clarification requests - Update AC expiry description to mention configurable 12/24 month validity Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,7 @@ import {
|
|||||||
import { Textarea } from "@/shared/components/ui/textarea";
|
import { Textarea } from "@/shared/components/ui/textarea";
|
||||||
import type {
|
import type {
|
||||||
ACValidityTracking,
|
ACValidityTracking,
|
||||||
|
ACValidityPeriod,
|
||||||
ACExecutionDuration,
|
ACExecutionDuration,
|
||||||
ACPhase,
|
ACPhase,
|
||||||
} from "../types";
|
} from "../types";
|
||||||
@@ -52,6 +53,11 @@ interface ACValidityTrackerProps {
|
|||||||
entryDate: string;
|
entryDate: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const VALIDITY_LABELS: Record<ACValidityPeriod, string> = {
|
||||||
|
12: "12 luni",
|
||||||
|
24: "24 luni",
|
||||||
|
};
|
||||||
|
|
||||||
const EXECUTION_LABELS: Record<ACExecutionDuration, string> = {
|
const EXECUTION_LABELS: Record<ACExecutionDuration, string> = {
|
||||||
6: "6 luni",
|
6: "6 luni",
|
||||||
12: "12 luni",
|
12: "12 luni",
|
||||||
@@ -158,9 +164,10 @@ export function ACValidityTracker({
|
|||||||
now.setHours(0, 0, 0, 0);
|
now.setHours(0, 0, 0, 0);
|
||||||
const today = now.toISOString().slice(0, 10);
|
const today = now.toISOString().slice(0, 10);
|
||||||
|
|
||||||
// 12-month validity period
|
// Configurable validity period (12 or 24 months)
|
||||||
|
const validityMonths = ac.validityMonths ?? 12;
|
||||||
const validityEnd = new Date(issuance);
|
const validityEnd = new Date(issuance);
|
||||||
validityEnd.setMonth(validityEnd.getMonth() + 12);
|
validityEnd.setMonth(validityEnd.getMonth() + validityMonths);
|
||||||
const validityEndStr = validityEnd.toISOString().slice(0, 10);
|
const validityEndStr = validityEnd.toISOString().slice(0, 10);
|
||||||
const daysToValidityEnd = daysBetween(today, validityEndStr);
|
const daysToValidityEnd = daysBetween(today, validityEndStr);
|
||||||
const monthsToValidityEnd = monthsBetween(today, validityEndStr);
|
const monthsToValidityEnd = monthsBetween(today, validityEndStr);
|
||||||
@@ -243,10 +250,10 @@ export function ACValidityTracker({
|
|||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent side="right" className="max-w-sm">
|
<TooltipContent side="right" className="max-w-sm">
|
||||||
<p className="text-xs">
|
<p className="text-xs">
|
||||||
Urmărirea completă a ciclului de viață al AC: valabilitate 12
|
Urmărirea completă a ciclului de viață al AC: valabilitate
|
||||||
luni, anunțare lucrări, documente obligatorii, durată
|
12 sau 24 luni (configurabil), anunțare lucrări, documente
|
||||||
execuție, prelungire. Conform Legii 50/1991 și normelor
|
obligatorii, durată execuție, prelungire. Conform Legii
|
||||||
aferente.
|
50/1991 și normelor aferente.
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -288,8 +295,8 @@ export function ACValidityTracker({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Issuance date + duration */}
|
{/* Issuance date + validity period + duration */}
|
||||||
<div className="grid gap-3 sm:grid-cols-3">
|
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||||
<div>
|
<div>
|
||||||
<Label className="text-xs">Data emitere AC</Label>
|
<Label className="text-xs">Data emitere AC</Label>
|
||||||
<Input
|
<Input
|
||||||
@@ -299,6 +306,28 @@ export function ACValidityTracker({
|
|||||||
className="mt-1"
|
className="mt-1"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label className="text-xs">Perioadă valabilitate</Label>
|
||||||
|
<Select
|
||||||
|
value={String(ac.validityMonths ?? 12)}
|
||||||
|
onValueChange={(v) =>
|
||||||
|
update({
|
||||||
|
validityMonths: parseInt(v, 10) as ACValidityPeriod,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="mt-1">
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{([12, 24] as ACValidityPeriod[]).map((d) => (
|
||||||
|
<SelectItem key={d} value={String(d)}>
|
||||||
|
{VALIDITY_LABELS[d]}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Label className="text-xs">Valabilitate până la</Label>
|
<Label className="text-xs">Valabilitate până la</Label>
|
||||||
<div className="mt-1 rounded border bg-muted/50 px-3 py-2 text-sm font-mono">
|
<div className="mt-1 rounded border bg-muted/50 px-3 py-2 text-sm font-mono">
|
||||||
@@ -633,7 +662,7 @@ export function ACValidityTracker({
|
|||||||
<span className="text-muted-foreground">
|
<span className="text-muted-foreground">
|
||||||
{ac.reminder.dismissed
|
{ac.reminder.dismissed
|
||||||
? "Remindere dezactivate"
|
? "Remindere dezactivate"
|
||||||
: `Reminder lunar activ (luna ${computedData.monthsToValidityEnd > 0 ? 12 - computedData.monthsToValidityEnd : 12}/12)`}
|
: `Reminder lunar activ (luna ${computedData.monthsToValidityEnd > 0 ? (ac.validityMonths ?? 12) - computedData.monthsToValidityEnd : (ac.validityMonths ?? 12)}/${ac.validityMonths ?? 12})`}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-1">
|
<div className="flex gap-1">
|
||||||
|
|||||||
@@ -257,6 +257,125 @@ export function DeadlineConfigOverview() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* ── Reminder & alert configuration ── */}
|
||||||
|
<div className="rounded-lg border bg-card">
|
||||||
|
<div className="flex items-center gap-3 px-4 py-3">
|
||||||
|
<Timer className="h-4 w-4 text-orange-500" />
|
||||||
|
<span className="text-sm font-medium">Configurare remindere si alerte</span>
|
||||||
|
</div>
|
||||||
|
<Separator />
|
||||||
|
<div className="px-4 py-3 space-y-4">
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
Praguri si intervale folosite de sistem pentru a genera alerte si notificari. Valorile se aplica automat tuturor inregistrarilor.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Thresholds table */}
|
||||||
|
<div className="overflow-hidden rounded-md border">
|
||||||
|
<table className="w-full text-xs">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-muted/50">
|
||||||
|
<th className="px-3 py-2 text-left font-medium">Parametru</th>
|
||||||
|
<th className="px-3 py-2 text-left font-medium">Valoare</th>
|
||||||
|
<th className="px-3 py-2 text-left font-medium">Descriere</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="divide-y">
|
||||||
|
<tr>
|
||||||
|
<td className="px-3 py-2 font-medium">Prag "Urgent"</td>
|
||||||
|
<td className="px-3 py-2">
|
||||||
|
<Badge variant="outline" className="bg-yellow-50 text-yellow-700 border-yellow-300 text-[10px] dark:bg-yellow-900/20 dark:text-yellow-300 dark:border-yellow-700">
|
||||||
|
5 zile
|
||||||
|
</Badge>
|
||||||
|
</td>
|
||||||
|
<td className="px-3 py-2 text-muted-foreground">
|
||||||
|
Termenele cu 5 sau mai putine zile ramase sunt marcate ca urgente (galben) si incluse in digest-ul zilnic.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-3 py-2 font-medium">Prag "Depasit"</td>
|
||||||
|
<td className="px-3 py-2">
|
||||||
|
<Badge variant="outline" className="bg-red-50 text-red-700 border-red-300 text-[10px] dark:bg-red-900/20 dark:text-red-300 dark:border-red-700">
|
||||||
|
0 zile
|
||||||
|
</Badge>
|
||||||
|
</td>
|
||||||
|
<td className="px-3 py-2 text-muted-foreground">
|
||||||
|
Termenele depasite (dupa data scadenta) sunt marcate rosu si raportate zilnic pana la rezolvare.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-3 py-2 font-medium">Alerta expirare CU</td>
|
||||||
|
<td className="px-3 py-2">
|
||||||
|
<Badge variant="outline" className="bg-amber-50 text-amber-700 border-amber-300 text-[10px] dark:bg-amber-900/20 dark:text-amber-300 dark:border-amber-700">
|
||||||
|
30 zile (implicit)
|
||||||
|
</Badge>
|
||||||
|
</td>
|
||||||
|
<td className="px-3 py-2 text-muted-foreground">
|
||||||
|
Se poate configura per inregistrare (campul "Zile alerta expirare"). Implicit 30 zile inainte de expirare.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-3 py-2 font-medium">Reminder lunar AC</td>
|
||||||
|
<td className="px-3 py-2">
|
||||||
|
<Badge variant="outline" className="bg-indigo-50 text-indigo-700 border-indigo-300 text-[10px] dark:bg-indigo-900/20 dark:text-indigo-300 dark:border-indigo-700">
|
||||||
|
Lunar
|
||||||
|
</Badge>
|
||||||
|
</td>
|
||||||
|
<td className="px-3 py-2 text-muted-foreground">
|
||||||
|
In faza de valabilitate AC, se afiseaza reminder lunar. Se poate amana (+1 luna) sau dezactiva (dismiss) per AC.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-3 py-2 font-medium">Cerere prelungire AC</td>
|
||||||
|
<td className="px-3 py-2">
|
||||||
|
<Badge variant="outline" className="bg-amber-50 text-amber-700 border-amber-300 text-[10px] dark:bg-amber-900/20 dark:text-amber-300 dark:border-amber-700">
|
||||||
|
45 zile lucr.
|
||||||
|
</Badge>
|
||||||
|
</td>
|
||||||
|
<td className="px-3 py-2 text-muted-foreground">
|
||||||
|
Alerta automata: cererea de prelungire trebuie depusa cu minim 45 zile lucratoare inainte de expirarea AC/executiei.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-3 py-2 font-medium">Anuntare lucrari AC</td>
|
||||||
|
<td className="px-3 py-2">
|
||||||
|
<Badge variant="outline" className="bg-green-50 text-green-700 border-green-300 text-[10px] dark:bg-green-900/20 dark:text-green-300 dark:border-green-700">
|
||||||
|
10 zile cal.
|
||||||
|
</Badge>
|
||||||
|
</td>
|
||||||
|
<td className="px-3 py-2 text-muted-foreground">
|
||||||
|
Lucrarile trebuie anuntate la Primarie si ISC cu minim 10 zile calendaristice inainte de incepere.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-3 py-2 font-medium">Transmitere in termen</td>
|
||||||
|
<td className="px-3 py-2">
|
||||||
|
<Badge variant="outline" className="border-dashed text-[10px] text-muted-foreground">
|
||||||
|
1 zi (fundal)
|
||||||
|
</Badge>
|
||||||
|
</td>
|
||||||
|
<td className="px-3 py-2 text-muted-foreground">
|
||||||
|
Verificare automata in fundal: actul administrativ trebuie transmis in 1 zi de la emitere. Se creeaza automat la inchidere.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Pause/resume info */}
|
||||||
|
<div className="rounded-md border bg-muted/20 px-3 py-2.5 space-y-1.5">
|
||||||
|
<p className="text-xs font-medium flex items-center gap-1.5">
|
||||||
|
<Clock className="h-3.5 w-3.5 text-blue-500" />
|
||||||
|
Suspendare / reluare termene (clarificari)
|
||||||
|
</p>
|
||||||
|
<p className="text-[11px] text-muted-foreground leading-relaxed">
|
||||||
|
Cand se primeste o solicitare de clarificari (document intrat conex), termenele active ale inregistrarii mama se suspenda automat.
|
||||||
|
La depunerea completarilor (document iesit conex), termenele se reiau, iar data scadenta se decaleaza cu numarul de zile suspendate.
|
||||||
|
Suspendarea se poate face si manual din fisa termenului.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* ── Document expiry overview ── */}
|
{/* ── Document expiry overview ── */}
|
||||||
<div className="rounded-lg border bg-card">
|
<div className="rounded-lg border bg-card">
|
||||||
<div className="flex items-center gap-3 px-4 py-3">
|
<div className="flex items-center gap-3 px-4 py-3">
|
||||||
@@ -280,7 +399,7 @@ export function DeadlineConfigOverview() {
|
|||||||
<div className="text-xs">
|
<div className="text-xs">
|
||||||
<span className="font-medium">Autorizatie de Construire (AC)</span>
|
<span className="font-medium">Autorizatie de Construire (AC)</span>
|
||||||
<span className="ml-1 text-muted-foreground">
|
<span className="ml-1 text-muted-foreground">
|
||||||
— validitate 12 luni de la emitere, executie 6/12/24/36 luni, prelungire +24 luni.
|
— valabilitate 12 sau 24 luni (configurabil per AC), executie 6/12/24/36 luni, prelungire +24 luni.
|
||||||
Reminder lunar automat (snooze/dismiss disponibil).
|
Reminder lunar automat (snooze/dismiss disponibil).
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -226,6 +226,8 @@ export interface ACReminder {
|
|||||||
dismissed: boolean;
|
dismissed: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ACValidityPeriod = 12 | 24;
|
||||||
|
|
||||||
/** Full AC validity tracking state */
|
/** Full AC validity tracking state */
|
||||||
export interface ACValidityTracking {
|
export interface ACValidityTracking {
|
||||||
/** Whether AC tracking is enabled for this entry */
|
/** Whether AC tracking is enabled for this entry */
|
||||||
@@ -234,6 +236,8 @@ export interface ACValidityTracking {
|
|||||||
issuanceDate: string;
|
issuanceDate: string;
|
||||||
/** Current phase */
|
/** Current phase */
|
||||||
phase: ACPhase;
|
phase: ACPhase;
|
||||||
|
/** Validity period in months (default 12, can be 24 for special cases) */
|
||||||
|
validityMonths?: ACValidityPeriod;
|
||||||
/** Execution duration selected (months) */
|
/** Execution duration selected (months) */
|
||||||
executionDuration: ACExecutionDuration;
|
executionDuration: ACExecutionDuration;
|
||||||
/** Date works were announced to City Hall & ISC */
|
/** Date works were announced to City Hall & ISC */
|
||||||
|
|||||||
Reference in New Issue
Block a user