fix(parcel-sync): replace Unicode escapes with actual Romanian diacritics
The \u0103, \u00ee etc. escape sequences were rendering literally in JSX text nodes instead of displaying ă, î, ț, ș characters. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -77,11 +77,11 @@ export function ConnectionPill({
|
||||
)}
|
||||
<span className="hidden sm:inline">
|
||||
{connecting
|
||||
? "Se conecteaz\u0103\u2026"
|
||||
? "Se conectează…"
|
||||
: session.connected
|
||||
? "eTerra"
|
||||
: session.eterraMaintenance
|
||||
? "Mentenan\u021b\u0103"
|
||||
? "Mentenanță"
|
||||
: connectionError
|
||||
? "Eroare"
|
||||
: "Deconectat"}
|
||||
@@ -128,11 +128,11 @@ export function ConnectionPill({
|
||||
<AlertTriangle className="h-3.5 w-3.5 text-amber-500 mt-0.5 shrink-0" />
|
||||
<div>
|
||||
<p className="font-medium text-amber-700 dark:text-amber-400">
|
||||
eTerra este \u00een mentenan\u021b\u0103
|
||||
eTerra este în mentenanță
|
||||
</p>
|
||||
<p className="mt-1 text-[11px] text-amber-600/80 dark:text-amber-400/70">
|
||||
Platforma ANCPI nu este disponibil\u0103 momentan. Conectarea va fi
|
||||
reactivat\u0103 automat c\u00e2nd serviciul revine online.
|
||||
Platforma ANCPI nu este disponibilă momentan. Conectarea va fi
|
||||
reactivată automat când serviciul revine online.
|
||||
</p>
|
||||
{session.eterraHealthMessage && (
|
||||
<p className="mt-1 text-[10px] opacity-60 font-mono">
|
||||
@@ -149,9 +149,9 @@ export function ConnectionPill({
|
||||
!connectionError &&
|
||||
!session.eterraMaintenance && (
|
||||
<div className="px-3 py-3 text-xs text-muted-foreground">
|
||||
<p>Conexiunea se face automat c\u00e2nd \u00eencepi s\u0103 scrii un UAT.</p>
|
||||
<p>Conexiunea se face automat când începi să scrii un UAT.</p>
|
||||
<p className="mt-1 text-[11px] opacity-70">
|
||||
Creden\u021bialele sunt preluate din configurarea serverului.
|
||||
Credențialele sunt preluate din configurarea serverului.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -162,7 +162,7 @@ export function ConnectionPill({
|
||||
!session.eterraMaintenance && (
|
||||
<div className="px-3 py-3 text-xs text-muted-foreground">
|
||||
<p>
|
||||
Conexiunea automat\u0103 a e\u0219uat. Verific\u0103 creden\u021bialele din
|
||||
Conexiunea automată a eșuat. Verifică credențialele din
|
||||
variabilele de mediu (ETERRA_USERNAME / ETERRA_PASSWORD).
|
||||
</p>
|
||||
</div>
|
||||
@@ -182,7 +182,7 @@ export function ConnectionPill({
|
||||
{session.activeJobPhase && (
|
||||
<span className="opacity-70">
|
||||
{" "}
|
||||
\u2014 {session.activeJobPhase}
|
||||
— {session.activeJobPhase}
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
|
||||
@@ -194,14 +194,14 @@ export function ParcelSyncModule() {
|
||||
...prev,
|
||||
eterraMaintenance: true,
|
||||
eterraAvailable: false,
|
||||
eterraHealthMessage: data.error ?? "eTerra \u00een mentenan\u021b\u0103",
|
||||
eterraHealthMessage: data.error ?? "eTerra în mentenanță",
|
||||
}));
|
||||
autoConnectAttempted.current = false;
|
||||
} else {
|
||||
setConnectionError(data.error ?? "Eroare conectare");
|
||||
}
|
||||
} catch {
|
||||
setConnectionError("Eroare re\u021bea");
|
||||
setConnectionError("Eroare rețea");
|
||||
}
|
||||
setConnecting(false);
|
||||
}, [session.connected, session.eterraMaintenance, connecting, fetchSession]);
|
||||
@@ -222,7 +222,7 @@ export function ParcelSyncModule() {
|
||||
setConnectionError(data.error ?? "Nu se poate deconecta");
|
||||
}
|
||||
} catch {
|
||||
setConnectionError("Eroare re\u021bea");
|
||||
setConnectionError("Eroare rețea");
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -282,7 +282,7 @@ export function ParcelSyncModule() {
|
||||
<MapPin className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground pointer-events-none" />
|
||||
<Input
|
||||
id="uat-search"
|
||||
placeholder="Selecteaz\u0103 UAT \u2014 scrie nume sau cod SIRUTA\u2026"
|
||||
placeholder="Selectează UAT — scrie nume sau cod SIRUTA…"
|
||||
value={uatQuery}
|
||||
onChange={(e) => {
|
||||
setUatQuery(e.target.value);
|
||||
@@ -329,7 +329,7 @@ export function ParcelSyncModule() {
|
||||
<span className="text-muted-foreground">({item.siruta})</span>
|
||||
{item.county && (
|
||||
<span className="text-muted-foreground">
|
||||
{"\u2013 "}
|
||||
{"– "}
|
||||
<span className="font-medium text-foreground/70">
|
||||
jud. {item.county}
|
||||
</span>
|
||||
@@ -363,7 +363,7 @@ export function ParcelSyncModule() {
|
||||
<TabsList>
|
||||
<TabsTrigger value="search" className="gap-1.5">
|
||||
<Search className="h-4 w-4" />
|
||||
C\u0103utare Parcele
|
||||
Căutare Parcele
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="layers" className="gap-1.5">
|
||||
<Layers className="h-4 w-4" />
|
||||
|
||||
@@ -85,7 +85,7 @@ export const normalizeText = (text: string) =>
|
||||
.trim();
|
||||
|
||||
export function formatDate(iso?: string | null) {
|
||||
if (!iso) return "\u2014";
|
||||
if (!iso) return "—";
|
||||
return new Date(iso).toLocaleDateString("ro-RO", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
@@ -96,13 +96,13 @@ export function formatDate(iso?: string | null) {
|
||||
}
|
||||
|
||||
export function formatArea(val?: number | null) {
|
||||
if (val == null) return "\u2014";
|
||||
if (val == null) return "—";
|
||||
return val.toLocaleString("ro-RO", { maximumFractionDigits: 2 }) + " mp";
|
||||
}
|
||||
|
||||
/** Format ISO date as DD.MM.YYYY (no time) */
|
||||
export function formatShortDate(iso?: string | null) {
|
||||
if (!iso) return "\u2014";
|
||||
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");
|
||||
@@ -110,7 +110,7 @@ export function formatShortDate(iso?: string | null) {
|
||||
}
|
||||
|
||||
export function relativeTime(date: Date | null) {
|
||||
if (!date) return "niciodat\u0103";
|
||||
if (!date) return "niciodată";
|
||||
const mins = Math.floor((Date.now() - date.getTime()) / 60_000);
|
||||
if (mins < 1) return "acum";
|
||||
if (mins < 60) return `acum ${mins} min`;
|
||||
|
||||
@@ -52,7 +52,7 @@ export function DatabaseTab({
|
||||
<Card>
|
||||
<CardContent className="py-12 text-center text-muted-foreground">
|
||||
<Loader2 className="h-8 w-8 mx-auto mb-3 animate-spin opacity-40" />
|
||||
<p>Se \u00eencarc\u0103 datele din baza de date\u2026</p>
|
||||
<p>Se încarcă datele din baza de date…</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
@@ -64,9 +64,9 @@ export function DatabaseTab({
|
||||
<Card>
|
||||
<CardContent className="py-12 text-center text-muted-foreground">
|
||||
<Database className="h-10 w-10 mx-auto mb-3 opacity-30" />
|
||||
<p className="font-medium">Nicio dat\u0103 \u00een baza de date</p>
|
||||
<p className="font-medium">Nicio dată în baza de date</p>
|
||||
<p className="text-xs mt-1">
|
||||
Folose\u0219te tab-ul Export pentru a sincroniza date din eTerra.
|
||||
Folosește tab-ul Export pentru a sincroniza date din eTerra.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -81,7 +81,7 @@ export function DatabaseTab({
|
||||
<div className="flex items-center gap-2">
|
||||
<Database className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-sm font-medium">
|
||||
{dbSummary.totalFeatures.toLocaleString("ro-RO")} entit\u0103\u021bi
|
||||
{dbSummary.totalFeatures.toLocaleString("ro-RO")} entități
|
||||
</span>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
din {dbSummary.totalUats} UAT-uri
|
||||
@@ -99,7 +99,7 @@ export function DatabaseTab({
|
||||
) : (
|
||||
<RefreshCw className="h-3 w-3 mr-1" />
|
||||
)}
|
||||
Re\u00eencarc\u0103
|
||||
Reîncarcă
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -169,7 +169,7 @@ export function DatabaseTab({
|
||||
Dashboard
|
||||
</Button>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{oldestSync ? relativeTime(oldestSync) : "\u2014"}
|
||||
{oldestSync ? relativeTime(oldestSync) : "—"}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
@@ -212,7 +212,7 @@ export function DatabaseTab({
|
||||
{noGeomTotal > 0 && (
|
||||
<span className="inline-flex items-center gap-1">
|
||||
<span className="text-muted-foreground">
|
||||
F\u0103r\u0103 geom:
|
||||
Fără geom:
|
||||
</span>
|
||||
<span className="font-medium tabular-nums text-amber-600 dark:text-amber-400">
|
||||
{noGeomTotal.toLocaleString("ro-RO")}
|
||||
@@ -239,7 +239,7 @@ export function DatabaseTab({
|
||||
? "border-teal-200 bg-teal-50/50 dark:border-teal-800 dark:bg-teal-950/30"
|
||||
: "border-muted bg-muted/30",
|
||||
)}
|
||||
title={`${label}: ${layer.count} entit\u0103\u021bi${isEnriched ? `, ${layer.enrichedCount} \u00eembog\u0103\u021bite` : ""}${layer.lastSynced ? `, sync: ${new Date(layer.lastSynced).toLocaleDateString("ro-RO")}` : ""}`}
|
||||
title={`${label}: ${layer.count} entități${isEnriched ? `, ${layer.enrichedCount} îmbogățite` : ""}${layer.lastSynced ? `, sync: ${new Date(layer.lastSynced).toLocaleDateString("ro-RO")}` : ""}`}
|
||||
>
|
||||
<span className="truncate max-w-[120px]">
|
||||
{label}
|
||||
|
||||
@@ -244,7 +244,7 @@ export function ExportTab({
|
||||
phase: "Finalizat",
|
||||
downloaded: prev.total ?? 100,
|
||||
total: prev.total ?? 100,
|
||||
message: `Desc\u0103rcare complet\u0103 \u2014 ${filename}`,
|
||||
message: `Descărcare completă — ${filename}`,
|
||||
note: undefined,
|
||||
}
|
||||
: null,
|
||||
@@ -365,7 +365,7 @@ export function ExportTab({
|
||||
err instanceof DOMException && err.name === "AbortError";
|
||||
if (isTimeout) {
|
||||
console.warn(
|
||||
"[no-geom-scan] Timeout after 2 min \u2014 server eTerra lent",
|
||||
"[no-geom-scan] Timeout after 2 min — server eTerra lent",
|
||||
);
|
||||
}
|
||||
setNoGeomScan({
|
||||
@@ -469,7 +469,7 @@ export function ExportTab({
|
||||
} else if (data.status === "done") {
|
||||
setBgJobId(saved.jobId);
|
||||
setBgProgress(data);
|
||||
if (data.phase) setBgPhaseTrail(["Sincronizare complet\u0103"]);
|
||||
if (data.phase) setBgPhaseTrail(["Sincronizare completă"]);
|
||||
localStorage.removeItem("parcel-sync:bg-job");
|
||||
} else {
|
||||
localStorage.removeItem("parcel-sync:bg-job");
|
||||
@@ -532,7 +532,7 @@ export function ExportTab({
|
||||
}
|
||||
startBgPolling(jid);
|
||||
} catch (error) {
|
||||
const msg = error instanceof Error ? error.message : "Eroare re\u021bea";
|
||||
const msg = error instanceof Error ? error.message : "Eroare rețea";
|
||||
console.warn("[sync-background]", msg);
|
||||
}
|
||||
},
|
||||
@@ -573,7 +573,7 @@ export function ExportTab({
|
||||
URL.revokeObjectURL(url);
|
||||
} catch (error) {
|
||||
const msg =
|
||||
error instanceof Error ? error.message : "Eroare desc\u0103rcare";
|
||||
error instanceof Error ? error.message : "Eroare descărcare";
|
||||
console.warn("[download-from-db]", msg);
|
||||
}
|
||||
setDownloadingFromDb(false);
|
||||
@@ -597,7 +597,7 @@ export function ExportTab({
|
||||
<span className="font-medium text-foreground">
|
||||
{dbTotalFeatures.toLocaleString("ro-RO")}
|
||||
</span>{" "}
|
||||
entit\u0103\u021bi \u00een DB din{" "}
|
||||
entități în DB din{" "}
|
||||
<span className="font-medium text-foreground">
|
||||
{dbLayersSummary.length}
|
||||
</span>{" "}
|
||||
@@ -664,10 +664,10 @@ export function ExportTab({
|
||||
)}
|
||||
<div className="text-left">
|
||||
<div className="font-semibold">
|
||||
Descarc\u0103 Terenuri \u0219i Cl\u0103diri
|
||||
Descarcă Terenuri și Clădiri
|
||||
</div>
|
||||
<div className="text-xs opacity-70 font-normal">
|
||||
Sync + GPKG (din cache dac\u0103 e proasp\u0103t)
|
||||
Sync + GPKG (din cache dacă e proaspăt)
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
@@ -686,7 +686,7 @@ export function ExportTab({
|
||||
<div className="text-left">
|
||||
<div className="font-semibold">Magic</div>
|
||||
<div className="text-xs opacity-70 font-normal">
|
||||
Sync + \u00eembog\u0103\u021bire (CF, proprietari, adres\u0103) + GPKG + CSV
|
||||
Sync + îmbogățire (CF, proprietari, adresă) + GPKG + CSV
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
@@ -697,12 +697,12 @@ export function ExportTab({
|
||||
{!session.connected ? (
|
||||
<>
|
||||
<Wifi className="h-10 w-10 mx-auto mb-3 opacity-30" />
|
||||
<p>Conecteaz\u0103-te la eTerra pentru a activa exportul.</p>
|
||||
<p>Conectează-te la eTerra pentru a activa exportul.</p>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<MapPin className="h-10 w-10 mx-auto mb-3 opacity-30" />
|
||||
<p>Selecteaz\u0103 un UAT pentru a activa exportul.</p>
|
||||
<p>Selectează un UAT pentru a activa exportul.</p>
|
||||
</>
|
||||
)}
|
||||
</CardContent>
|
||||
@@ -730,10 +730,10 @@ export function ExportTab({
|
||||
<CardContent className="py-3 px-4">
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<Loader2 className="h-4 w-4 animate-spin text-amber-500" />
|
||||
Se scaneaz\u0103 lista de imobile din eTerra\u2026 (max 2 min)
|
||||
Se scanează lista de imobile din eTerra… (max 2 min)
|
||||
</div>
|
||||
<p className="text-[11px] text-muted-foreground mt-1 ml-6">
|
||||
Po\u021bi folosi butoanele de mai jos f\u0103r\u0103 s\u0103 a\u0219tep\u021bi scanarea.
|
||||
Poți folosi butoanele de mai jos fără să aștepți scanarea.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -746,10 +746,10 @@ export function ExportTab({
|
||||
<CardContent className="py-3 px-4">
|
||||
<div className="flex items-center gap-2 text-sm text-amber-600 dark:text-amber-400">
|
||||
<Clock className="h-4 w-4 shrink-0" />
|
||||
Scanarea a dep\u0103\u0219it 2 minute \u2014 serverul eTerra e lent.
|
||||
Scanarea a depășit 2 minute — serverul eTerra e lent.
|
||||
</div>
|
||||
<p className="text-[11px] text-muted-foreground mt-1 ml-6">
|
||||
Po\u021bi lansa sincronizarea fundal f\u0103r\u0103 rezultate de scanare.
|
||||
Poți lansa sincronizarea fundal fără rezultate de scanare.
|
||||
Include no-geom nu va fi disponibil.
|
||||
</p>
|
||||
<Button
|
||||
@@ -759,7 +759,7 @@ export function ExportTab({
|
||||
onClick={() => void handleNoGeomScan()}
|
||||
>
|
||||
<RefreshCw className="h-3 w-3 mr-1" />
|
||||
Re\u00eencearc\u0103 scanarea
|
||||
Reîncearcă scanarea
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -779,7 +779,7 @@ export function ExportTab({
|
||||
<div className="flex items-center gap-1.5 flex-wrap text-[11px] text-muted-foreground">
|
||||
<Database className="h-3 w-3 shrink-0" />
|
||||
<span>
|
||||
Baza de date local\u0103:{" "}
|
||||
Baza de date locală:{" "}
|
||||
<span className="font-medium text-foreground">
|
||||
{noGeomScan.localDbWithGeom.toLocaleString("ro-RO")}
|
||||
</span>{" "}
|
||||
@@ -790,16 +790,16 @@ export function ExportTab({
|
||||
<span className="font-medium text-amber-600 dark:text-amber-400">
|
||||
{noGeomScan.localDbNoGeom.toLocaleString("ro-RO")}
|
||||
</span>{" "}
|
||||
f\u0103r\u0103 geometrie
|
||||
fără geometrie
|
||||
</>
|
||||
)}
|
||||
{noGeomScan.localDbEnriched > 0 && (
|
||||
<>
|
||||
{" \u00b7 "}
|
||||
{" · "}
|
||||
<span className="font-medium text-teal-600 dark:text-teal-400">
|
||||
{noGeomScan.localDbEnriched.toLocaleString("ro-RO")}
|
||||
</span>{" "}
|
||||
\u00eembog\u0103\u021bite
|
||||
îmbogățite
|
||||
{staleEnrichment && (
|
||||
<span className="text-orange-600 dark:text-orange-400">
|
||||
{" "}
|
||||
@@ -810,7 +810,7 @@ export function ExportTab({
|
||||
)}
|
||||
{noGeomScan.localSyncFresh && (
|
||||
<span className="text-emerald-600 dark:text-emerald-400 ml-1">
|
||||
(proasp\u0103t)
|
||||
(proaspăt)
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
@@ -819,9 +819,9 @@ export function ExportTab({
|
||||
<div className="flex items-center gap-1.5 text-[11px] text-orange-600 dark:text-orange-400 ml-[18px]">
|
||||
<AlertTriangle className="h-3 w-3 shrink-0" />
|
||||
<span>
|
||||
{staleCount.toLocaleString("ro-RO")} parcele au \u00eembog\u0103\u021bire
|
||||
veche (lips\u0103 PROPRIETARI_VECHI). Vor fi re-\u00eembog\u0103\u021bite la
|
||||
urm\u0103torul export Magic.
|
||||
{staleCount.toLocaleString("ro-RO")} parcele au îmbogățire
|
||||
veche (lipsă PROPRIETARI_VECHI). Vor fi re-îmbogățite la
|
||||
următorul export Magic.
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
@@ -832,11 +832,11 @@ export function ExportTab({
|
||||
const workflowPreview = scanDone && (
|
||||
<div className="mt-2 ml-7 space-y-0.5">
|
||||
<p className="text-[11px] font-medium text-muted-foreground">
|
||||
La ap\u0103sarea Magic, pa\u0219ii vor fi:
|
||||
La apăsarea Magic, pașii vor fi:
|
||||
</p>
|
||||
<ol className="text-[11px] text-muted-foreground list-decimal ml-4 space-y-px">
|
||||
<li>
|
||||
{"Sync GIS \u2014 "}
|
||||
{"Sync GIS — "}
|
||||
<span
|
||||
className={cn(
|
||||
"font-medium",
|
||||
@@ -848,16 +848,16 @@ export function ExportTab({
|
||||
>
|
||||
{noGeomScan.localSyncFresh &&
|
||||
noGeomScan.localDbWithGeom > 0
|
||||
? "skip (date proaspete \u00een DB)"
|
||||
: `descarc\u0103 ${noGeomScan.remoteGisCount.toLocaleString("ro-RO")} terenuri` +
|
||||
? "skip (date proaspete în DB)"
|
||||
: `descarcă ${noGeomScan.remoteGisCount.toLocaleString("ro-RO")} terenuri` +
|
||||
(noGeomScan.remoteCladiriCount > 0
|
||||
? ` + ${noGeomScan.remoteCladiriCount.toLocaleString("ro-RO")} cl\u0103diri`
|
||||
? ` + ${noGeomScan.remoteCladiriCount.toLocaleString("ro-RO")} clădiri`
|
||||
: "")}
|
||||
</span>
|
||||
</li>
|
||||
{includeNoGeom && (
|
||||
<li>
|
||||
Import parcele f\u0103r\u0103 geometrie \u2014{" "}
|
||||
Import parcele fără geometrie —{" "}
|
||||
<span className="font-medium text-amber-600 dark:text-amber-400">
|
||||
{(() => {
|
||||
const usefulNoGeom =
|
||||
@@ -878,7 +878,7 @@ export function ExportTab({
|
||||
</li>
|
||||
)}
|
||||
<li>
|
||||
\u00cembog\u0103\u021bire CF, proprietari, adrese \u2014{" "}
|
||||
\u00cembogățire CF, proprietari, adrese —{" "}
|
||||
<span className="font-medium text-teal-600 dark:text-teal-400">
|
||||
{(() => {
|
||||
// What will be in DB after sync + optional no-geom import:
|
||||
@@ -900,12 +900,12 @@ export function ExportTab({
|
||||
totalAfter - noGeomScan.localDbEnrichedComplete;
|
||||
return remaining > 0
|
||||
? `~${remaining.toLocaleString("ro-RO")} de procesat (~${Math.ceil((remaining * 0.25) / 60)} min)`
|
||||
: "deja \u00eembog\u0103\u021bite";
|
||||
: "deja îmbogățite";
|
||||
})()}
|
||||
</span>
|
||||
</li>
|
||||
<li>Generare GPKG + CSV</li>
|
||||
<li>Comprimare ZIP + desc\u0103rcare</li>
|
||||
<li>Comprimare ZIP + descărcare</li>
|
||||
</ol>
|
||||
</div>
|
||||
);
|
||||
@@ -939,10 +939,10 @@ export function ExportTab({
|
||||
"ro-RO",
|
||||
)}
|
||||
</span>{" "}
|
||||
cl\u0103diri
|
||||
clădiri
|
||||
</>
|
||||
)}
|
||||
{" \u00b7 "}
|
||||
{" · "}
|
||||
Lista imobile:{" "}
|
||||
<span className="font-semibold">
|
||||
{noGeomScan.totalImmovables.toLocaleString("ro-RO")}
|
||||
@@ -956,11 +956,11 @@ export function ExportTab({
|
||||
noGeomScan.remoteGisCount,
|
||||
).toLocaleString("ro-RO")}
|
||||
</span>
|
||||
{" f\u0103r\u0103 geometrie)"}
|
||||
{" fără geometrie)"}
|
||||
</p>
|
||||
<p className="text-[11px] text-muted-foreground mt-0.5">
|
||||
Cele f\u0103r\u0103 geometrie exist\u0103 \u00een baza de date eTerra dar
|
||||
nu au contur desenat \u00een layerul GIS.
|
||||
Cele fără geometrie există în baza de date eTerra dar
|
||||
nu au contur desenat în layerul GIS.
|
||||
</p>
|
||||
{localDbLine}
|
||||
</div>
|
||||
@@ -984,7 +984,7 @@ export function ExportTab({
|
||||
className="h-4 w-4 rounded border-muted-foreground/30 accent-amber-600"
|
||||
/>
|
||||
<span className="text-sm font-medium">
|
||||
Include \u0219i parcelele f\u0103r\u0103 geometrie la export
|
||||
Include și parcelele fără geometrie la export
|
||||
</span>
|
||||
</label>
|
||||
{/* Quality breakdown of no-geom items */}
|
||||
@@ -992,7 +992,7 @@ export function ExportTab({
|
||||
<div className="ml-7 p-2 rounded-md bg-muted/40 space-y-1">
|
||||
<p className="text-[11px] font-medium text-muted-foreground">
|
||||
Calitate date (din{" "}
|
||||
{noGeomScan.noGeomCount.toLocaleString("ro-RO")} f\u0103r\u0103
|
||||
{noGeomScan.noGeomCount.toLocaleString("ro-RO")} fără
|
||||
geometrie):
|
||||
</p>
|
||||
<div className="grid grid-cols-2 gap-x-4 gap-y-0.5 text-[11px] text-muted-foreground">
|
||||
@@ -1013,7 +1013,7 @@ export function ExportTab({
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
Cu nr. cad. pe h\u00e2rtie:{" "}
|
||||
Cu nr. cad. pe hârtie:{" "}
|
||||
<span className="font-medium text-foreground">
|
||||
{noGeomScan.qualityBreakdown.withPaperCad.toLocaleString(
|
||||
"ro-RO",
|
||||
@@ -1021,7 +1021,7 @@ export function ExportTab({
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
Cu suprafa\u021b\u0103:{" "}
|
||||
Cu suprafață:{" "}
|
||||
<span className="font-medium text-foreground">
|
||||
{noGeomScan.qualityBreakdown.withArea.toLocaleString(
|
||||
"ro-RO",
|
||||
@@ -1037,7 +1037,7 @@ export function ExportTab({
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
Cu carte funciar\u0103:{" "}
|
||||
Cu carte funciară:{" "}
|
||||
<span className="font-medium text-foreground">
|
||||
{noGeomScan.qualityBreakdown.withLandbook.toLocaleString(
|
||||
"ro-RO",
|
||||
@@ -1056,7 +1056,7 @@ export function ExportTab({
|
||||
</span>
|
||||
{noGeomScan.qualityBreakdown.empty > 0 && (
|
||||
<span>
|
||||
Filtrate (f\u0103r\u0103 CF/inactive/f\u0103r\u0103 date):{" "}
|
||||
Filtrate (fără CF/inactive/fără date):{" "}
|
||||
<span className="font-semibold text-rose-600 dark:text-rose-400">
|
||||
{noGeomScan.qualityBreakdown.empty.toLocaleString(
|
||||
"ro-RO",
|
||||
@@ -1070,9 +1070,9 @@ export function ExportTab({
|
||||
{includeNoGeom && (
|
||||
<p className="text-[11px] text-muted-foreground ml-7">
|
||||
{noGeomScan.qualityBreakdown.empty > 0
|
||||
? `Din ${noGeomScan.noGeomCount.toLocaleString("ro-RO")} f\u0103r\u0103 geometrie, ~${noGeomScan.qualityBreakdown.useful.toLocaleString("ro-RO")} vor fi importate (imobile electronice cu CF). ${noGeomScan.qualityBreakdown.empty.toLocaleString("ro-RO")} vor fi filtrate (f\u0103r\u0103 carte funciar\u0103, inactive sau f\u0103r\u0103 date).`
|
||||
: "Vor fi importate \u00een DB \u0219i incluse \u00een CSV + Magic GPKG (coloana HAS_GEOMETRY=0/1)."}{" "}
|
||||
\u00cen GPKG de baz\u0103 apar doar cele cu geometrie.
|
||||
? `Din ${noGeomScan.noGeomCount.toLocaleString("ro-RO")} fără geometrie, ~${noGeomScan.qualityBreakdown.useful.toLocaleString("ro-RO")} vor fi importate (imobile electronice cu CF). ${noGeomScan.qualityBreakdown.empty.toLocaleString("ro-RO")} vor fi filtrate (fără carte funciară, inactive sau fără date).`
|
||||
: "Vor fi importate în DB și incluse în CSV + Magic GPKG (coloana HAS_GEOMETRY=0/1)."}{" "}
|
||||
\u00cen GPKG de bază apar doar cele cu geometrie.
|
||||
</p>
|
||||
)}
|
||||
{workflowPreview}
|
||||
@@ -1091,14 +1091,14 @@ export function ExportTab({
|
||||
<CheckCircle2 className="h-3.5 w-3.5 text-emerald-500" />
|
||||
Toate cele{" "}
|
||||
{noGeomScan.totalImmovables.toLocaleString("ro-RO")}{" "}
|
||||
imobile din eTerra au geometrie \u2014 nimic de importat
|
||||
imobile din eTerra au geometrie — nimic de importat
|
||||
suplimentar.
|
||||
{noGeomScan.localDbTotal > 0 && (
|
||||
<span className="ml-1">
|
||||
({noGeomScan.localDbTotal.toLocaleString("ro-RO")}{" "}
|
||||
\u00een DB local
|
||||
în DB local
|
||||
{noGeomScan.localDbEnriched > 0 &&
|
||||
`, ${noGeomScan.localDbEnriched.toLocaleString("ro-RO")} \u00eembog\u0103\u021bite`}
|
||||
`, ${noGeomScan.localDbEnriched.toLocaleString("ro-RO")} îmbogățite`}
|
||||
{noGeomScan.localDbEnriched > 0 &&
|
||||
noGeomScan.localDbEnrichedComplete <
|
||||
noGeomScan.localDbEnriched && (
|
||||
@@ -1106,15 +1106,15 @@ export function ExportTab({
|
||||
{` (${(noGeomScan.localDbEnriched - noGeomScan.localDbEnrichedComplete).toLocaleString("ro-RO")} incomplete)`}
|
||||
</span>
|
||||
)}
|
||||
{noGeomScan.localSyncFresh && ", proasp\u0103t"})
|
||||
{noGeomScan.localSyncFresh && ", proaspăt"})
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<AlertTriangle className="h-3.5 w-3.5 text-muted-foreground" />
|
||||
Nu s-au g\u0103sit imobile \u00een lista eTerra pentru acest
|
||||
UAT. Verific\u0103 sesiunea eTerra.
|
||||
Nu s-au găsit imobile în lista eTerra pentru acest
|
||||
UAT. Verifică sesiunea eTerra.
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
@@ -1133,10 +1133,10 @@ export function ExportTab({
|
||||
<div className="flex items-center gap-2">
|
||||
<HardDrive className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-sm font-medium">
|
||||
Procesare fundal & desc\u0103rcare din DB
|
||||
Procesare fundal & descărcare din DB
|
||||
</span>
|
||||
<span className="text-[10px] text-muted-foreground">
|
||||
\u2014 porne\u0219te sincronizarea, \u00eenchide pagina, descarc\u0103 mai t\u00e2rziu
|
||||
— pornește sincronizarea, închide pagina, descarcă mai târziu
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -1154,11 +1154,11 @@ export function ExportTab({
|
||||
className="h-4 w-4 rounded border-muted-foreground/30 accent-amber-600"
|
||||
/>
|
||||
<span className="text-xs">
|
||||
Include \u0219i parcelele f\u0103r\u0103 geometrie
|
||||
Include și parcelele fără geometrie
|
||||
</span>
|
||||
{noGeomScanning && (
|
||||
<span className="text-[10px] text-muted-foreground">
|
||||
(scanare \u00een curs\u2026)
|
||||
(scanare în curs…)
|
||||
</span>
|
||||
)}
|
||||
</label>
|
||||
@@ -1179,17 +1179,17 @@ export function ExportTab({
|
||||
>
|
||||
{bgJobId &&
|
||||
bgProgress?.status === "running" &&
|
||||
!bgPhaseTrail.some((p) => p.includes("\u00cembog\u0103\u021bire")) ? (
|
||||
!bgPhaseTrail.some((p) => p.includes("\u00cembogățire")) ? (
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
) : (
|
||||
<ArrowDownToLine className="mr-2 h-4 w-4" />
|
||||
)}
|
||||
<div className="text-left">
|
||||
<div className="text-xs font-semibold">
|
||||
Sync fundal \u2014 Baz\u0103
|
||||
Sync fundal — Bază
|
||||
</div>
|
||||
<div className="text-[10px] opacity-60 font-normal">
|
||||
Terenuri + cl\u0103diri \u2192 salveaz\u0103 \u00een DB
|
||||
Terenuri + clădiri \u2192 salvează în DB
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
@@ -1205,17 +1205,17 @@ export function ExportTab({
|
||||
>
|
||||
{bgJobId &&
|
||||
bgProgress?.status === "running" &&
|
||||
bgPhaseTrail.some((p) => p.includes("\u00cembog\u0103\u021bire")) ? (
|
||||
bgPhaseTrail.some((p) => p.includes("\u00cembogățire")) ? (
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin text-teal-600" />
|
||||
) : (
|
||||
<Sparkles className="mr-2 h-4 w-4 text-teal-600" />
|
||||
)}
|
||||
<div className="text-left">
|
||||
<div className="text-xs font-semibold">
|
||||
Sync fundal \u2014 Magic
|
||||
Sync fundal — Magic
|
||||
</div>
|
||||
<div className="text-[10px] opacity-60 font-normal">
|
||||
Sync + \u00eembog\u0103\u021bire \u2192 salveaz\u0103 \u00een DB
|
||||
Sync + îmbogățire \u2192 salvează în DB
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
@@ -1239,10 +1239,10 @@ export function ExportTab({
|
||||
)}
|
||||
<div className="text-left">
|
||||
<div className="text-xs font-semibold">
|
||||
Descarc\u0103 din DB \u2014 Baz\u0103
|
||||
Descarcă din DB — Bază
|
||||
</div>
|
||||
<div className="text-[10px] opacity-60 font-normal">
|
||||
GPKG terenuri + cl\u0103diri (instant, f\u0103r\u0103 eTerra)
|
||||
GPKG terenuri + clădiri (instant, fără eTerra)
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
@@ -1260,7 +1260,7 @@ export function ExportTab({
|
||||
)}
|
||||
<div className="text-left">
|
||||
<div className="text-xs font-semibold">
|
||||
Descarc\u0103 din DB \u2014 Magic
|
||||
Descarcă din DB — Magic
|
||||
</div>
|
||||
<div className="text-[10px] opacity-60 font-normal">
|
||||
GPKG + CSV + raport calitate (instant)
|
||||
@@ -1272,8 +1272,8 @@ export function ExportTab({
|
||||
|
||||
{!session.connected && dbTotalFeatures === 0 && (
|
||||
<p className="text-xs text-muted-foreground ml-6">
|
||||
Conecteaz\u0103-te la eTerra pentru a porni sincronizarea fundal,
|
||||
sau sincronizeaz\u0103 mai \u00eent\u00e2i date \u00een baza local\u0103.
|
||||
Conectează-te la eTerra pentru a porni sincronizarea fundal,
|
||||
sau sincronizează mai întâi date în baza locală.
|
||||
</p>
|
||||
)}
|
||||
</CardContent>
|
||||
@@ -1302,7 +1302,7 @@ export function ExportTab({
|
||||
</span>
|
||||
{bgProgress.status === "running" && (
|
||||
<span className="text-muted-foreground">
|
||||
(po\u021bi \u00eenchide pagina)
|
||||
(poți închide pagina)
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@@ -1396,7 +1396,7 @@ export function ExportTab({
|
||||
) : (
|
||||
<Database className="mr-1.5 h-3 w-3" />
|
||||
)}
|
||||
Descarc\u0103 din DB (Magic)
|
||||
Descarcă din DB (Magic)
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
@@ -1466,7 +1466,7 @@ export function ExportTab({
|
||||
{exportProgress.phase}
|
||||
{exportProgress.phaseCurrent != null &&
|
||||
exportProgress.phaseTotal
|
||||
? ` \u2014 ${exportProgress.phaseCurrent} / ${exportProgress.phaseTotal}`
|
||||
? ` — ${exportProgress.phaseCurrent} / ${exportProgress.phaseTotal}`
|
||||
: ""}
|
||||
</p>
|
||||
{exportProgress.note && (
|
||||
|
||||
@@ -239,7 +239,7 @@ export function LayersTab({
|
||||
async (layerId: string) => {
|
||||
if (!siruta || syncingLayer) return;
|
||||
setSyncingLayer(layerId);
|
||||
setSyncProgress("Sincronizare pornit\u0103\u2026");
|
||||
setSyncProgress("Sincronizare pornită…");
|
||||
try {
|
||||
const res = await fetch("/api/eterra/sync", {
|
||||
method: "POST",
|
||||
@@ -261,13 +261,13 @@ export function LayersTab({
|
||||
setSyncProgress(`Eroare: ${data.error}`);
|
||||
} else {
|
||||
setSyncProgress(
|
||||
`Finalizat \u2014 ${data.newFeatures ?? 0} noi, ${data.removedFeatures ?? 0} \u0219terse, ${data.totalLocal ?? 0} total local`,
|
||||
`Finalizat — ${data.newFeatures ?? 0} noi, ${data.removedFeatures ?? 0} șterse, ${data.totalLocal ?? 0} total local`,
|
||||
);
|
||||
// Refresh sync status
|
||||
onSyncRefresh();
|
||||
}
|
||||
} catch {
|
||||
setSyncProgress("Eroare re\u021bea");
|
||||
setSyncProgress("Eroare rețea");
|
||||
}
|
||||
// Clear progress after 8s
|
||||
setTimeout(() => {
|
||||
@@ -334,7 +334,7 @@ export function LayersTab({
|
||||
for (const layerId of layerIds) {
|
||||
setSyncingLayer(layerId);
|
||||
setSyncProgress(
|
||||
`Sincronizare ${LAYER_CATALOG.find((l) => l.id === layerId)?.label ?? layerId}\u2026`,
|
||||
`Sincronizare ${LAYER_CATALOG.find((l) => l.id === layerId)?.label ?? layerId}…`,
|
||||
);
|
||||
try {
|
||||
const res = await fetch("/api/eterra/sync", {
|
||||
@@ -356,7 +356,7 @@ export function LayersTab({
|
||||
setSyncProgress(`Eroare: ${data.error}`);
|
||||
}
|
||||
} catch {
|
||||
setSyncProgress("Eroare re\u021bea");
|
||||
setSyncProgress("Eroare rețea");
|
||||
}
|
||||
// Remove from queue
|
||||
syncQueueRef.current = syncQueueRef.current.filter(
|
||||
@@ -445,7 +445,7 @@ export function LayersTab({
|
||||
phase: "Finalizat",
|
||||
downloaded: prev.total ?? 100,
|
||||
total: prev.total ?? 100,
|
||||
message: `Desc\u0103rcare complet\u0103 \u2014 ${filename}`,
|
||||
message: `Descărcare completă — ${filename}`,
|
||||
note: undefined,
|
||||
}
|
||||
: null,
|
||||
@@ -489,8 +489,8 @@ export function LayersTab({
|
||||
<Layers className="h-10 w-10 mx-auto mb-3 opacity-30" />
|
||||
<p>
|
||||
{!session.connected
|
||||
? "Conecteaz\u0103-te la eTerra \u0219i selecteaz\u0103 un UAT."
|
||||
: "Selecteaz\u0103 un UAT pentru a vedea catalogul de layere."}
|
||||
? "Conectează-te la eTerra și selectează un UAT."
|
||||
: "Selectează un UAT pentru a vedea catalogul de layere."}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -504,8 +504,8 @@ export function LayersTab({
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{layerCountSiruta === siruta &&
|
||||
Object.keys(layerCounts).length > 0
|
||||
? `Num\u0103r features pentru SIRUTA ${siruta}`
|
||||
: "Apas\u0103 pentru a num\u0103ra features-urile din fiecare layer."}
|
||||
? `Număr features pentru SIRUTA ${siruta}`
|
||||
: "Apasă pentru a număra features-urile din fiecare layer."}
|
||||
</p>
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Export from local DB */}
|
||||
@@ -537,7 +537,7 @@ export function LayersTab({
|
||||
) : (
|
||||
<Search className="h-3.5 w-3.5 mr-1.5" />
|
||||
)}
|
||||
{countingLayers ? "Se num\u0103r\u0103\u2026" : "Num\u0103r\u0103"}
|
||||
{countingLayers ? "Se numără…" : "Numără"}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -712,7 +712,7 @@ export function LayersTab({
|
||||
void handleSyncLayer(layer.id)
|
||||
}
|
||||
className="border-violet-200 dark:border-violet-800"
|
||||
title="Sincronizeaz\u0103 \u00een baza de date"
|
||||
title="Sincronizează în baza de date"
|
||||
>
|
||||
{isSyncing ? (
|
||||
<Loader2 className="h-3.5 w-3.5 animate-spin" />
|
||||
@@ -733,8 +733,8 @@ export function LayersTab({
|
||||
}
|
||||
title={
|
||||
localCount > 0
|
||||
? "Descarc\u0103 GPKG (din cache dac\u0103 e proasp\u0103t)"
|
||||
: "Sincronizeaz\u0103 + descarc\u0103 GPKG"
|
||||
? "Descarcă GPKG (din cache dacă e proaspăt)"
|
||||
: "Sincronizează + descarcă GPKG"
|
||||
}
|
||||
>
|
||||
{isDownloading ? (
|
||||
@@ -787,7 +787,7 @@ export function LayersTab({
|
||||
<p className="text-[11px] font-semibold text-muted-foreground">
|
||||
SIRUTA {sir}{" "}
|
||||
<span className="font-normal opacity-70">
|
||||
\u2014{" "}
|
||||
—{" "}
|
||||
{new Date(entries[0]!.time).toLocaleTimeString(
|
||||
"ro-RO",
|
||||
{ hour: "2-digit", minute: "2-digit" },
|
||||
@@ -845,7 +845,7 @@ export function LayersTab({
|
||||
<Database className="h-3.5 w-3.5 mr-1.5" />
|
||||
)}
|
||||
{postgisRunning
|
||||
? "Se activeaza\u2026"
|
||||
? "Se activeaza…"
|
||||
: "Activeaza compatibilitate QGIS"}
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
@@ -871,7 +871,7 @@ export function LayersTab({
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckCircle2 className="h-4 w-4 text-emerald-500" />
|
||||
<span className="text-sm font-medium text-emerald-700 dark:text-emerald-400">
|
||||
QGIS compatibil \u2014 gata de conectare
|
||||
QGIS compatibil — gata de conectare
|
||||
</span>
|
||||
</div>
|
||||
<div className="rounded bg-muted/50 p-3 text-xs space-y-2">
|
||||
@@ -946,7 +946,7 @@ export function LayersTab({
|
||||
si limitelor UAT.
|
||||
</p>
|
||||
<p>
|
||||
Apasa butonul pentru a activa \u2014 creeaza view-uri read-only
|
||||
Apasa butonul pentru a activa — creeaza view-uri read-only
|
||||
(nu modifica datele, nu afecteaza performanta aplicatiei).
|
||||
</p>
|
||||
</div>
|
||||
@@ -965,7 +965,7 @@ export function LayersTab({
|
||||
{exportProgress.phase}
|
||||
{exportProgress.phaseCurrent != null &&
|
||||
exportProgress.phaseTotal
|
||||
? ` \u2014 ${exportProgress.phaseCurrent} / ${exportProgress.phaseTotal}`
|
||||
? ` — ${exportProgress.phaseCurrent} / ${exportProgress.phaseTotal}`
|
||||
: ""}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -321,7 +321,7 @@ export function MapTab({ siruta, sirutaValid }: MapTabProps) {
|
||||
<Card>
|
||||
<CardContent className="py-12 text-center text-muted-foreground">
|
||||
<MapIcon className="h-10 w-10 mx-auto mb-3 opacity-30" />
|
||||
<p>Selecteaz\u0103 un UAT din lista de mai sus</p>
|
||||
<p>Selectează un UAT din lista de mai sus</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
@@ -332,7 +332,7 @@ export function MapTab({ siruta, sirutaValid }: MapTabProps) {
|
||||
{boundsLoading && (
|
||||
<div className="absolute top-3 left-1/2 -translate-x-1/2 z-20 flex items-center gap-2 rounded-full bg-background/90 border px-3 py-1.5 text-xs shadow-sm">
|
||||
<Loader2 className="h-3 w-3 animate-spin" />
|
||||
Se \u00eencarc\u0103 zona UAT...
|
||||
Se încarcă zona UAT...
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -376,7 +376,7 @@ export function MapTab({ siruta, sirutaValid }: MapTabProps) {
|
||||
<div className="absolute bottom-3 right-3 z-10 rounded-lg bg-background/90 border p-2 text-[10px] space-y-1">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="inline-block h-3 w-3 rounded-sm border" style={{ backgroundColor: "rgba(134,239,172,0.25)", borderColor: "#15803d" }} />
|
||||
F\u0103r\u0103 enrichment
|
||||
Fără enrichment
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="inline-block h-3 w-3 rounded-sm border" style={{ backgroundColor: "rgba(21,128,61,0.25)", borderColor: "#15803d" }} />
|
||||
@@ -384,11 +384,11 @@ export function MapTab({ siruta, sirutaValid }: MapTabProps) {
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="inline-block h-3 w-3 rounded-sm" style={{ border: "2px solid #3b82f6" }} />
|
||||
Cu cl\u0103dire
|
||||
Cu clădire
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="inline-block h-3 w-3 rounded-sm" style={{ border: "2px solid #ef4444" }} />
|
||||
Cl\u0103dire f\u0103r\u0103 acte
|
||||
Clădire fără acte
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -123,7 +123,7 @@ export function SearchTab({
|
||||
setSearchError("");
|
||||
}
|
||||
} catch {
|
||||
setSearchError("Eroare de re\u021bea.");
|
||||
setSearchError("Eroare de rețea.");
|
||||
}
|
||||
setLoadingFeatures(false);
|
||||
}, [siruta, featuresSearch, workspacePk]);
|
||||
@@ -178,12 +178,12 @@ export function SearchTab({
|
||||
if (data.eterraNote) notes.push(data.eterraNote);
|
||||
setOwnerNote(
|
||||
notes.length > 0
|
||||
? `Surse: ${notes.join(" + ")}${data.total ? ` \u00b7 ${data.total} rezultate` : ""}`
|
||||
? `Surse: ${notes.join(" + ")}${data.total ? ` · ${data.total} rezultate` : ""}`
|
||||
: "",
|
||||
);
|
||||
}
|
||||
} catch {
|
||||
setOwnerError("Eroare de re\u021bea.");
|
||||
setOwnerError("Eroare de rețea.");
|
||||
}
|
||||
setOwnerLoading(false);
|
||||
}, [siruta, ownerSearch, workspacePk]);
|
||||
@@ -596,7 +596,7 @@ export function SearchTab({
|
||||
<Card>
|
||||
<CardContent className="py-12 text-center text-muted-foreground">
|
||||
<Search className="h-10 w-10 mx-auto mb-3 opacity-30" />
|
||||
<p>Selecteaz\u0103 un UAT mai sus pentru a c\u0103uta parcele.</p>
|
||||
<p>Selectează un UAT mai sus pentru a căuta parcele.</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
@@ -640,7 +640,7 @@ export function SearchTab({
|
||||
<div className="flex gap-3 items-end">
|
||||
<div className="space-y-1 flex-1">
|
||||
<Label className="text-xs">
|
||||
Numere cadastrale (separate prin virgul\u0103 sau Enter)
|
||||
Numere cadastrale (separate prin virgulă sau Enter)
|
||||
</Label>
|
||||
<div className="relative">
|
||||
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
@@ -655,8 +655,8 @@ export function SearchTab({
|
||||
</div>
|
||||
{!session.connected && (
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Necesit\u0103 conexiune eTerra. Folose\u0219te modul Proprietar
|
||||
pentru a c\u0103uta offline \u00een DB.
|
||||
Necesită conexiune eTerra. Folosește modul Proprietar
|
||||
pentru a căuta offline în DB.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
@@ -673,7 +673,7 @@ export function SearchTab({
|
||||
) : (
|
||||
<Search className="mr-2 h-4 w-4" />
|
||||
)}
|
||||
Caut\u0103
|
||||
Caută
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
@@ -683,7 +683,7 @@ export function SearchTab({
|
||||
<div className="flex gap-3 items-end">
|
||||
<div className="space-y-1 flex-1">
|
||||
<Label className="text-xs">
|
||||
Nume proprietar (caut\u0103 \u00een DB local + eTerra)
|
||||
Nume proprietar (caută în DB local + eTerra)
|
||||
</Label>
|
||||
<div className="relative">
|
||||
<User className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
@@ -705,7 +705,7 @@ export function SearchTab({
|
||||
) : (
|
||||
<Search className="mr-2 h-4 w-4" />
|
||||
)}
|
||||
Caut\u0103
|
||||
Caută
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
@@ -729,10 +729,10 @@ export function SearchTab({
|
||||
<Card>
|
||||
<CardContent className="py-12 text-center text-muted-foreground">
|
||||
<Loader2 className="h-10 w-10 mx-auto mb-3 animate-spin opacity-50" />
|
||||
<p>Se caut\u0103 \u00een eTerra...</p>
|
||||
<p>Se caută în eTerra...</p>
|
||||
<p className="text-xs mt-1 opacity-60">
|
||||
Prima c\u0103utare pe un UAT nou poate dura ~10-30s (se
|
||||
\u00eencarc\u0103 lista de jude\u021be).
|
||||
Prima căutare pe un UAT nou poate dura ~10-30s (se
|
||||
încarcă lista de județe).
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -747,7 +747,7 @@ export function SearchTab({
|
||||
{searchResults.length > 1 ? "e" : ""}
|
||||
{searchList.length > 0 && (
|
||||
<span className="ml-2">
|
||||
· <strong>{searchList.length}</strong> \u00een list\u0103
|
||||
· <strong>{searchList.length}</strong> în listă
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
@@ -761,7 +761,7 @@ export function SearchTab({
|
||||
}}
|
||||
>
|
||||
<Plus className="mr-1 h-3.5 w-3.5" />
|
||||
Adaug\u0103 toate \u00een list\u0103
|
||||
Adaugă toate în listă
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
@@ -773,7 +773,7 @@ export function SearchTab({
|
||||
}
|
||||
>
|
||||
<FileDown className="mr-1 h-3.5 w-3.5" />
|
||||
Descarc\u0103 CSV
|
||||
Descarcă CSV
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -796,7 +796,7 @@ export function SearchTab({
|
||||
</h3>
|
||||
{!p.immovablePk && (
|
||||
<p className="text-xs text-destructive">
|
||||
Parcela nu a fost g\u0103sit\u0103 \u00een eTerra.
|
||||
Parcela nu a fost găsită în eTerra.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
@@ -805,7 +805,7 @@ export function SearchTab({
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
className="h-7 w-7 p-0"
|
||||
title="Adaug\u0103 \u00een list\u0103"
|
||||
title="Adaugă în listă"
|
||||
onClick={() => addToList(p)}
|
||||
disabled={!p.immovablePk}
|
||||
>
|
||||
@@ -819,7 +819,7 @@ export function SearchTab({
|
||||
onClick={() => {
|
||||
const text = [
|
||||
`Nr. Cad: ${p.nrCad}`,
|
||||
`Nr. CF: ${p.nrCF || "\u2014"}`,
|
||||
`Nr. CF: ${p.nrCF || "—"}`,
|
||||
p.nrCFVechi
|
||||
? `CF vechi: ${p.nrCFVechi}`
|
||||
: null,
|
||||
@@ -829,7 +829,7 @@ export function SearchTab({
|
||||
p.suprafata != null
|
||||
? `Suprafata: ${p.suprafata.toLocaleString("ro-RO")} mp`
|
||||
: null,
|
||||
`Intravilan: ${p.intravilan || "\u2014"}`,
|
||||
`Intravilan: ${p.intravilan || "—"}`,
|
||||
p.categorieFolosinta
|
||||
? `Categorie: ${p.categorieFolosinta}`
|
||||
: null,
|
||||
@@ -870,7 +870,7 @@ export function SearchTab({
|
||||
Nr. CF
|
||||
</span>
|
||||
<span className="font-medium">
|
||||
{p.nrCF || "\u2014"}
|
||||
{p.nrCF || "—"}
|
||||
</span>
|
||||
</div>
|
||||
{p.nrCFVechi && (
|
||||
@@ -885,16 +885,16 @@ export function SearchTab({
|
||||
<span className="text-xs text-muted-foreground block">
|
||||
Nr. Topo
|
||||
</span>
|
||||
<span>{p.nrTopo || "\u2014"}</span>
|
||||
<span>{p.nrTopo || "—"}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-xs text-muted-foreground block">
|
||||
Suprafa\u021b\u0103
|
||||
Suprafață
|
||||
</span>
|
||||
<span className="tabular-nums">
|
||||
{p.suprafata != null
|
||||
? formatArea(p.suprafata)
|
||||
: "\u2014"}
|
||||
: "—"}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
@@ -911,13 +911,13 @@ export function SearchTab({
|
||||
}
|
||||
className="text-[11px]"
|
||||
>
|
||||
{p.intravilan || "\u2014"}
|
||||
{p.intravilan || "—"}
|
||||
</Badge>
|
||||
</div>
|
||||
{p.categorieFolosinta && (
|
||||
<div className="col-span-2">
|
||||
<span className="text-xs text-muted-foreground block">
|
||||
Categorii folosin\u021b\u0103
|
||||
Categorii folosință
|
||||
</span>
|
||||
<span className="text-xs">
|
||||
{p.categorieFolosinta}
|
||||
@@ -927,7 +927,7 @@ export function SearchTab({
|
||||
{p.adresa && (
|
||||
<div className="col-span-2">
|
||||
<span className="text-xs text-muted-foreground block">
|
||||
Adres\u0103
|
||||
Adresă
|
||||
</span>
|
||||
<span>{p.adresa}</span>
|
||||
</div>
|
||||
@@ -991,10 +991,10 @@ export function SearchTab({
|
||||
<Card>
|
||||
<CardContent className="py-12 text-center text-muted-foreground">
|
||||
<Search className="h-10 w-10 mx-auto mb-3 opacity-30" />
|
||||
<p>Introdu un num\u0103r cadastral \u0219i apas\u0103 Caut\u0103.</p>
|
||||
<p>Introdu un număr cadastral și apasă Caută.</p>
|
||||
<p className="text-xs mt-1 opacity-60">
|
||||
Po\u021bi c\u0103uta mai multe parcele simultan, separate prin
|
||||
virgul\u0103.
|
||||
Poți căuta mai multe parcele simultan, separate prin
|
||||
virgulă.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -1009,9 +1009,9 @@ export function SearchTab({
|
||||
<Card>
|
||||
<CardContent className="py-12 text-center text-muted-foreground">
|
||||
<Loader2 className="h-10 w-10 mx-auto mb-3 animate-spin opacity-50" />
|
||||
<p>Se caut\u0103 proprietar...</p>
|
||||
<p>Se caută proprietar...</p>
|
||||
<p className="text-xs mt-1 opacity-60">
|
||||
Caut\u0103 mai \u00eent\u00e2i \u00een DB local (date \u00eembog\u0103\u021bite), apoi pe
|
||||
Caută mai întâi în DB local (date îmbogățite), apoi pe
|
||||
eTerra.
|
||||
</p>
|
||||
</CardContent>
|
||||
@@ -1036,7 +1036,7 @@ export function SearchTab({
|
||||
}}
|
||||
>
|
||||
<Plus className="mr-1 h-3.5 w-3.5" />
|
||||
Adaug\u0103 toate \u00een list\u0103
|
||||
Adaugă toate în listă
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
@@ -1047,7 +1047,7 @@ export function SearchTab({
|
||||
}
|
||||
>
|
||||
<FileDown className="mr-1 h-3.5 w-3.5" />
|
||||
Descarc\u0103 CSV
|
||||
Descarcă CSV
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1075,7 +1075,7 @@ export function SearchTab({
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
className="h-7 w-7 p-0"
|
||||
title="Adaug\u0103 \u00een list\u0103"
|
||||
title="Adaugă în listă"
|
||||
onClick={() =>
|
||||
addToList(ownerResultToParcelDetail(r))
|
||||
}
|
||||
@@ -1128,7 +1128,7 @@ export function SearchTab({
|
||||
{r.suprafata && (
|
||||
<div>
|
||||
<span className="text-xs text-muted-foreground block">
|
||||
Suprafa\u021b\u0103
|
||||
Suprafață
|
||||
</span>
|
||||
<span className="tabular-nums">
|
||||
{typeof r.suprafata === "number"
|
||||
@@ -1159,7 +1159,7 @@ export function SearchTab({
|
||||
{r.categorieFolosinta && (
|
||||
<div className="col-span-2">
|
||||
<span className="text-xs text-muted-foreground block">
|
||||
Categorii folosin\u021b\u0103
|
||||
Categorii folosință
|
||||
</span>
|
||||
<span className="text-xs">
|
||||
{r.categorieFolosinta}
|
||||
@@ -1169,7 +1169,7 @@ export function SearchTab({
|
||||
{r.adresa && (
|
||||
<div className="col-span-2">
|
||||
<span className="text-xs text-muted-foreground block">
|
||||
Adres\u0103
|
||||
Adresă
|
||||
</span>
|
||||
<span>{r.adresa}</span>
|
||||
</div>
|
||||
@@ -1206,12 +1206,12 @@ export function SearchTab({
|
||||
<Card>
|
||||
<CardContent className="py-12 text-center text-muted-foreground">
|
||||
<User className="h-10 w-10 mx-auto mb-3 opacity-30" />
|
||||
<p>Introdu numele proprietarului \u0219i apas\u0103 Caut\u0103.</p>
|
||||
<p>Introdu numele proprietarului și apasă Caută.</p>
|
||||
<p className="text-xs mt-1 opacity-60">
|
||||
Caut\u0103 \u00een datele \u00eembog\u0103\u021bite (DB local) \u0219i pe eTerra.
|
||||
Caută în datele îmbogățite (DB local) și pe eTerra.
|
||||
<br />
|
||||
Pentru rezultate complete, lanseaz\u0103 "Sync fundal \u2014
|
||||
Magic" \u00een tab-ul Export.
|
||||
Pentru rezultate complete, lansează "Sync fundal —
|
||||
Magic" în tab-ul Export.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -1377,15 +1377,15 @@ export function SearchTab({
|
||||
{p.nrCad}
|
||||
</td>
|
||||
<td className="px-3 py-2 text-xs">
|
||||
{p.nrCF || "\u2014"}
|
||||
{p.nrCF || "—"}
|
||||
</td>
|
||||
<td className="px-3 py-2 text-right hidden sm:table-cell tabular-nums text-xs">
|
||||
{p.suprafata != null
|
||||
? formatArea(p.suprafata)
|
||||
: "\u2014"}
|
||||
: "—"}
|
||||
</td>
|
||||
<td className="px-3 py-2 hidden md:table-cell text-xs truncate max-w-[300px]">
|
||||
{p.proprietari || "\u2014"}
|
||||
{p.proprietari || "—"}
|
||||
</td>
|
||||
<td className="px-3 py-2 text-center">
|
||||
<TooltipProvider>
|
||||
|
||||
Reference in New Issue
Block a user