feat(registratura): auto-close monitoring on resolved, inline check, edit tracking
- Auto-deactivate monitoring when status is 'solutionat' or 'respins' - 'Verifica acum' shows result inline (no page reload/close) - 'Modifica' button opens edit dialog to fix petitioner/regNumber/date - Show monitoring section even when inactive (final status visible) - Display tracking config info (nr, date, petitioner) in detail view Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -166,11 +166,21 @@ export function RegistryEntryDetail({
|
|||||||
const [previewIndex, setPreviewIndex] = useState<number | null>(null);
|
const [previewIndex, setPreviewIndex] = useState<number | null>(null);
|
||||||
const [copiedPath, setCopiedPath] = useState<string | null>(null);
|
const [copiedPath, setCopiedPath] = useState<string | null>(null);
|
||||||
const [monitorConfigOpen, setMonitorConfigOpen] = useState(false);
|
const [monitorConfigOpen, setMonitorConfigOpen] = useState(false);
|
||||||
|
const [monitorEditMode, setMonitorEditMode] = useState(false);
|
||||||
|
|
||||||
// Auto-detect if recipient matches a known authority
|
// Authority for existing tracking or auto-detected from recipient
|
||||||
|
const trackingAuthority = useMemo(() => {
|
||||||
|
if (!entry) return undefined;
|
||||||
|
if (entry.externalStatusTracking) {
|
||||||
|
return getAuthority(entry.externalStatusTracking.authorityId) ?? undefined;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}, [entry]);
|
||||||
|
|
||||||
|
// Auto-detect if recipient matches a known authority (only when no tracking)
|
||||||
const matchedAuthority = useMemo(() => {
|
const matchedAuthority = useMemo(() => {
|
||||||
if (!entry) return undefined;
|
if (!entry) return undefined;
|
||||||
if (entry.externalStatusTracking?.active) return undefined;
|
if (entry.externalStatusTracking) return undefined;
|
||||||
if (!entry.recipientRegNumber) return undefined;
|
if (!entry.recipientRegNumber) return undefined;
|
||||||
return findAuthorityForContact(entry.recipient);
|
return findAuthorityForContact(entry.recipient);
|
||||||
}, [entry]);
|
}, [entry]);
|
||||||
@@ -757,14 +767,47 @@ export function RegistryEntryDetail({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ── External status monitoring ── */}
|
{/* ── External status monitoring ── */}
|
||||||
{entry.externalStatusTracking?.active && (
|
{entry.externalStatusTracking && (
|
||||||
<ExternalStatusSection
|
<>
|
||||||
entry={entry}
|
<ExternalStatusSection
|
||||||
/>
|
entry={entry}
|
||||||
|
onEdit={() => {
|
||||||
|
setMonitorEditMode(true);
|
||||||
|
setMonitorConfigOpen(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{trackingAuthority && (
|
||||||
|
<StatusMonitorConfig
|
||||||
|
open={monitorConfigOpen && monitorEditMode}
|
||||||
|
onOpenChange={(open) => {
|
||||||
|
setMonitorConfigOpen(open);
|
||||||
|
if (!open) setMonitorEditMode(false);
|
||||||
|
}}
|
||||||
|
entry={entry}
|
||||||
|
authority={trackingAuthority}
|
||||||
|
editMode
|
||||||
|
onActivate={async (tracking) => {
|
||||||
|
try {
|
||||||
|
await fetch("/api/registratura", {
|
||||||
|
method: "PUT",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({
|
||||||
|
id: entry.id,
|
||||||
|
updates: { externalStatusTracking: tracking },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
window.location.reload();
|
||||||
|
} catch {
|
||||||
|
// Best effort
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ── Auto-detect: suggest monitoring activation ── */}
|
{/* ── Auto-detect: suggest monitoring activation ── */}
|
||||||
{matchedAuthority && !entry.externalStatusTracking?.active && (
|
{matchedAuthority && !entry.externalStatusTracking && (
|
||||||
<div className="rounded-lg border border-dashed border-blue-300 dark:border-blue-700 bg-blue-50/50 dark:bg-blue-950/20 p-3">
|
<div className="rounded-lg border border-dashed border-blue-300 dark:border-blue-700 bg-blue-50/50 dark:bg-blue-950/20 p-3">
|
||||||
<div className="flex items-start gap-2">
|
<div className="flex items-start gap-2">
|
||||||
<Radio className="h-4 w-4 text-blue-500 mt-0.5 shrink-0" />
|
<Radio className="h-4 w-4 text-blue-500 mt-0.5 shrink-0" />
|
||||||
@@ -780,7 +823,10 @@ export function RegistryEntryDetail({
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="mt-2 h-6 text-xs"
|
className="mt-2 h-6 text-xs"
|
||||||
onClick={() => setMonitorConfigOpen(true)}
|
onClick={() => {
|
||||||
|
setMonitorEditMode(false);
|
||||||
|
setMonitorConfigOpen(true);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
Configureaza monitorizarea
|
Configureaza monitorizarea
|
||||||
</Button>
|
</Button>
|
||||||
@@ -788,12 +834,11 @@ export function RegistryEntryDetail({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<StatusMonitorConfig
|
<StatusMonitorConfig
|
||||||
open={monitorConfigOpen}
|
open={monitorConfigOpen && !monitorEditMode}
|
||||||
onOpenChange={setMonitorConfigOpen}
|
onOpenChange={setMonitorConfigOpen}
|
||||||
entry={entry}
|
entry={entry}
|
||||||
authority={matchedAuthority}
|
authority={matchedAuthority}
|
||||||
onActivate={async (tracking) => {
|
onActivate={async (tracking) => {
|
||||||
// Save tracking to entry via API
|
|
||||||
try {
|
try {
|
||||||
await fetch("/api/registratura", {
|
await fetch("/api/registratura", {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
@@ -892,26 +937,54 @@ const STATUS_COLORS: Record<ExternalDocStatus, string> = {
|
|||||||
necunoscut: "bg-muted text-muted-foreground",
|
necunoscut: "bg-muted text-muted-foreground",
|
||||||
};
|
};
|
||||||
|
|
||||||
function ExternalStatusSection({ entry }: { entry: RegistryEntry }) {
|
function ExternalStatusSection({
|
||||||
|
entry,
|
||||||
|
onEdit,
|
||||||
|
}: {
|
||||||
|
entry: RegistryEntry;
|
||||||
|
onEdit: () => void;
|
||||||
|
}) {
|
||||||
const tracking = entry.externalStatusTracking;
|
const tracking = entry.externalStatusTracking;
|
||||||
if (!tracking) return null;
|
if (!tracking) return null;
|
||||||
|
|
||||||
const [checking, setChecking] = useState(false);
|
const [checking, setChecking] = useState(false);
|
||||||
|
const [checkResult, setCheckResult] = useState<{
|
||||||
|
changed: boolean;
|
||||||
|
error: string | null;
|
||||||
|
newStatus?: string;
|
||||||
|
} | null>(null);
|
||||||
const [showHistory, setShowHistory] = useState(false);
|
const [showHistory, setShowHistory] = useState(false);
|
||||||
|
const [liveTracking, setLiveTracking] = useState(tracking);
|
||||||
const authority = getAuthority(tracking.authorityId);
|
const authority = getAuthority(tracking.authorityId);
|
||||||
|
|
||||||
const handleManualCheck = useCallback(async () => {
|
const handleManualCheck = useCallback(async () => {
|
||||||
setChecking(true);
|
setChecking(true);
|
||||||
|
setCheckResult(null);
|
||||||
try {
|
try {
|
||||||
await fetch("/api/registratura/status-check/single", {
|
const res = await fetch("/api/registratura/status-check/single", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ entryId: entry.id }),
|
body: JSON.stringify({ entryId: entry.id }),
|
||||||
});
|
});
|
||||||
// Reload page to show updated status
|
const data = (await res.json()) as {
|
||||||
window.location.reload();
|
changed: boolean;
|
||||||
} catch {
|
error: string | null;
|
||||||
// Ignore — user will see if it worked on reload
|
newStatus?: string;
|
||||||
|
tracking?: typeof tracking;
|
||||||
|
};
|
||||||
|
setCheckResult({
|
||||||
|
changed: data.changed,
|
||||||
|
error: data.error,
|
||||||
|
newStatus: data.newStatus,
|
||||||
|
});
|
||||||
|
if (data.tracking) {
|
||||||
|
setLiveTracking(data.tracking);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setCheckResult({
|
||||||
|
changed: false,
|
||||||
|
error: err instanceof Error ? err.message : "Eroare conexiune",
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setChecking(false);
|
setChecking(false);
|
||||||
}
|
}
|
||||||
@@ -928,80 +1001,121 @@ function ExternalStatusSection({ entry }: { entry: RegistryEntry }) {
|
|||||||
return `acum ${days}z`;
|
return `acum ${days}z`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const t = liveTracking;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center justify-between mb-2">
|
<div className="flex items-center justify-between mb-2">
|
||||||
<h3 className="text-xs font-semibold text-muted-foreground uppercase tracking-wider">
|
<h3 className="text-xs font-semibold text-muted-foreground uppercase tracking-wider">
|
||||||
Monitorizare status extern
|
Monitorizare status extern
|
||||||
|
{!t.active && (
|
||||||
|
<span className="ml-1.5 text-[10px] font-normal normal-case">(oprita)</span>
|
||||||
|
)}
|
||||||
</h3>
|
</h3>
|
||||||
<Button
|
<div className="flex gap-1">
|
||||||
variant="ghost"
|
<Button
|
||||||
size="sm"
|
variant="ghost"
|
||||||
className="h-6 px-2 text-xs"
|
size="sm"
|
||||||
onClick={handleManualCheck}
|
className="h-6 px-2 text-xs"
|
||||||
disabled={checking}
|
onClick={onEdit}
|
||||||
>
|
>
|
||||||
<RefreshCw className={cn("h-3 w-3 mr-1", checking && "animate-spin")} />
|
<Pencil className="h-3 w-3 mr-1" />
|
||||||
{checking ? "Se verifică..." : "Verifică acum"}
|
Modifica
|
||||||
</Button>
|
</Button>
|
||||||
|
{t.active && (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="h-6 px-2 text-xs"
|
||||||
|
onClick={handleManualCheck}
|
||||||
|
disabled={checking}
|
||||||
|
>
|
||||||
|
<RefreshCw className={cn("h-3 w-3 mr-1", checking && "animate-spin")} />
|
||||||
|
{checking ? "Se verifica..." : "Verifica acum"}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Inline check result */}
|
||||||
|
{checkResult && (
|
||||||
|
<div className={cn(
|
||||||
|
"rounded border px-2.5 py-1.5 text-xs mb-2",
|
||||||
|
checkResult.error
|
||||||
|
? "border-red-200 bg-red-50 text-red-700 dark:border-red-800 dark:bg-red-950/30 dark:text-red-400"
|
||||||
|
: checkResult.changed
|
||||||
|
? "border-green-200 bg-green-50 text-green-700 dark:border-green-800 dark:bg-green-950/30 dark:text-green-400"
|
||||||
|
: "border-muted bg-muted/30 text-muted-foreground",
|
||||||
|
)}>
|
||||||
|
{checkResult.error
|
||||||
|
? `Eroare: ${checkResult.error}`
|
||||||
|
: checkResult.changed
|
||||||
|
? `Status actualizat: ${EXTERNAL_STATUS_LABELS[checkResult.newStatus as ExternalDocStatus] ?? checkResult.newStatus}`
|
||||||
|
: "Nicio schimbare detectata"}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{/* Authority + status badge */}
|
{/* Authority + status badge */}
|
||||||
<div className="flex items-center gap-2 flex-wrap">
|
<div className="flex items-center gap-2 flex-wrap">
|
||||||
<span className="text-xs text-muted-foreground">
|
<span className="text-xs text-muted-foreground">
|
||||||
{authority?.name ?? tracking.authorityId}
|
{authority?.name ?? t.authorityId}
|
||||||
</span>
|
</span>
|
||||||
<Badge className={cn("text-[10px] px-1.5 py-0", STATUS_COLORS[tracking.semanticStatus])}>
|
<Badge className={cn("text-[10px] px-1.5 py-0", STATUS_COLORS[t.semanticStatus])}>
|
||||||
<Radio className="mr-0.5 inline h-2.5 w-2.5" />
|
<Radio className="mr-0.5 inline h-2.5 w-2.5" />
|
||||||
{EXTERNAL_STATUS_LABELS[tracking.semanticStatus]}
|
{EXTERNAL_STATUS_LABELS[t.semanticStatus]}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Last check time */}
|
{/* Last check time */}
|
||||||
{tracking.lastCheckAt && (
|
{t.lastCheckAt && (
|
||||||
<p className="text-[10px] text-muted-foreground">
|
<p className="text-[10px] text-muted-foreground">
|
||||||
Ultima verificare: {relativeTime(tracking.lastCheckAt)}
|
Ultima verificare: {relativeTime(t.lastCheckAt)}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Error state */}
|
{/* Error state */}
|
||||||
{tracking.lastError && (
|
{t.lastError && (
|
||||||
<p className="text-[10px] text-red-500">{tracking.lastError}</p>
|
<p className="text-[10px] text-red-500">{t.lastError}</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Latest status row */}
|
{/* Latest status row */}
|
||||||
{tracking.lastStatusRow && (
|
{t.lastStatusRow && (
|
||||||
<div className="rounded border bg-muted/30 p-2 text-xs space-y-1">
|
<div className="rounded border bg-muted/30 p-2 text-xs space-y-1">
|
||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
<span>
|
<span>
|
||||||
<span className="text-muted-foreground">Sursa:</span>{" "}
|
<span className="text-muted-foreground">Sursa:</span>{" "}
|
||||||
{tracking.lastStatusRow.sursa}
|
{t.lastStatusRow.sursa}
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<span className="text-muted-foreground">→</span>{" "}
|
<span className="text-muted-foreground">→</span>{" "}
|
||||||
{tracking.lastStatusRow.destinatie}
|
{t.lastStatusRow.destinatie}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{tracking.lastStatusRow.modRezolvare && (
|
{t.lastStatusRow.modRezolvare && (
|
||||||
<div>
|
<div>
|
||||||
<span className="text-muted-foreground">Rezolvare:</span>{" "}
|
<span className="text-muted-foreground">Rezolvare:</span>{" "}
|
||||||
<span className="font-medium">{tracking.lastStatusRow.modRezolvare}</span>
|
<span className="font-medium">{t.lastStatusRow.modRezolvare}</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{tracking.lastStatusRow.comentarii && (
|
{t.lastStatusRow.comentarii && (
|
||||||
<div className="text-muted-foreground">
|
<div className="text-muted-foreground">
|
||||||
{tracking.lastStatusRow.comentarii}
|
{t.lastStatusRow.comentarii}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="text-muted-foreground">
|
<div className="text-muted-foreground">
|
||||||
{tracking.lastStatusRow.dataVenire} {tracking.lastStatusRow.oraVenire}
|
{t.lastStatusRow.dataVenire} {t.lastStatusRow.oraVenire}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Tracking config info */}
|
||||||
|
<div className="text-[10px] text-muted-foreground">
|
||||||
|
Nr: {t.regNumber} | Data: {t.regDate} | Deponent: {t.petitionerName}
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* History toggle */}
|
{/* History toggle */}
|
||||||
{tracking.history.length > 0 && (
|
{t.history.length > 0 && (
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
className="flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground transition-colors"
|
className="flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground transition-colors"
|
||||||
@@ -1012,12 +1126,12 @@ function ExternalStatusSection({ entry }: { entry: RegistryEntry }) {
|
|||||||
) : (
|
) : (
|
||||||
<ChevronDown className="h-3 w-3" />
|
<ChevronDown className="h-3 w-3" />
|
||||||
)}
|
)}
|
||||||
Istoric ({tracking.history.length} schimbări)
|
Istoric ({t.history.length} schimbari)
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{showHistory && (
|
{showHistory && (
|
||||||
<div className="mt-1 space-y-1.5 max-h-48 overflow-y-auto">
|
<div className="mt-1 space-y-1.5 max-h-48 overflow-y-auto">
|
||||||
{[...tracking.history].reverse().map((change, i) => (
|
{[...t.history].reverse().map((change, i) => (
|
||||||
<div
|
<div
|
||||||
key={`${change.timestamp}-${i}`}
|
key={`${change.timestamp}-${i}`}
|
||||||
className="rounded border bg-muted/20 p-1.5 text-[10px]"
|
className="rounded border bg-muted/20 p-1.5 text-[10px]"
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ interface StatusMonitorConfigProps {
|
|||||||
entry: RegistryEntry;
|
entry: RegistryEntry;
|
||||||
authority: AuthorityConfig;
|
authority: AuthorityConfig;
|
||||||
onActivate: (tracking: ExternalStatusTracking) => void;
|
onActivate: (tracking: ExternalStatusTracking) => void;
|
||||||
|
/** When true, pre-fills from existing tracking data for editing */
|
||||||
|
editMode?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function StatusMonitorConfig({
|
export function StatusMonitorConfig({
|
||||||
@@ -37,30 +39,35 @@ export function StatusMonitorConfig({
|
|||||||
entry,
|
entry,
|
||||||
authority,
|
authority,
|
||||||
onActivate,
|
onActivate,
|
||||||
|
editMode,
|
||||||
}: StatusMonitorConfigProps) {
|
}: StatusMonitorConfigProps) {
|
||||||
|
const existing = entry.externalStatusTracking;
|
||||||
const [petitionerName, setPetitionerName] = useState("");
|
const [petitionerName, setPetitionerName] = useState("");
|
||||||
const [regNumber, setRegNumber] = useState(
|
const [regNumber, setRegNumber] = useState(
|
||||||
entry.recipientRegNumber ?? "",
|
entry.recipientRegNumber ?? "",
|
||||||
);
|
);
|
||||||
const [regDate, setRegDate] = useState("");
|
const [regDate, setRegDate] = useState("");
|
||||||
|
|
||||||
// Convert YYYY-MM-DD to dd.mm.yyyy
|
// Pre-fill: edit mode uses existing tracking, otherwise entry fields
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (entry.recipientRegDate) {
|
if (editMode && existing) {
|
||||||
const parts = entry.recipientRegDate.split("-");
|
setPetitionerName(existing.petitionerName);
|
||||||
if (parts.length === 3) {
|
setRegNumber(existing.regNumber);
|
||||||
setRegDate(`${parts[2]}.${parts[1]}.${parts[0]}`);
|
setRegDate(existing.regDate);
|
||||||
|
} else {
|
||||||
|
setRegNumber(entry.recipientRegNumber ?? "");
|
||||||
|
if (entry.recipientRegDate) {
|
||||||
|
const parts = entry.recipientRegDate.split("-");
|
||||||
|
if (parts.length === 3) {
|
||||||
|
setRegDate(`${parts[2]}.${parts[1]}.${parts[0]}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
const saved = localStorage.getItem(
|
||||||
|
`status-monitor-petitioner:${authority.id}`,
|
||||||
|
);
|
||||||
|
if (saved) setPetitionerName(saved);
|
||||||
}
|
}
|
||||||
}, [entry.recipientRegDate]);
|
}, [editMode, existing, entry.recipientRegNumber, entry.recipientRegDate, authority.id]);
|
||||||
|
|
||||||
// Load saved petitioner name from localStorage
|
|
||||||
useEffect(() => {
|
|
||||||
const saved = localStorage.getItem(
|
|
||||||
`status-monitor-petitioner:${authority.id}`,
|
|
||||||
);
|
|
||||||
if (saved) setPetitionerName(saved);
|
|
||||||
}, [authority.id]);
|
|
||||||
|
|
||||||
const canActivate =
|
const canActivate =
|
||||||
petitionerName.trim().length >= 3 &&
|
petitionerName.trim().length >= 3 &&
|
||||||
@@ -74,19 +81,28 @@ export function StatusMonitorConfig({
|
|||||||
petitionerName.trim(),
|
petitionerName.trim(),
|
||||||
);
|
);
|
||||||
|
|
||||||
const tracking: ExternalStatusTracking = {
|
const tracking: ExternalStatusTracking = editMode && existing
|
||||||
authorityId: authority.id,
|
? {
|
||||||
petitionerName: petitionerName.trim(),
|
...existing,
|
||||||
regNumber: regNumber.trim(),
|
petitionerName: petitionerName.trim(),
|
||||||
regDate: regDate.trim(),
|
regNumber: regNumber.trim(),
|
||||||
lastCheckAt: null,
|
regDate: regDate.trim(),
|
||||||
lastStatusRow: null,
|
active: true,
|
||||||
statusHash: "",
|
lastError: null,
|
||||||
semanticStatus: "necunoscut",
|
}
|
||||||
history: [],
|
: {
|
||||||
active: true,
|
authorityId: authority.id,
|
||||||
lastError: null,
|
petitionerName: petitionerName.trim(),
|
||||||
};
|
regNumber: regNumber.trim(),
|
||||||
|
regDate: regDate.trim(),
|
||||||
|
lastCheckAt: null,
|
||||||
|
lastStatusRow: null,
|
||||||
|
statusHash: "",
|
||||||
|
semanticStatus: "necunoscut",
|
||||||
|
history: [],
|
||||||
|
active: true,
|
||||||
|
lastError: null,
|
||||||
|
};
|
||||||
|
|
||||||
onActivate(tracking);
|
onActivate(tracking);
|
||||||
onOpenChange(false);
|
onOpenChange(false);
|
||||||
@@ -98,11 +114,12 @@ export function StatusMonitorConfig({
|
|||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle className="flex items-center gap-2">
|
<DialogTitle className="flex items-center gap-2">
|
||||||
<Radio className="h-4 w-4" />
|
<Radio className="h-4 w-4" />
|
||||||
Monitorizare status extern
|
{editMode ? "Modifica monitorizarea" : "Monitorizare status extern"}
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
{authority.name} suporta verificarea automata a statusului.
|
{editMode
|
||||||
Configureaza datele de mai jos pentru a activa monitorizarea.
|
? "Modifica datele de monitorizare. Istoricul se pastreaza."
|
||||||
|
: `${authority.name} suporta verificarea automata a statusului. Configureaza datele de mai jos pentru a activa monitorizarea.`}
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
@@ -152,7 +169,7 @@ export function StatusMonitorConfig({
|
|||||||
Anuleaza
|
Anuleaza
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={handleActivate} disabled={!canActivate}>
|
<Button onClick={handleActivate} disabled={!canActivate}>
|
||||||
Activeaza monitorizarea
|
{editMode ? "Salveaza" : "Activeaza monitorizarea"}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|||||||
@@ -229,6 +229,14 @@ export async function runStatusCheck(
|
|||||||
tracking.statusHash = newHash;
|
tracking.statusHash = newHash;
|
||||||
tracking.semanticStatus = checkResult.newStatus;
|
tracking.semanticStatus = checkResult.newStatus;
|
||||||
|
|
||||||
|
// Auto-deactivate monitoring when resolved or rejected
|
||||||
|
if (
|
||||||
|
checkResult.newStatus === "solutionat" ||
|
||||||
|
checkResult.newStatus === "respins"
|
||||||
|
) {
|
||||||
|
tracking.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Cap history at 50
|
// Cap history at 50
|
||||||
tracking.history.push(change);
|
tracking.history.push(change);
|
||||||
if (tracking.history.length > 50) {
|
if (tracking.history.length > 50) {
|
||||||
@@ -436,6 +444,15 @@ export async function checkSingleEntry(
|
|||||||
tracking.lastStatusRow = result.newRow;
|
tracking.lastStatusRow = result.newRow;
|
||||||
tracking.statusHash = newHash;
|
tracking.statusHash = newHash;
|
||||||
tracking.semanticStatus = result.newStatus;
|
tracking.semanticStatus = result.newStatus;
|
||||||
|
|
||||||
|
// Auto-deactivate monitoring when resolved or rejected
|
||||||
|
if (
|
||||||
|
result.newStatus === "solutionat" ||
|
||||||
|
result.newStatus === "respins"
|
||||||
|
) {
|
||||||
|
tracking.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
tracking.history.push(change);
|
tracking.history.push(change);
|
||||||
if (tracking.history.length > 50) {
|
if (tracking.history.length > 50) {
|
||||||
tracking.history = tracking.history.slice(-50);
|
tracking.history = tracking.history.slice(-50);
|
||||||
|
|||||||
Reference in New Issue
Block a user