feat(registratura): add Conex (reply) + Inchide buttons, reorder completari last
- Conex button on table rows (Reply icon, blue) — opens new entry with threadParentId pre-set + flipped direction - Conex button on detail panel — same behavior - Inchide button on table rows (CheckCircle2 icon, green) — only for open entries - replyTo prop on RegistryEntryForm: pre-sets threadParentId + direction flip (intrat→iesit, iesit→intrat) - Card header shows "Conex la BTG-0042/2026" with blue badge when replying - Completari moved to last position in deadline category order Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -70,6 +70,8 @@ export function RegistraturaModule() {
|
||||
const [viewMode, setViewMode] = useState<ViewMode>("list");
|
||||
const [editingEntry, setEditingEntry] = useState<RegistryEntry | null>(null);
|
||||
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);
|
||||
const [closingId, setClosingId] = useState<string | null>(null);
|
||||
const [linkCheckId, setLinkCheckId] = useState<string | null>(null);
|
||||
|
||||
@@ -136,6 +138,7 @@ export function RegistraturaModule() {
|
||||
data: Omit<RegistryEntry, "id" | "number" | "createdAt" | "updatedAt">,
|
||||
) => {
|
||||
await addEntry(data);
|
||||
setReplyToEntry(null);
|
||||
setViewMode("list");
|
||||
};
|
||||
|
||||
@@ -152,6 +155,13 @@ export function RegistraturaModule() {
|
||||
setViewingEntry(full ?? entry);
|
||||
};
|
||||
|
||||
const handleReply = (entry: RegistryEntry) => {
|
||||
setReplyToEntry(entry);
|
||||
setViewingEntry(null);
|
||||
setEditingEntry(null);
|
||||
setViewMode("add");
|
||||
};
|
||||
|
||||
const handleNavigateEntry = async (entry: RegistryEntry) => {
|
||||
const full = await loadFullEntry(entry.id);
|
||||
setEditingEntry(full ?? entry);
|
||||
@@ -206,6 +216,7 @@ export function RegistraturaModule() {
|
||||
const handleCancel = () => {
|
||||
setViewMode("list");
|
||||
setEditingEntry(null);
|
||||
setReplyToEntry(null);
|
||||
};
|
||||
|
||||
// ── Dashboard deadline resolve/chain handlers ──
|
||||
@@ -384,6 +395,7 @@ export function RegistraturaModule() {
|
||||
onEdit={handleEdit}
|
||||
onDelete={handleDelete}
|
||||
onClose={handleCloseRequest}
|
||||
onReply={handleReply}
|
||||
/>
|
||||
|
||||
{!loading && (
|
||||
@@ -398,15 +410,27 @@ export function RegistraturaModule() {
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
Înregistrare nouă
|
||||
<Badge variant="outline" className="text-xs">
|
||||
Nr. auto
|
||||
</Badge>
|
||||
{replyToEntry ? (
|
||||
<>
|
||||
Conex la {replyToEntry.number}
|
||||
<Badge variant="outline" className="text-xs text-blue-600 border-blue-300">
|
||||
Raspuns
|
||||
</Badge>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
Inregistrare noua
|
||||
<Badge variant="outline" className="text-xs">
|
||||
Nr. auto
|
||||
</Badge>
|
||||
</>
|
||||
)}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<RegistryEntryForm
|
||||
allEntries={allEntries}
|
||||
replyTo={replyToEntry ?? undefined}
|
||||
onSubmit={handleAdd}
|
||||
onCancel={handleCancel}
|
||||
onCreateContact={handleCreateContact}
|
||||
@@ -445,6 +469,7 @@ export function RegistraturaModule() {
|
||||
onEdit={handleEdit}
|
||||
onClose={handleCloseRequest}
|
||||
onDelete={handleDelete}
|
||||
onReply={handleReply}
|
||||
allEntries={allEntries}
|
||||
/>
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
User,
|
||||
X,
|
||||
Image as ImageIcon,
|
||||
Reply,
|
||||
} from "lucide-react";
|
||||
import { Button } from "@/shared/components/ui/button";
|
||||
import { Badge } from "@/shared/components/ui/badge";
|
||||
@@ -49,6 +50,8 @@ interface RegistryEntryDetailProps {
|
||||
onEdit: (entry: RegistryEntry) => void;
|
||||
onClose: (id: string) => void;
|
||||
onDelete: (id: string) => void;
|
||||
/** Create a new entry linked as reply (conex) to this entry */
|
||||
onReply?: (entry: RegistryEntry) => void;
|
||||
allEntries: RegistryEntry[];
|
||||
}
|
||||
|
||||
@@ -137,6 +140,7 @@ export function RegistryEntryDetail({
|
||||
onEdit,
|
||||
onClose,
|
||||
onDelete,
|
||||
onReply,
|
||||
allEntries,
|
||||
}: RegistryEntryDetailProps) {
|
||||
const [previewIndex, setPreviewIndex] = useState<number | null>(null);
|
||||
@@ -200,6 +204,19 @@ export function RegistryEntryDetail({
|
||||
>
|
||||
<Pencil className="mr-1.5 h-3.5 w-3.5" /> Editează
|
||||
</Button>
|
||||
{onReply && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
className="text-blue-600 border-blue-300 hover:bg-blue-50 dark:border-blue-700 dark:hover:bg-blue-950/30"
|
||||
onClick={() => {
|
||||
onOpenChange(false);
|
||||
onReply(entry);
|
||||
}}
|
||||
>
|
||||
<Reply className="mr-1.5 h-3.5 w-3.5" /> Conex
|
||||
</Button>
|
||||
)}
|
||||
{entry.status === "deschis" && (
|
||||
<Button
|
||||
size="sm"
|
||||
@@ -210,7 +227,7 @@ export function RegistryEntryDetail({
|
||||
onClose(entry.id);
|
||||
}}
|
||||
>
|
||||
<CheckCircle2 className="mr-1.5 h-3.5 w-3.5" /> Închide
|
||||
<CheckCircle2 className="mr-1.5 h-3.5 w-3.5" /> Inchide
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
|
||||
@@ -87,6 +87,8 @@ import { getDeadlineType } from "../services/deadline-catalog";
|
||||
|
||||
interface RegistryEntryFormProps {
|
||||
initial?: RegistryEntry;
|
||||
/** Pre-fill as reply (conex) to this entry — sets threadParentId, flips direction */
|
||||
replyTo?: RegistryEntry;
|
||||
allEntries?: RegistryEntry[];
|
||||
onSubmit: (
|
||||
data: Omit<RegistryEntry, "id" | "number" | "createdAt" | "updatedAt">,
|
||||
@@ -106,6 +108,7 @@ interface RegistryEntryFormProps {
|
||||
|
||||
export function RegistryEntryForm({
|
||||
initial,
|
||||
replyTo,
|
||||
allEntries,
|
||||
onSubmit,
|
||||
onCancel,
|
||||
@@ -150,8 +153,12 @@ export function RegistryEntryForm({
|
||||
return sorted;
|
||||
}, [docTypeTags, localCustomTypes]);
|
||||
|
||||
// When replyTo is provided, flip direction (intrat→iesit, iesit→intrat)
|
||||
const replyDirection: RegistryDirection | undefined = replyTo
|
||||
? replyTo.direction === "intrat" ? "iesit" : "intrat"
|
||||
: undefined;
|
||||
const [direction, setDirection] = useState<RegistryDirection>(
|
||||
initial?.direction ?? "intrat",
|
||||
initial?.direction ?? replyDirection ?? "intrat",
|
||||
);
|
||||
const defaultDocType = initial?.documentType ?? (direction === "intrat" ? "aviz" : "cerere");
|
||||
const [documentType, setDocumentType] = useState<DocumentType>(defaultDocType);
|
||||
@@ -182,7 +189,7 @@ export function RegistryEntryForm({
|
||||
initial?.assigneeContactId ?? "",
|
||||
);
|
||||
const [threadParentId, setThreadParentId] = useState(
|
||||
initial?.threadParentId ?? "",
|
||||
initial?.threadParentId ?? replyTo?.id ?? "",
|
||||
);
|
||||
const [notes, setNotes] = useState(initial?.notes ?? "");
|
||||
const [linkedEntryIds, setLinkedEntryIds] = useState<string[]>(
|
||||
|
||||
@@ -10,6 +10,8 @@ import {
|
||||
User,
|
||||
Settings2,
|
||||
Paperclip,
|
||||
Reply,
|
||||
CheckCircle2,
|
||||
} from "lucide-react";
|
||||
import { Button } from "@/shared/components/ui/button";
|
||||
import { Badge } from "@/shared/components/ui/badge";
|
||||
@@ -39,6 +41,8 @@ interface RegistryTableProps {
|
||||
onEdit: (entry: RegistryEntry) => void;
|
||||
onDelete: (id: string) => void;
|
||||
onClose: (id: string) => void;
|
||||
/** Create a new entry linked as reply (conex) to this entry */
|
||||
onReply?: (entry: RegistryEntry) => void;
|
||||
}
|
||||
|
||||
// ── Column definitions ──
|
||||
@@ -175,6 +179,7 @@ export function RegistryTable({
|
||||
onEdit,
|
||||
onDelete,
|
||||
onClose,
|
||||
onReply,
|
||||
}: RegistryTableProps) {
|
||||
const [visibleCols, setVisibleCols] = useState<Set<ColumnId>>(
|
||||
() => DEFAULT_VISIBLE,
|
||||
@@ -465,10 +470,38 @@ export function RegistryTable({
|
||||
e.stopPropagation();
|
||||
onEdit(entry);
|
||||
}}
|
||||
title="Editează"
|
||||
title="Editeaza"
|
||||
>
|
||||
<Pencil className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
{onReply && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-7 w-7 text-blue-600"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onReply(entry);
|
||||
}}
|
||||
title="Conex — creeaza raspuns"
|
||||
>
|
||||
<Reply className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
)}
|
||||
{entry.status === "deschis" && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-7 w-7 text-green-600"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onClose(entry.id);
|
||||
}}
|
||||
title="Inchide"
|
||||
>
|
||||
<CheckCircle2 className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -639,7 +639,7 @@ export const DIRECTION_CATEGORIES: Record<
|
||||
RegistryDirection,
|
||||
DeadlineCategory[]
|
||||
> = {
|
||||
iesit: ["certificat", "avize", "completari", "urbanism", "autorizare"],
|
||||
iesit: ["certificat", "avize", "urbanism", "autorizare", "completari"],
|
||||
intrat: ["contestatie"],
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user