From 442a1565fd532eb159fe4fbb53be66f06f1c0ad8 Mon Sep 17 00:00:00 2001 From: AI Assistant Date: Tue, 10 Mar 2026 22:41:14 +0200 Subject: [PATCH] feat: avize deadline restructure with interruption mechanism + comisie toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add "Necesita analiza in comisie" toggle for avize category (mirrors CJ toggle) - When OFF: auto-creates 5-day working limit for completari requests - When ON: no limit (institution can request completions anytime) - Add interruption mechanism: resolve aviz as "intrerupt" when institution requests completions → auto-creates new 15-day deadline from completions date - New resolution type "intrerupt" with yellow badge + chain support - Restructure avize catalog entries: - aviz-ac-15 (L50) and aviz-urbanism-30 (L350) now have chain to aviz-emitere-dupa-completari for interruption flow - aviz-mediu: updated hints about procedure closure prerequisite - aviz-cultura-comisie: 2-phase with auto-track depunere la comisie (30 days) - aeronautica, ISU, transport-eu: all get interruption chain - 3 new auto-track entries: aviz-completari-limit (5zl), aviz-emitere-dupa-completari (15zc), aviz-cultura-depunere-comisie (30zc) - New document type: "Convocare sedinta" - Info boxes in dialog explaining auto-track behavior + interruption mechanism Co-Authored-By: Claude Opus 4.6 --- .../components/deadline-add-dialog.tsx | 58 +++++++++- .../registratura/components/deadline-card.tsx | 8 ++ .../components/deadline-resolve-dialog.tsx | 55 +++++++--- .../components/registry-entry-form.tsx | 52 ++++++++- .../registratura/services/deadline-catalog.ts | 102 +++++++++++++++--- .../registratura/services/deadline-service.ts | 3 + src/modules/registratura/types.ts | 5 +- 7 files changed, 252 insertions(+), 31 deletions(-) diff --git a/src/modules/registratura/components/deadline-add-dialog.tsx b/src/modules/registratura/components/deadline-add-dialog.tsx index 5177f85..38117e9 100644 --- a/src/modules/registratura/components/deadline-add-dialog.tsx +++ b/src/modules/registratura/components/deadline-add-dialog.tsx @@ -32,11 +32,11 @@ interface DeadlineAddDialogProps { direction: RegistryDirection; /** Document type — filters which deadline categories are available */ documentType?: string; - /** Callback: typeId, startDate, options (CJ toggle etc.) */ + /** Callback: typeId, startDate, options (CJ / Comisie toggles etc.) */ onAdd: ( typeId: string, startDate: string, - options?: { isCJ?: boolean }, + options?: { isCJ?: boolean; isComisie?: boolean }, ) => void; } @@ -58,6 +58,7 @@ export function DeadlineAddDialog({ ); const [startDate, setStartDate] = useState(entryDate); const [isCJ, setIsCJ] = useState(false); + const [isComisie, setIsComisie] = useState(false); // ── Prelungire helper state ── const [cuIssueDate, setCuIssueDate] = useState(""); @@ -104,6 +105,7 @@ export function DeadlineAddDialog({ setSelectedType(null); setStartDate(entryDate); setIsCJ(false); + setIsComisie(false); setCuIssueDate(""); setCuDurationMonths(null); onOpenChange(false); @@ -127,6 +129,7 @@ export function DeadlineAddDialog({ setStep("category"); setSelectedCategory(null); setIsCJ(false); + setIsComisie(false); } else if (step === "date") { setStep("type"); setSelectedType(null); @@ -140,8 +143,10 @@ export function DeadlineAddDialog({ const isCUType = selectedType.id === "cu-emitere-l50" || selectedType.id === "cu-emitere-l350"; + const isAvizeType = selectedCategory === "avize"; onAdd(selectedType.id, startDate, { isCJ: isCUType ? isCJ : undefined, + isComisie: isAvizeType ? isComisie : undefined, }); handleClose(); }; @@ -238,6 +243,30 @@ export function DeadlineAddDialog({ )} + {/* Comisie toggle for Avize category */} + {selectedCategory === "avize" && ( + + )} +
{typesForCategory.map((typ) => (
)} + + {/* Info about auto-tracked deadlines for Avize */} + {selectedCategory === "avize" && ( +
+ +
+

Termene automate (in fundal):

+ {!isComisie && ( +

+ Limita solicitare completari (5 zile lucr.) — dupa acest + termen, institutia nu mai poate solicita completari. +

+ )} +

+ Comunicare catre beneficiar (1 zi) — obligatia institutiei + de a transmite avizul in ziua emiterii. +

+

+ Daca institutia solicita completari, rezolvati termenul ca + "Intrerupt" — se va crea automat termen nou de 15 + zile de la depunerea completarilor. +

+
+
+ )} )} diff --git a/src/modules/registratura/components/deadline-card.tsx b/src/modules/registratura/components/deadline-card.tsx index d63818f..08942ec 100644 --- a/src/modules/registratura/components/deadline-card.tsx +++ b/src/modules/registratura/components/deadline-card.tsx @@ -109,6 +109,14 @@ export function DeadlineCard({ )} + {/* Interruption badge */} + {deadline.resolution === "intrerupt" && ( +
+ + Intrerupt — completari solicitate + +
+ )}
{def?.isBackwardDeadline ? "Termen limita" : "Start"}:{" "} {formatDate(deadline.startDate)} diff --git a/src/modules/registratura/components/deadline-resolve-dialog.tsx b/src/modules/registratura/components/deadline-resolve-dialog.tsx index a80770b..bf93dd6 100644 --- a/src/modules/registratura/components/deadline-resolve-dialog.tsx +++ b/src/modules/registratura/components/deadline-resolve-dialog.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useState } from 'react'; +import { useState, useMemo } from 'react'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from '@/shared/components/ui/dialog'; @@ -18,9 +18,10 @@ interface DeadlineResolveDialogProps { onResolve: (resolution: DeadlineResolution, note: string, chainNext: boolean) => void; } -const RESOLUTION_OPTIONS: Array<{ value: DeadlineResolution; label: string }> = [ +const ALL_RESOLUTION_OPTIONS: Array<{ value: DeadlineResolution; label: string }> = [ { value: 'completed', label: 'Finalizat' }, { value: 'aprobat-tacit', label: 'Aprobat tacit' }, + { value: 'intrerupt', label: 'Intrerupt (completari solicitate)' }, { value: 'respins', label: 'Respins' }, { value: 'anulat', label: 'Anulat' }, ]; @@ -32,7 +33,22 @@ export function DeadlineResolveDialog({ open, deadline, onOpenChange, onResolve if (!deadline) return null; const def = getDeadlineType(deadline.typeId); - const hasChain = def?.chainNextTypeId && (resolution === 'completed' || resolution === 'aprobat-tacit'); + + // "intrerupt" option only for avize deadlines that have a chain (interruption mechanism) + const filteredOptions = useMemo(() => { + return ALL_RESOLUTION_OPTIONS.filter((opt) => { + if (opt.value === 'intrerupt') { + return def?.chainNextTypeId && def?.category === 'avize'; + } + return true; + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [def?.chainNextTypeId, def?.category]); + + // Chain fires on completed, aprobat-tacit, or intrerupt (for avize interruption) + const hasChain = def?.chainNextTypeId && ( + resolution === 'completed' || resolution === 'aprobat-tacit' || resolution === 'intrerupt' + ); const handleResolve = () => { onResolve(resolution, note, !!hasChain); @@ -51,16 +67,16 @@ export function DeadlineResolveDialog({ open, deadline, onOpenChange, onResolve { if (!o) handleClose(); }}> - Rezolvă — {def?.label ?? deadline.typeId} + Rezolva — {def?.label ?? deadline.typeId}
- +