Dashboard page showing:
- nginx tile-cache status (connections, requests)
- Martin tile server sources
- PMTiles file info (size, last modified)
- Cache HIT/MISS test on sample tiles
- Configuration summary
Action buttons:
- Rebuild PMTiles (triggers N8N webhook)
- Warm Cache (fetches common tiles from container)
Auto-refreshes every 30 seconds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Building labels (C1/C2/C3) disabled — Martin MVT tiles don't include
cadastral_ref as a property despite the PostgreSQL view exposing it.
Root cause needs investigation (Martin config or alternative tile server).
Removed temporary debug endpoints:
- /api/eterra/debug-tile-props
- /api/eterra/debug-tile-sample
Kept /api/eterra/debug-fields (useful long-term diagnostic).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Temporary diagnostic to verify what columns gis_cladiri view exposes
for Martin vector tiles. Needed to debug missing C1/C2 labels.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shows all available eTerra fields for a parcel + buildings:
- GIS layer attributes (raw from ArcGIS)
- Immovable parcel details (intravilan, categories)
- Immovable list entry (address, areas)
- Documentation data (owners, registrations)
- Local DB state (enrichment, sync dates)
Usage: /api/eterra/debug-fields?siruta=161829&cadRef=77102
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Same search pattern as parcel-sync module: type name or SIRUTA code,
pick from dropdown, city is added instantly. Already-queued cities
are filtered out from results.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The /wds page was showing 0 cities because the KeyValueStore was empty
until the scheduler ran for the first time. Now the GET endpoint
initializes the queue with the 9 default cities on first access.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All sync paths now include both admin layers (LIMITE_INTRAV_DYNAMIC +
LIMITE_UAT) as best-effort alongside terenuri + cladiri:
- export-bundle (hero buttons)
- sync-background (fire-and-forget)
- auto-refresh scheduler (weekday nights)
- weekend deep sync (weekend nights)
- freshness check (export tab badge)
LIMITE_UAT rarely changes so incremental sync will skip it almost
every time, but it stays fresh in the DB freshness check.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sync Incremental:
- Add fetchObjectIds (returnIdsOnly) to eterra-client — fetches only OBJECTIDs in 1 request
- Add fetchFeaturesByObjectIds — downloads only delta features by OBJECTID IN (...)
- Rewrite syncLayer: compare remote IDs vs local, download only new features
- Fallback to full sync for first sync, forceFullSync, or delta > 50%
- Reduces sync time from ~10 min to ~5-10s for typical updates
Smart Export Tab:
- Hero buttons detect DB freshness — use export-local (instant) when data is fresh
- Dynamic subtitles: "Din DB (sync acum Xh)" / "Sync incremental" / "Sync complet"
- Re-sync link when data is fresh but user wants forced refresh
- Removed duplicate "Descarca din DB" buttons from background section
Auto-Refresh Scheduler:
- Self-contained timer via instrumentation.ts (Next.js startup hook)
- Weekday 1-5 AM: incremental refresh for existing UATs in DB
- Staggered processing with random delays between UATs
- Health check before processing, respects eTerra maintenance
Weekend Deep Sync:
- Full Magic processing for 9 large municipalities (Cluj, Bistrita, TgMures, etc.)
- Runs Fri/Sat/Sun 23:00-04:00, round-robin intercalated between cities
- 4 steps per city: sync terenuri, sync cladiri, import no-geom, enrichment
- State persisted in KeyValueStore — survives restarts, continues across nights
- Email status report at end of each session via Brevo SMTP
- Admin page at /wds: add/remove cities, view progress, reset
- Hint link on export tab pointing to /wds
API endpoints:
- POST /api/eterra/auto-refresh — N8N-compatible cron endpoint (Bearer token auth)
- GET/POST /api/eterra/weekend-sync — queue management for /wds page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Personal prompt library at /prompts with:
- 6 categories: Module Work, API & Backend, Quality & Security,
Session & Continue, Documentation & Meta, Quick Actions
- 22 optimized prompt templates for ArchiTools development
- Copy-to-clipboard on every prompt
- One-time prompts with checkbox persistence (localStorage)
- Search/filter across all prompts
- Best practices sidebar (10 tips from Claude Code research)
- Module name quick-copy badges
- Variable placeholders highlighted ({MODULE_NAME}, etc.)
- Deploy prep checklist, debug unknown errors, and more
Not registered as a module — accessible only via direct URL.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Export fix:
- Replaced DropdownMenu with direct DXF/GPKG buttons in SelectionToolbar.
Radix dropdown portals don't work inside fixed z-[110] containers.
Direct buttons work reliably on all platforms.
Mobile RGI cards:
- Single-row compact layout: icon + nr cerere + solicitant + termen + status
- Smaller icons (3.5), tighter spacing, shorter status labels
- No Card wrapper — lightweight border div for less visual weight
Mobile filters:
- Tighter spacing, smaller labels
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Selection toolbar:
- Moved OUTSIDE map container div to a fixed viewport position
(bottom-4, z-[110]). iOS Safari clips absolute elements inside
calc(100vh) containers — fixed positioning solves this.
- Only shown when UAT selected and has data.
Mobile top layout:
- UAT card takes full width (right-2 not right-[140px])
- Basemap switcher at top-[52px] left-2 on mobile (below UAT card)
- Desktop: unchanged (top-right offset from zoom controls)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ZIP download:
- Both portal and RGI test page now create a single ZIP archive
(Documente_eliberate_{appNo}.zip) instead of sequential downloads
- Uses JSZip (already in project dependencies)
Portal mobile:
- Basemap switcher drops below UAT card on mobile (top-14 sm:top-2)
- Selection toolbar at bottom-3 with z-30 (always visible)
- Click on feature centers map on that parcel (flyTo)
Tooltips:
- Green download icon: "Descarca arhiva ZIP cu documentele cererii X"
- Updated on both portal and RGI test page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Freehand drawing fix:
- Disable dragPan when in freehand mode (was only disabling dblclick
zoom). Without this, clicks were interpreted as pan gestures.
- Re-enable dragPan when exiting freehand mode.
Click highlight:
- Clicking a parcel in "off" mode now highlights it with the selection
layer (amber fill + orange outline). Clicking empty space clears it.
- Provides visual feedback for which parcel was clicked.
Mobile toolbar:
- Moved selection toolbar higher (bottom-12 on mobile) with z-20
to ensure it's above MapLibre attribution bar.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SelectionToolbar: new hideEnrichment prop hides the Enrichment button.
Portal uses it to show only Export + Clear in selection toolbar.
Portal feature panel: added disabled "Solicita extras CF" button with
tooltip "Sectiune platita — contacteaza administratorul".
Initial map zoom: starts at zoom 15 (close-up) instead of 7 (Romania
overview). Prevents the UAT boundaries flash before fitBounds runs.
Applied to both ParcelSync Harta tab and Portal.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
RGI (both pages):
- Default sort: Termen descrescator (cel mai in viitor sus)
Portal map:
- Basemap switcher moved left (right-12) to avoid zoom controls overlap
- Selection toolbar moved up (bottom-8) to avoid attribution overlap
- Download button has title tooltip on mobile cards
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixed:
- Added setLayoutProperty to MapLike type (was missing, broke build)
- Replaced FeatureInfoPanel with simple inline panel showing only:
SIRUTA, Nr. cadastral, Suprafata (no enrichment, no CF extract,
no "Actualizeaza" button)
- Fixed unknown type errors in JSX property access
- Hidden basemap boundaries + UAT layers for cleaner map
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The fitBounds effect was re-triggered every time mapReady toggled
(which happened frequently due to the source-checking polling interval).
Now uses boundsFittedForSirutaRef to ensure fitBounds runs only ONCE
per siruta selection — changing UAT still zooms correctly, but manual
zoom/pan is preserved afterwards.
Fixed in both ParcelSync Harta tab and Portal map.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Portal layout: removed conflicting (portal)/layout.tsx that had
duplicate html/body tags. Portal page now uses fixed overlay
(z-[100]) that covers the entire screen including sidebar.
Middleware: portal-only users (dan.tiurbe) are automatically
redirected from any non-portal route to /portal. They can still
access /api/ and /auth/ routes normally.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Default columns: Nr. cerere, Solicitant, Termen, Status, Rezolutie, UAT
(matching user's preferred view). Obiect, Identificatori, Deponent,
Data depunere now off by default.
Date sort: dueDate and appDate columns now sort by raw timestamp
(not by DD.MM.YYYY string which sorted incorrectly).
Filenames: removed long documentPk from filename. Now uses
DocType_AppNo.pdf (e.g. Receptie_tehnica_66903.pdf). Duplicate
types get suffix: Receptie_tehnica_66903_2.pdf.
Green icon: click downloads ALL documents from that application
sequentially. Shows spinner while downloading. Tooltip shows
"Nr. 66903 — click descarca toate" + details.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Page improvements:
- County dropdown with all 41 Romanian counties (default Cluj)
- orgUnitId auto-computed (countyId * 1000 + 2)
- Sortable columns: click header to sort asc/desc with arrow indicators
- Search input: filters across all visible columns (diacritics-insensitive)
- Soft blocked message: amber toast "Documentul nu este inca disponibil"
auto-hides after 5s (no more redirect errors)
Download improvements:
- Meaningful filenames: {docType}_{appNo}.pdf (e.g. Harti_planuri_66903.pdf)
- Romanian diacritics stripped from filenames
- Returns { blocked: true } JSON instead of redirect when unavailable
Bug fix: replaced incorrect useState() side-effect with proper useEffect()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The dueDate-based lock was incorrect: some documents with future
dueDate ARE downloadable. The availability depends on eTerra internal
rules, not predictably on dueDate.
Now all documents show a download button. If server-side download
fails (fileVisibility 404), it redirects to eTerra direct URL
which works in the user's browser session.
Filters changed to: Solutionate / Confirmate / Toate
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
eTerra blocks document downloads until dueDate passes (new rule).
Now the page shows:
Filter modes:
- "Descarcabile acum" (default) — solved + dueDate passed
- "In asteptare" — solved + dueDate future (documents locked)
- "Toate" — no filter
UI indicators:
- Green download icon: ready to download
- Amber clock icon: solved but locked until dueDate
- Documents panel shows "Disponibile de la DD.MM.YYYY" badge when locked
- Download button replaced with date badge for locked documents
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Before downloading, now calls:
1. verifyCurrentActorAuthenticated — sets actor context in session
2. appdetail/details — loads application context
Then tries download regardless of fileVisibility result.
The session context might be what enables downloads that previously
returned 404.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When fileVisibility returns OK → download server-side (fast).
When not available → HTTP 302 redirect to eTerra direct URL.
User's browser session handles authentication automatically.
This means: if logged into eTerra in browser, ALL documents download.
If not logged in, eTerra shows its own login page.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Download route simplified:
1. fileVisibility check — if 404, returns "indisponibil" + eTerra URL
2. Single download pattern (the one that works)
When document not available server-side, response includes direct
eTerra URL as fallback. No more 7 pattern attempts = much faster.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Server credentials can list RGI applications and docs but can't download
files (confirmOnView returns false — only the current actor/deponent
has download permission).
Download now opens the eTerra URL directly in the user's browser,
which uses their existing eTerra session cookie. Flow:
1. Hidden iframe calls confirmOnView
2. After 500ms, opens downloadFile URL in new tab
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Download route now:
- Calls fileVisibility with documentTypeId (if provided)
- Calls confirmOnView with documentPk
- Tries 3 different download URL patterns until one works
- Add &debug=1 to see diagnostic results instead of downloading
- Page now passes documentTypeId in download link
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaced single colSpan td with flex layout → proper td per column.
Headers and data cells now align correctly. Expanded docs row uses
colSpan only for the detail panel.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrote RGI test page:
- Clean card-based UI with status icons (green=solved, amber=pending)
- Click row to expand and see issued documents
- Each document has a direct "Descarca" download button
- Filter toggle "Doar solutionate cu termen viitor"
- No more raw JSON tables
Download route now follows eTerra's 3-step flow:
1. fileVisibility — check access, get fileId
2. confirmOnView — confirm document view
3. loadDocument/downloadFile — actual file download
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New eTerra RGI (Registrul General de Intrare) integration:
API routes (/api/eterra/rgi/):
- POST /applications — list applications with workspace/year filters
- GET /details?applicationId=X — application details
- GET /issued-docs?applicationId=X&workspaceId=Y — issued documents list
- GET /download-doc?wid=X&aid=Y&did=Z — download issued document
EterraClient: added rgiPost, rgiGet, rgiDownload methods for RGI API.
Test page (/rgi-test):
- Filters: workspace, orgUnit, year
- Toggle: "Doar solutionate cu termen viitor"
- Table with application list, expandable issued docs, download links
- Raw JSON debug sections (collapsible)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Map tab: when UAT has no local data, shows a "Sincronizează terenuri,
clădiri și intravilan" button that triggers background base sync.
Sync background (base mode): now also syncs LIMITE_INTRAV_DYNAMIC layer
(intravilan boundaries) alongside TERENURI_ACTIVE + CLADIRI_ACTIVE.
Non-critical — if intravilan fails, the rest continues.
Also fixed remaining \u2192 unicode escapes in export/layers/epay tabs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PostgreSQL CREATE OR REPLACE VIEW fails when column structure changes.
Now drops views first, then recreates them.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
LEFT JOIN caused duplicate rows and column conflicts. Replaced with a
correlated subquery (LIMIT 1) to safely look up BUILD_LEGAL from the
parent parcel's enrichment.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Click fix:
- Keep l-terenuri-fill visible but transparent (opacity 0) so it still
catches click events for FeatureInfoPanel. Enrichment overlay renders
underneath.
Color changes:
- No enrichment: amber/yellow fill (was light green)
- With enrichment: green fill
- Buildings: red fill = no legal docs, blue = legal, gray = unknown
- Parcel outline: red = building no legal, blue = building legal
Boundary cross-check (/api/geoportal/boundary-check?siruta=X):
- Finds "foreign" parcels: registered in other UATs but geometrically
within this UAT boundary (orange dashed)
- Finds "edge" parcels: registered here but centroid outside boundary
(purple dashed)
- Alert banner shows count, legend updated with mismatch indicators
Martin config: added gis_cladiri_status source with build_legal property.
Enrichment views: gis_cladiri_status now JOINs parent parcel's BUILD_LEGAL.
Requires: docker restart martin + POST /api/geoportal/setup-enrichment-views
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Basemaps: added Google Satellite option
ANCPI ortofoto: fixed bbox conversion (all 4 corners, not just SW/NE)
Selection: ESC key and right-click exit selection mode, tooltips updated
UAT layers: removed fill (only lines + labels), less visual clutter
Proprietari vechi: greyed out (opacity-50) so current owners stand out
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instead of reimplementing eTerra search logic (which missed most fields),
now calls the existing /api/eterra/search endpoint that already works
perfectly in ParcelSync. Same data, same format: proprietari, CF, CFvechi,
topo, intravilan, categorie, adresa, solicitant.
Per-parcel, 2-5 seconds, persists in DB.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaces background UAT-wide enrichment with instant per-parcel search.
Uses eTerra searchImmovableByIdentifier (cadastral number lookup) which
returns in 1-3 seconds instead of minutes.
Extracts: NR_CF, proprietari (with shares), intravilan, categorie,
adresa, has_building, build_legal. Persists in DB immediately.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previous single-parcel enrichment wrote empty data (couldn't match in eTerra).
Now uses the original enrichFeatures() which properly fetches owners, CF, etc.
Changes:
- Enrichment runs in BACKGROUND (returns immediately with message)
- Clears bad enrichment data before re-running
- Tracks running enrichments to avoid duplicates
- GET /api/geoportal/enrich?siruta=... checks if enrichment is running
- Panel: hasRealEnrichment checks for CF/PROPRIETARI/CATEGORIE (not just NR_CAD)
- Enrichment button stays visible until real data exists
- Message: "Enrichment pornit in background. Datele vor aparea in 1-3 minute."
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>