feat(registratura): fix thread clear, close via conex entry

- Fix threadParentId clear: always show "Sterge" button even when parent not found in allEntries
- Bigger clear button with text label instead of tiny X icon
- Fallback display when parent not in current list (shows truncated ID)
- Close via conex: table/detail "Inchide" now creates a new reply entry that closes the original
- Header shows "Conex la BTG-XXX" + "Inchide originala" badge when closing via conex
- After saving the new conex entry, parent is auto-closed with resolution "finalizat"
- onClose signature changed from (id: string) to (entry: RegistryEntry) across table + detail

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-10 21:15:40 +02:00
parent f5e19ce3d1
commit 85077251f3
4 changed files with 68 additions and 21 deletions
@@ -72,6 +72,8 @@ export function RegistraturaModule() {
const [viewingEntry, setViewingEntry] = useState<RegistryEntry | null>(null);
/** Entry to reply to (conex) — pre-sets threadParentId in new form */
const [replyToEntry, setReplyToEntry] = useState<RegistryEntry | null>(null);
/** If set, the parent entry will be closed after saving the new conex entry */
const [closesEntryId, setClosesEntryId] = useState<string | null>(null);
const [closingId, setClosingId] = useState<string | null>(null);
const [linkCheckId, setLinkCheckId] = useState<string | null>(null);
@@ -138,6 +140,25 @@ export function RegistraturaModule() {
data: Omit<RegistryEntry, "id" | "number" | "createdAt" | "updatedAt">,
) => {
await addEntry(data);
// If this new entry closes a parent, close the parent automatically
if (closesEntryId) {
const parentEntry = allEntries.find((e) => e.id === closesEntryId);
if (parentEntry && parentEntry.status === "deschis") {
const closureInfo: ClosureInfo = {
resolution: "finalizat",
reason: "Inchis prin inregistrare conex",
closedBy: "",
closedAt: new Date().toISOString(),
hadActiveDeadlines:
(parentEntry.trackedDeadlines ?? []).some(
(d) => d.resolution === "pending",
),
};
await updateEntry(closesEntryId, { closureInfo });
await closeEntry(closesEntryId, false);
}
setClosesEntryId(null);
}
setReplyToEntry(null);
setViewMode("list");
};
@@ -157,6 +178,16 @@ export function RegistraturaModule() {
const handleReply = (entry: RegistryEntry) => {
setReplyToEntry(entry);
setClosesEntryId(null);
setViewingEntry(null);
setEditingEntry(null);
setViewMode("add");
};
/** Close entry via conex: create reply entry that closes the parent */
const handleCloseViaConex = (entry: RegistryEntry) => {
setReplyToEntry(entry);
setClosesEntryId(entry.id);
setViewingEntry(null);
setEditingEntry(null);
setViewMode("add");
@@ -217,6 +248,7 @@ export function RegistraturaModule() {
setViewMode("list");
setEditingEntry(null);
setReplyToEntry(null);
setClosesEntryId(null);
};
// ── Dashboard deadline resolve/chain handlers ──
@@ -394,7 +426,7 @@ export function RegistraturaModule() {
onView={handleView}
onEdit={handleEdit}
onDelete={handleDelete}
onClose={handleCloseRequest}
onClose={handleCloseViaConex}
onReply={handleReply}
/>
@@ -416,6 +448,11 @@ export function RegistraturaModule() {
<Badge variant="outline" className="text-xs text-blue-600 border-blue-300">
Raspuns
</Badge>
{closesEntryId && (
<Badge variant="outline" className="text-xs text-green-600 border-green-300">
Inchide originala
</Badge>
)}
</>
) : (
<>
@@ -467,7 +504,7 @@ export function RegistraturaModule() {
if (!open) setViewingEntry(null);
}}
onEdit={handleEdit}
onClose={handleCloseRequest}
onClose={handleCloseViaConex}
onDelete={handleDelete}
onReply={handleReply}
allEntries={allEntries}
@@ -48,7 +48,7 @@ interface RegistryEntryDetailProps {
open: boolean;
onOpenChange: (open: boolean) => void;
onEdit: (entry: RegistryEntry) => void;
onClose: (id: string) => void;
onClose: (entry: RegistryEntry) => void;
onDelete: (id: string) => void;
/** Create a new entry linked as reply (conex) to this entry */
onReply?: (entry: RegistryEntry) => void;
@@ -224,7 +224,7 @@ export function RegistryEntryDetail({
className="text-green-600 border-green-300 hover:bg-green-50 dark:border-green-700 dark:hover:bg-green-950/30"
onClick={() => {
onOpenChange(false);
onClose(entry.id);
onClose(entry);
}}
>
<CheckCircle2 className="mr-1.5 h-3.5 w-3.5" /> Inchide
@@ -1311,28 +1311,38 @@ export function RegistryEntryForm({
</Tooltip>
</TooltipProvider>
</Label>
{threadParent && (
{threadParentId && (
<div className="mt-1.5 flex items-center gap-2 rounded border border-primary/30 bg-primary/5 px-2 py-1.5 text-sm">
{threadParent ? (
<>
<Badge
variant={
threadParent.direction === "intrat" ? "default" : "secondary"
}
className="text-[10px]"
>
{threadParent.direction === "intrat" ? "" : ""}
{threadParent.direction === "intrat" ? "\u2193" : "\u2191"}
</Badge>
<span className="font-mono text-xs">{threadParent.number}</span>
<span className="truncate text-muted-foreground text-xs">
{threadParent.subject}
</span>
</>
) : (
<span className="text-xs text-muted-foreground italic">
Legat de o inregistrare (ID: {threadParentId.slice(0, 8)}...)
</span>
)}
<Button
type="button"
variant="ghost"
size="sm"
className="ml-auto h-6 w-6 p-0"
className="ml-auto h-7 px-2 text-xs text-destructive hover:text-destructive"
onClick={() => setThreadParentId("")}
title="Sterge legatura"
>
<X className="h-3.5 w-3.5" />
<X className="h-3.5 w-3.5 mr-0.5" />
Sterge
</Button>
</div>
)}
@@ -40,7 +40,7 @@ interface RegistryTableProps {
onView: (entry: RegistryEntry) => void;
onEdit: (entry: RegistryEntry) => void;
onDelete: (id: string) => void;
onClose: (id: string) => void;
onClose: (entry: RegistryEntry) => void;
/** Create a new entry linked as reply (conex) to this entry */
onReply?: (entry: RegistryEntry) => void;
}
@@ -495,7 +495,7 @@ export function RegistryTable({
className="h-7 w-7 text-green-600"
onClick={(e) => {
e.stopPropagation();
onClose(entry.id);
onClose(entry);
}}
title="Inchide"
>