feat(ancpi): complete ePay UI + dedup protection
UI Components (Phase 4): - epay-connect.tsx: connection widget with credit badge, auto-connect - epay-order-button.tsx: per-parcel "Extras CF" button with status - epay-tab.tsx: full "Extrase CF" tab with orders table, filters, download/refresh actions, new order form - Minimal changes to parcel-sync-module.tsx: 5th tab + button on search results + ePay connect widget Dedup Protection: - epay-queue.ts: batch-level dedup (60s window, canonical key from sorted cadastral numbers) - order/route.ts: request nonce idempotency (60s cache) - test/route.ts: refresh protection (30s cache) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -55,8 +55,11 @@ import {
|
||||
} from "../services/eterra-layers";
|
||||
import type { ParcelDetail } from "@/app/api/eterra/search/route";
|
||||
import type { OwnerSearchResult } from "@/app/api/eterra/search-owner/route";
|
||||
import { User } from "lucide-react";
|
||||
import { User, FileText } from "lucide-react";
|
||||
import { UatDashboard } from "./uat-dashboard";
|
||||
import { EpayConnect } from "./epay-connect";
|
||||
import { EpayOrderButton } from "./epay-order-button";
|
||||
import { EpayTab } from "./epay-tab";
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Types */
|
||||
@@ -1660,6 +1663,12 @@ export function ParcelSyncModule() {
|
||||
|
||||
const sirutaValid = siruta.length > 0 && /^\d+$/.test(siruta);
|
||||
|
||||
// Resolve selected UAT entry for ePay order context
|
||||
const selectedUat = useMemo(
|
||||
() => uatData.find((u) => u.siruta === siruta),
|
||||
[uatData, siruta],
|
||||
);
|
||||
|
||||
const progressPct =
|
||||
exportProgress?.total && exportProgress.total > 0
|
||||
? Math.round((exportProgress.downloaded / exportProgress.total) * 100)
|
||||
@@ -1787,13 +1796,16 @@ export function ParcelSyncModule() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Connection pill */}
|
||||
<ConnectionPill
|
||||
session={session}
|
||||
connecting={connecting}
|
||||
connectionError={connectionError}
|
||||
onDisconnect={handleDisconnect}
|
||||
/>
|
||||
{/* Connection pills */}
|
||||
<div className="flex items-center gap-2">
|
||||
<EpayConnect />
|
||||
<ConnectionPill
|
||||
session={session}
|
||||
connecting={connecting}
|
||||
connectionError={connectionError}
|
||||
onDisconnect={handleDisconnect}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tab bar */}
|
||||
@@ -1814,6 +1826,10 @@ export function ParcelSyncModule() {
|
||||
<Database className="h-4 w-4" />
|
||||
Baza de Date
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="extracts" className="gap-1.5">
|
||||
<FileText className="h-4 w-4" />
|
||||
Extrase CF
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</div>
|
||||
|
||||
@@ -2082,6 +2098,14 @@ export function ParcelSyncModule() {
|
||||
>
|
||||
<ClipboardCopy className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
{p.immovablePk && sirutaValid && (
|
||||
<EpayOrderButton
|
||||
nrCadastral={p.nrCad}
|
||||
siruta={siruta}
|
||||
judetName={selectedUat?.county ?? ""}
|
||||
uatName={selectedUat?.name ?? ""}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2332,6 +2356,14 @@ export function ParcelSyncModule() {
|
||||
>
|
||||
<ClipboardCopy className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
{r.immovablePk && sirutaValid && (
|
||||
<EpayOrderButton
|
||||
nrCadastral={r.nrCad}
|
||||
siruta={siruta}
|
||||
judetName={selectedUat?.county ?? ""}
|
||||
uatName={selectedUat?.name ?? ""}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4133,6 +4165,13 @@ export function ParcelSyncModule() {
|
||||
</>
|
||||
)}
|
||||
</TabsContent>
|
||||
|
||||
{/* ═══════════════════════════════════════════════════════ */}
|
||||
{/* Tab 5: Extrase CF */}
|
||||
{/* ═══════════════════════════════════════════════════════ */}
|
||||
<TabsContent value="extracts" className="space-y-4">
|
||||
<EpayTab />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user