feat(ancpi): re-download with CF matching + tooltips + animations

Re-download: all 7 orders re-downloaded using documentsByCadastral
for correct CF→document matching. No more hardcoded order→parcel map.

Tooltips on all CF extract UI elements:
- No extract: "Comandă extras CF (1 credit)"
- Valid: "Valid până la DD.MM.YYYY" + "Descarcă extras CF"
- Expired: "Expirat pe DD.MM.YYYY" + "Comandă extras CF nou (1 credit)"
- Processing: "Comanda în curs de procesare"

Animations: Loader2 spinner while ordering, transition to green check.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-23 09:38:23 +02:00
parent 0c94af75d3
commit a826f45b24
3 changed files with 457 additions and 263 deletions
+179 -136
View File
@@ -86,46 +86,25 @@ export async function GET(req: Request) {
}); });
} }
// ── download ── Download PDFs from 5 existing orders // ── download ── Re-download PDFs from all known ePay orders
if (step === "download") { if (step === "download") {
const client = await EpayClient.create(username, password); const client = await EpayClient.create(username, password);
createEpaySession(username, password, await client.getCredits()); createEpaySession(username, password, await client.getCredits());
// Known orders from previous test // All known order IDs (MinIO + DB were cleaned, need re-download)
const orderIds = ["9685480", "9685481", "9685482", "9685483", "9685484"]; // Single orders: mapping unknown — use documentsByCadastral to discover CF
const singleOrderIds = ["9685480", "9685481", "9685482", "9685483", "9685484"];
// Batch orders: documentsByCadastral maps CF -> doc correctly
const batchOrderIds = ["9685487", "9685488"];
const allOrderIds = [...singleOrderIds, ...batchOrderIds];
// Mapping: orderId → nrCadastral (5 orders for 3 parcels) // UAT name lookup for DB records
// Orders were for: 345295 (Cluj-Napoca), 63565 (Feleacu), 88089 (Florești) const uatLookup: Record<string, { uatId: number; uatName: string }> = {
// 5 orders for 3 parcels = some duplicates "345295": { uatId: 54975, uatName: "Cluj-Napoca" },
const orderParcelMap: Record< "63565": { uatId: 57582, uatName: "Feleacu" },
string, "88089": { uatId: 57706, uatName: "Floresti" },
{ nrCadastral: string; judetName: string; uatName: string } "61904": { uatId: 57582, uatName: "Feleacu" },
> = { "309952": { uatId: 54975, uatName: "Cluj-Napoca" },
"9685480": {
nrCadastral: "345295",
judetName: "CLUJ",
uatName: "Cluj-Napoca",
},
"9685481": {
nrCadastral: "63565",
judetName: "CLUJ",
uatName: "Feleacu",
},
"9685482": {
nrCadastral: "88089",
judetName: "CLUJ",
uatName: "Florești",
},
"9685483": {
nrCadastral: "345295",
judetName: "CLUJ",
uatName: "Cluj-Napoca",
},
"9685484": {
nrCadastral: "63565",
judetName: "CLUJ",
uatName: "Feleacu",
},
}; };
const results: Array<{ const results: Array<{
@@ -138,31 +117,18 @@ export async function GET(req: Request) {
error?: string; error?: string;
}> = []; }> = [];
for (const orderId of orderIds) { for (const orderId of allOrderIds) {
const parcelInfo = orderParcelMap[orderId];
if (!parcelInfo) {
results.push({
orderId,
nrCadastral: "unknown",
status: "error",
documents: 0,
downloaded: false,
error: "No parcel mapping for orderId",
});
continue;
}
try { try {
// Get order status and document info // Get order status documentsByCadastral maps CF → doc
const orderStatus = await client.getOrderStatus(orderId); const orderStatus = await client.getOrderStatus(orderId);
console.log( console.log(
`[ancpi-test] Order ${orderId}: status=${orderStatus.status}, docs=${orderStatus.documents.length}`, `[ancpi-test] Order ${orderId}: status=${orderStatus.status}, docs=${orderStatus.documents.length}, byCF=${orderStatus.documentsByCadastral.size}`,
); );
if (orderStatus.documents.length === 0) { if (orderStatus.documents.length === 0) {
results.push({ results.push({
orderId, orderId,
nrCadastral: parcelInfo.nrCadastral, nrCadastral: "unknown",
status: orderStatus.status, status: orderStatus.status,
documents: 0, documents: 0,
downloaded: false, downloaded: false,
@@ -171,94 +137,171 @@ export async function GET(req: Request) {
continue; continue;
} }
// Find downloadable PDF document // Process each document by cadastral number from the map
const doc = orderStatus.documents.find( if (orderStatus.documentsByCadastral.size > 0) {
(d) => d.downloadValabil && d.contentType === "application/pdf", for (const [cfNumber, doc] of orderStatus.documentsByCadastral) {
); if (!doc.downloadValabil || doc.contentType !== "application/pdf") {
results.push({
orderId,
nrCadastral: cfNumber,
status: orderStatus.status,
documents: orderStatus.documents.length,
downloaded: false,
error: "Document not downloadable or not PDF",
});
continue;
}
if (!doc) { try {
results.push({ // Download the PDF
orderId, const pdfBuffer = await client.downloadDocument(doc.idDocument, 4);
nrCadastral: parcelInfo.nrCadastral, console.log(
status: orderStatus.status, `[ancpi-test] Downloaded doc ${doc.idDocument} (CF ${cfNumber}): ${pdfBuffer.length} bytes`,
documents: orderStatus.documents.length, );
downloaded: false,
error: "No downloadable PDF found",
});
continue;
}
// Download the PDF // Resolve UAT info for this cadastral number
const pdfBuffer = await client.downloadDocument(doc.idDocument, 4); const uat = uatLookup[cfNumber];
console.log( const uatId = uat?.uatId ?? 0;
`[ancpi-test] Downloaded doc ${doc.idDocument}: ${pdfBuffer.length} bytes`, const uatName = uat?.uatName ?? "Necunoscut";
);
// Store in MinIO // Store in MinIO
const { path, index } = await storeCfExtract( const { path, index } = await storeCfExtract(
pdfBuffer, pdfBuffer,
parcelInfo.nrCadastral, cfNumber,
{ {
"ancpi-order-id": orderId, "ancpi-order-id": orderId,
"nr-cadastral": parcelInfo.nrCadastral, "nr-cadastral": cfNumber,
judet: parcelInfo.judetName, judet: "CLUJ",
uat: parcelInfo.uatName, uat: uatName,
"data-document": doc.dataDocument ?? "", "data-document": doc.dataDocument ?? "",
stare: orderStatus.status, stare: orderStatus.status,
produs: "EXI_ONLINE", produs: "EXI_ONLINE",
}, },
); );
// Upsert CfExtract record — find by orderId or create // Calculate dates
const documentDate = doc.dataDocument const documentDate = doc.dataDocument
? new Date(doc.dataDocument) ? new Date(doc.dataDocument)
: new Date(); : new Date();
const expiresAt = new Date(documentDate); const expiresAt = new Date(documentDate);
expiresAt.setDate(expiresAt.getDate() + 30); expiresAt.setDate(expiresAt.getDate() + 30);
// Try to find existing record by orderId // Always create new records (DB was cleaned)
const existing = await prisma.cfExtract.findFirst({ // Increment version for duplicate parcels
where: { orderId }, const maxVersion = await prisma.cfExtract.aggregate({
}); where: { nrCadastral: cfNumber },
_max: { version: true },
});
if (existing) { await prisma.cfExtract.create({
// Update existing record data: {
await prisma.cfExtract.update({ orderId,
where: { id: existing.id }, nrCadastral: cfNumber,
data: { nrCF: cfNumber,
status: "completed", judetIndex: 127,
epayStatus: orderStatus.status, judetName: "CLUJ",
idDocument: doc.idDocument, uatId,
documentName: doc.nume, uatName,
documentDate, status: "completed",
minioPath: path, epayStatus: orderStatus.status,
minioIndex: index, idDocument: doc.idDocument,
completedAt: new Date(), documentName: doc.nume,
expiresAt, documentDate,
errorMessage: null, minioPath: path,
}, minioIndex: index,
}); completedAt: new Date(),
expiresAt,
version: (maxVersion._max.version ?? 0) + 1,
},
});
results.push({
orderId,
nrCadastral: cfNumber,
status: orderStatus.status,
documents: orderStatus.documents.length,
downloaded: true,
minioPath: path,
});
} catch (dlErr) {
const msg = dlErr instanceof Error ? dlErr.message : String(dlErr);
console.error(
`[ancpi-test] Failed to download doc for CF ${cfNumber} in order ${orderId}:`,
msg,
);
results.push({
orderId,
nrCadastral: cfNumber,
status: "error",
documents: orderStatus.documents.length,
downloaded: false,
error: msg,
});
}
}
} else { } else {
// Create new record // Fallback: no CF mapping, process first downloadable document
const doc = orderStatus.documents.find(
(d) => d.downloadValabil && d.contentType === "application/pdf",
);
if (!doc) {
results.push({
orderId,
nrCadastral: "unknown",
status: orderStatus.status,
documents: orderStatus.documents.length,
downloaded: false,
error: "No downloadable PDF and no CF mapping found",
});
continue;
}
// Try to extract CF from document name (e.g. "Extras_Informare_345295.pdf")
const cfFromName = doc.nume.match(/(\d{4,})/)?.[1] ?? "unknown";
const pdfBuffer = await client.downloadDocument(doc.idDocument, 4);
console.log(
`[ancpi-test] Downloaded doc ${doc.idDocument} (CF from name: ${cfFromName}): ${pdfBuffer.length} bytes`,
);
const uat = uatLookup[cfFromName];
const uatId = uat?.uatId ?? 0;
const uatName = uat?.uatName ?? "Necunoscut";
const { path, index } = await storeCfExtract(
pdfBuffer,
cfFromName,
{
"ancpi-order-id": orderId,
"nr-cadastral": cfFromName,
judet: "CLUJ",
uat: uatName,
"data-document": doc.dataDocument ?? "",
stare: orderStatus.status,
produs: "EXI_ONLINE",
},
);
const documentDate = doc.dataDocument
? new Date(doc.dataDocument)
: new Date();
const expiresAt = new Date(documentDate);
expiresAt.setDate(expiresAt.getDate() + 30);
const maxVersion = await prisma.cfExtract.aggregate({ const maxVersion = await prisma.cfExtract.aggregate({
where: { nrCadastral: parcelInfo.nrCadastral }, where: { nrCadastral: cfFromName },
_max: { version: true }, _max: { version: true },
}); });
await prisma.cfExtract.create({ await prisma.cfExtract.create({
data: { data: {
orderId, orderId,
nrCadastral: parcelInfo.nrCadastral, nrCadastral: cfFromName,
nrCF: parcelInfo.nrCadastral, nrCF: cfFromName,
judetIndex: 127, judetIndex: 127,
judetName: parcelInfo.judetName, judetName: "CLUJ",
uatId: uatId,
parcelInfo.uatName === "Cluj-Napoca" uatName,
? 54975
: parcelInfo.uatName === "Feleacu"
? 57582
: 57706,
uatName: parcelInfo.uatName,
status: "completed", status: "completed",
epayStatus: orderStatus.status, epayStatus: orderStatus.status,
idDocument: doc.idDocument, idDocument: doc.idDocument,
@@ -271,16 +314,16 @@ export async function GET(req: Request) {
version: (maxVersion._max.version ?? 0) + 1, version: (maxVersion._max.version ?? 0) + 1,
}, },
}); });
}
results.push({ results.push({
orderId, orderId,
nrCadastral: parcelInfo.nrCadastral, nrCadastral: cfFromName,
status: orderStatus.status, status: orderStatus.status,
documents: orderStatus.documents.length, documents: orderStatus.documents.length,
downloaded: true, downloaded: true,
minioPath: path, minioPath: path,
}); });
}
} catch (error) { } catch (error) {
const message = const message =
error instanceof Error ? error.message : String(error); error instanceof Error ? error.message : String(error);
@@ -290,7 +333,7 @@ export async function GET(req: Request) {
); );
results.push({ results.push({
orderId, orderId,
nrCadastral: parcelInfo.nrCadastral, nrCadastral: "unknown",
status: "error", status: "error",
documents: 0, documents: 0,
downloaded: false, downloaded: false,
@@ -301,7 +344,7 @@ export async function GET(req: Request) {
return NextResponse.json({ return NextResponse.json({
step: "download", step: "download",
totalOrders: orderIds.length, totalOrders: allOrderIds.length,
results, results,
summary: { summary: {
downloaded: results.filter((r) => r.downloaded).length, downloaded: results.filter((r) => r.downloaded).length,
@@ -1,8 +1,14 @@
"use client"; "use client";
import { useState, useEffect, useCallback, useRef } from "react"; import { useState, useEffect, useCallback, useRef } from "react";
import { FileText, Loader2, Check } from "lucide-react"; import { FileText, Loader2, Check, RefreshCw } from "lucide-react";
import { Button } from "@/shared/components/ui/button"; import { Button } from "@/shared/components/ui/button";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/shared/components/ui/tooltip";
import { cn } from "@/shared/lib/utils"; import { cn } from "@/shared/lib/utils";
import type { EpaySessionStatus } from "./epay-connect"; import type { EpaySessionStatus } from "./epay-connect";
@@ -15,6 +21,10 @@ type Props = {
siruta: string; siruta: string;
judetName: string; judetName: string;
uatName: string; uatName: string;
/** Custom label for the button (e.g. "Actualizeaza" for expired extracts) */
label?: string;
/** Custom tooltip text */
tooltipText?: string;
}; };
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@@ -26,6 +36,8 @@ export function EpayOrderButton({
siruta, siruta,
judetName, judetName,
uatName, uatName,
label,
tooltipText,
}: Props) { }: Props) {
const [ordering, setOrdering] = useState(false); const [ordering, setOrdering] = useState(false);
const [ordered, setOrdered] = useState(false); const [ordered, setOrdered] = useState(false);
@@ -93,12 +105,12 @@ export function EpayOrderButton({
}); });
const data = (await res.json()) as { orders?: unknown[]; error?: string }; const data = (await res.json()) as { orders?: unknown[]; error?: string };
if (!res.ok || data.error) { if (!res.ok || data.error) {
if (mountedRef.current) setError(data.error ?? "Eroare comandă"); if (mountedRef.current) setError(data.error ?? "Eroare comanda");
} else { } else {
if (mountedRef.current) setOrdered(true); if (mountedRef.current) setOrdered(true);
} }
} catch { } catch {
if (mountedRef.current) setError("Eroare rețea"); if (mountedRef.current) setError("Eroare retea");
} finally { } finally {
if (mountedRef.current) setOrdering(false); if (mountedRef.current) setOrdering(false);
} }
@@ -109,45 +121,95 @@ export function EpayOrderButton({
(epayStatus.credits != null && epayStatus.credits < 1) || (epayStatus.credits != null && epayStatus.credits < 1) ||
ordering; ordering;
const isRenew = !!label; // "Actualizeaza" mode for expired extracts
const Icon = isRenew ? RefreshCw : FileText;
const resolveTooltip = (): string => {
if (error) return error;
if (ordering) return "Se comanda...";
if (ordered) return "Extras CF valid";
if (!epayStatus.connected) return "ePay neconectat";
if (epayStatus.credits != null && epayStatus.credits < 1) return "Credite insuficiente";
return tooltipText ?? "Comanda extras CF (1 credit)";
};
if (ordered) { if (ordered) {
return ( return (
<Button <TooltipProvider>
size="sm" <Tooltip>
variant="ghost" <TooltipTrigger asChild>
className="h-7 w-7 p-0 text-emerald-600 dark:text-emerald-400" <Button
title="Extras CF comandat" size="sm"
disabled variant="ghost"
> className="h-7 gap-1 px-1.5 text-emerald-600 dark:text-emerald-400"
<Check className="h-3.5 w-3.5" /> disabled
</Button> >
<Check className="h-3.5 w-3.5" />
<span className="text-[10px]">Extras CF valid</span>
</Button>
</TooltipTrigger>
<TooltipContent>Extras CF comandat cu succes</TooltipContent>
</Tooltip>
</TooltipProvider>
); );
} }
if (label) {
// Render as a compact text button with label (for "Actualizeaza" etc.)
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
size="sm"
variant="ghost"
className={cn(
"h-7 gap-1 px-1.5 text-[10px]",
error && "text-destructive",
ordering && "text-muted-foreground",
)}
disabled={disabled}
onClick={() => void handleOrder()}
>
{ordering ? (
<Loader2 className="h-3 w-3 animate-spin" />
) : (
<Icon className="h-3 w-3" />
)}
{ordering ? "Se comanda..." : label}
</Button>
</TooltipTrigger>
<TooltipContent>{resolveTooltip()}</TooltipContent>
</Tooltip>
</TooltipProvider>
);
}
// Default: icon-only button
return ( return (
<Button <TooltipProvider>
size="sm" <Tooltip>
variant="ghost" <TooltipTrigger asChild>
className={cn( <Button
"h-7 w-7 p-0", size="sm"
error && "text-destructive", variant="ghost"
)} className={cn(
title={ "h-7 w-7 p-0",
error error && "text-destructive",
? error ordering && "text-muted-foreground",
: !epayStatus.connected )}
? "ePay neconectat" disabled={disabled}
: epayStatus.credits != null && epayStatus.credits < 1 onClick={() => void handleOrder()}
? "Credite insuficiente" >
: "Extras CF" {ordering ? (
} <Loader2 className="h-3.5 w-3.5 animate-spin" />
disabled={disabled} ) : (
onClick={() => void handleOrder()} <FileText className="h-3.5 w-3.5" />
> )}
{ordering ? ( </Button>
<Loader2 className="h-3.5 w-3.5 animate-spin" /> </TooltipTrigger>
) : ( <TooltipContent>{resolveTooltip()}</TooltipContent>
<FileText className="h-3.5 w-3.5" /> </Tooltip>
)} </TooltipProvider>
</Button>
); );
} }
@@ -46,6 +46,12 @@ import {
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/shared/components/ui/dropdown-menu"; } from "@/shared/components/ui/dropdown-menu";
import { cn } from "@/shared/lib/utils"; import { cn } from "@/shared/lib/utils";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/shared/components/ui/tooltip";
import { import {
LAYER_CATALOG, LAYER_CATALOG,
LAYER_CATEGORY_LABELS, LAYER_CATEGORY_LABELS,
@@ -126,6 +132,15 @@ function formatArea(val?: number | null) {
return val.toLocaleString("ro-RO", { maximumFractionDigits: 2 }) + " mp"; return val.toLocaleString("ro-RO", { maximumFractionDigits: 2 }) + " mp";
} }
/** Format ISO date as DD.MM.YYYY (no time) */
function formatShortDate(iso?: string | null) {
if (!iso) return "—";
const d = new Date(iso);
const dd = String(d.getDate()).padStart(2, "0");
const mm = String(d.getMonth() + 1).padStart(2, "0");
return `${dd}.${mm}.${d.getFullYear()}`;
}
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* Connection Status Pill */ /* Connection Status Pill */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@@ -447,6 +462,8 @@ export function ParcelSyncModule() {
const [cfStatusMap, setCfStatusMap] = useState<Record<string, string>>({}); const [cfStatusMap, setCfStatusMap] = useState<Record<string, string>>({});
/** Latest completed extract IDs per nrCadastral */ /** Latest completed extract IDs per nrCadastral */
const [cfLatestIds, setCfLatestIds] = useState<Record<string, string>>({}); const [cfLatestIds, setCfLatestIds] = useState<Record<string, string>>({});
/** Expiry dates per nrCadastral (ISO string) */
const [cfExpiryDates, setCfExpiryDates] = useState<Record<string, string>>({});
/** Whether we're currently loading CF statuses */ /** Whether we're currently loading CF statuses */
const [cfStatusLoading, setCfStatusLoading] = useState(false); const [cfStatusLoading, setCfStatusLoading] = useState(false);
/** List CF batch order state */ /** List CF batch order state */
@@ -1534,12 +1551,18 @@ export function ParcelSyncModule() {
} }
if (data.latestById) { if (data.latestById) {
const idMap: Record<string, string> = {}; const idMap: Record<string, string> = {};
const expiryMap: Record<string, string> = {};
for (const [nr, rec] of Object.entries(data.latestById)) { for (const [nr, rec] of Object.entries(data.latestById)) {
if (rec && typeof rec === "object" && "id" in rec) { if (rec && typeof rec === "object" && "id" in rec) {
idMap[nr] = (rec as { id: string }).id; idMap[nr] = (rec as { id: string }).id;
const expires = (rec as { expiresAt: string | null }).expiresAt;
if (expires) {
expiryMap[nr] = expires;
}
} }
} }
setCfLatestIds((prev) => ({ ...prev, ...idMap })); setCfLatestIds((prev) => ({ ...prev, ...idMap }));
setCfExpiryDates((prev) => ({ ...prev, ...expiryMap }));
} }
} catch { } catch {
/* silent */ /* silent */
@@ -2318,61 +2341,93 @@ export function ParcelSyncModule() {
{p.immovablePk && sirutaValid && (() => { {p.immovablePk && sirutaValid && (() => {
const cfStatus = cfStatusMap[p.nrCad]; const cfStatus = cfStatusMap[p.nrCad];
const extractId = cfLatestIds[p.nrCad]; const extractId = cfLatestIds[p.nrCad];
const cfExpiry = cfExpiryDates[p.nrCad];
if (cfStatus === "valid") { if (cfStatus === "valid") {
return ( return (
<div className="flex items-center gap-1"> <TooltipProvider>
<Badge <div className="flex items-center gap-1">
variant="outline" <Tooltip>
className="text-[10px] border-emerald-200 text-emerald-700 dark:border-emerald-800 dark:text-emerald-400" <TooltipTrigger asChild>
> <Badge
Extras CF valid variant="outline"
</Badge> className="text-[10px] border-emerald-200 text-emerald-700 dark:border-emerald-800 dark:text-emerald-400 cursor-default"
{extractId && ( >
<Button Extras CF
size="sm" </Badge>
variant="ghost" </TooltipTrigger>
className="h-7 w-7 p-0 text-emerald-600" <TooltipContent>
title="Descarca extras CF" {cfExpiry ? `Valid pana la ${formatShortDate(cfExpiry)}` : "Extras CF valid"}
asChild </TooltipContent>
> </Tooltip>
<a {extractId && (
href={`/api/ancpi/download?id=${extractId}`} <Tooltip>
target="_blank" <TooltipTrigger asChild>
rel="noopener noreferrer" <Button
> size="sm"
<Download className="h-3.5 w-3.5" /> variant="ghost"
</a> className="h-7 w-7 p-0 text-emerald-600"
</Button> asChild
)} >
</div> <a
href={`/api/ancpi/download?id=${extractId}`}
target="_blank"
rel="noopener noreferrer"
>
<Download className="h-3.5 w-3.5" />
</a>
</Button>
</TooltipTrigger>
<TooltipContent>Descarca extras CF</TooltipContent>
</Tooltip>
)}
</div>
</TooltipProvider>
); );
} }
if (cfStatus === "expired") { if (cfStatus === "expired") {
return ( return (
<div className="flex items-center gap-1"> <TooltipProvider>
<Badge <div className="flex items-center gap-1">
variant="outline" <Tooltip>
className="text-[10px] border-orange-200 text-orange-600 dark:border-orange-800 dark:text-orange-400" <TooltipTrigger asChild>
> <Badge
Extras CF expirat variant="outline"
</Badge> className="text-[10px] border-orange-200 text-orange-600 dark:border-orange-800 dark:text-orange-400 cursor-default"
<EpayOrderButton >
nrCadastral={p.nrCad} Expirat
siruta={siruta} </Badge>
judetName={selectedUat?.county ?? ""} </TooltipTrigger>
uatName={selectedUat?.name ?? ""} <TooltipContent>
/> {cfExpiry ? `Expirat pe ${formatShortDate(cfExpiry)}` : "Extras CF expirat"}
</div> </TooltipContent>
</Tooltip>
<EpayOrderButton
nrCadastral={p.nrCad}
siruta={siruta}
judetName={selectedUat?.county ?? ""}
uatName={selectedUat?.name ?? ""}
label="Actualizeaza"
tooltipText="Comanda extras CF nou (1 credit)"
/>
</div>
</TooltipProvider>
); );
} }
if (cfStatus === "processing") { if (cfStatus === "processing") {
return ( return (
<Badge <TooltipProvider>
variant="outline" <Tooltip>
className="text-[10px] border-yellow-200 text-yellow-600 dark:border-yellow-800 dark:text-yellow-400 animate-pulse" <TooltipTrigger asChild>
> <Badge
Se proceseaza... variant="outline"
</Badge> className="text-[10px] border-yellow-200 text-yellow-600 dark:border-yellow-800 dark:text-yellow-400 animate-pulse cursor-default"
>
Se proceseaza...
</Badge>
</TooltipTrigger>
<TooltipContent>Comanda in curs de procesare</TooltipContent>
</Tooltip>
</TooltipProvider>
); );
} }
// "none" or unknown // "none" or unknown
@@ -2382,6 +2437,7 @@ export function ParcelSyncModule() {
siruta={siruta} siruta={siruta}
judetName={selectedUat?.county ?? ""} judetName={selectedUat?.county ?? ""}
uatName={selectedUat?.name ?? ""} uatName={selectedUat?.name ?? ""}
tooltipText="Comanda extras CF (1 credit)"
/> />
); );
})()} })()}
@@ -2639,61 +2695,93 @@ export function ParcelSyncModule() {
{r.immovablePk && sirutaValid && (() => { {r.immovablePk && sirutaValid && (() => {
const cfStatus = cfStatusMap[r.nrCad]; const cfStatus = cfStatusMap[r.nrCad];
const extractId = cfLatestIds[r.nrCad]; const extractId = cfLatestIds[r.nrCad];
const cfExpiry = cfExpiryDates[r.nrCad];
if (cfStatus === "valid") { if (cfStatus === "valid") {
return ( return (
<div className="flex items-center gap-1"> <TooltipProvider>
<Badge <div className="flex items-center gap-1">
variant="outline" <Tooltip>
className="text-[10px] border-emerald-200 text-emerald-700 dark:border-emerald-800 dark:text-emerald-400" <TooltipTrigger asChild>
> <Badge
Extras CF valid variant="outline"
</Badge> className="text-[10px] border-emerald-200 text-emerald-700 dark:border-emerald-800 dark:text-emerald-400 cursor-default"
{extractId && ( >
<Button Extras CF
size="sm" </Badge>
variant="ghost" </TooltipTrigger>
className="h-7 w-7 p-0 text-emerald-600" <TooltipContent>
title="Descarca extras CF" {cfExpiry ? `Valid pana la ${formatShortDate(cfExpiry)}` : "Extras CF valid"}
asChild </TooltipContent>
> </Tooltip>
<a {extractId && (
href={`/api/ancpi/download?id=${extractId}`} <Tooltip>
target="_blank" <TooltipTrigger asChild>
rel="noopener noreferrer" <Button
> size="sm"
<Download className="h-3.5 w-3.5" /> variant="ghost"
</a> className="h-7 w-7 p-0 text-emerald-600"
</Button> asChild
)} >
</div> <a
href={`/api/ancpi/download?id=${extractId}`}
target="_blank"
rel="noopener noreferrer"
>
<Download className="h-3.5 w-3.5" />
</a>
</Button>
</TooltipTrigger>
<TooltipContent>Descarca extras CF</TooltipContent>
</Tooltip>
)}
</div>
</TooltipProvider>
); );
} }
if (cfStatus === "expired") { if (cfStatus === "expired") {
return ( return (
<div className="flex items-center gap-1"> <TooltipProvider>
<Badge <div className="flex items-center gap-1">
variant="outline" <Tooltip>
className="text-[10px] border-orange-200 text-orange-600 dark:border-orange-800 dark:text-orange-400" <TooltipTrigger asChild>
> <Badge
Extras CF expirat variant="outline"
</Badge> className="text-[10px] border-orange-200 text-orange-600 dark:border-orange-800 dark:text-orange-400 cursor-default"
<EpayOrderButton >
nrCadastral={r.nrCad} Expirat
siruta={siruta} </Badge>
judetName={selectedUat?.county ?? ""} </TooltipTrigger>
uatName={selectedUat?.name ?? ""} <TooltipContent>
/> {cfExpiry ? `Expirat pe ${formatShortDate(cfExpiry)}` : "Extras CF expirat"}
</div> </TooltipContent>
</Tooltip>
<EpayOrderButton
nrCadastral={r.nrCad}
siruta={siruta}
judetName={selectedUat?.county ?? ""}
uatName={selectedUat?.name ?? ""}
label="Actualizeaza"
tooltipText="Comanda extras CF nou (1 credit)"
/>
</div>
</TooltipProvider>
); );
} }
if (cfStatus === "processing") { if (cfStatus === "processing") {
return ( return (
<Badge <TooltipProvider>
variant="outline" <Tooltip>
className="text-[10px] border-yellow-200 text-yellow-600 dark:border-yellow-800 dark:text-yellow-400 animate-pulse" <TooltipTrigger asChild>
> <Badge
Se proceseaza... variant="outline"
</Badge> className="text-[10px] border-yellow-200 text-yellow-600 dark:border-yellow-800 dark:text-yellow-400 animate-pulse cursor-default"
>
Se proceseaza...
</Badge>
</TooltipTrigger>
<TooltipContent>Comanda in curs de procesare</TooltipContent>
</Tooltip>
</TooltipProvider>
); );
} }
return ( return (
@@ -2702,6 +2790,7 @@ export function ParcelSyncModule() {
siruta={siruta} siruta={siruta}
judetName={selectedUat?.county ?? ""} judetName={selectedUat?.county ?? ""}
uatName={selectedUat?.name ?? ""} uatName={selectedUat?.name ?? ""}
tooltipText="Comanda extras CF (1 credit)"
/> />
); );
})()} })()}