Commit Graph

2 Commits

Author SHA1 Message Date
chaim 2924f716d4 Fix: harden RTL — tables and tabs were rendering left-to-right
Five-layer defense so that no single library/browser quirk can flip the
layout back to LTR:

1. <body dir="rtl"> in addition to <html dir="rtl"> — some libs read
   document.body.dir, not document.documentElement.dir.
2. Explicit `direction: rtl` on html, body in the @layer base CSS.
3. <DirectionProvider dir="rtl"> from @radix-ui/react-direction wrapping
   the React tree, so every Radix primitive (Tabs, Dialog, Select,
   Popover, Toast) gets RTL context — Radix's useDirection defaults to
   "ltr" without it.
4. shadcn Tabs wrapper now defaults its dir prop to "rtl" — redundant
   with the provider above, but defends against a future provider
   removal silently breaking Tabs.
5. dir="rtl" set explicitly on each <table> element.

Fixes the symptom seen on the live site: deals/appraisals tables had
תאריך (the first <th> in the JSX) rendering on the LEFT instead of the
RIGHT, and Tabs flowed עסקאות→שמאי left-to-right instead of the
expected right-to-left.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 13:51:19 +00:00
chaim 5e9963f51b Add: Web UI (React 19 + Vite + shadcn/ui) + FastAPI REST layer
Adds a self-contained web interface that wraps the MCP tools so end users
don't need to issue MCP commands. Single Docker container serves:

  /              → React SPA (RTL Hebrew, Heebo font, shadcn/ui components)
  /api/*         → FastAPI REST endpoints used by the SPA
  /api/docs      → OpenAPI / Swagger
  /mcp           → existing FastMCP streamable-http endpoint
  /health        → liveness probe

REST endpoints (in nadlan_mcp/web_app.py):
  GET  /api/search/address?q=...  — autocomplete + best-effort gush/חלקה
                                    via Govmap PARCEL_ALL layer
  POST /api/search/deals          — Govmap deals around an address
  POST /api/search/appraisals     — Decisive-appraiser search (gov.il)
  GET  /api/appraisals/pdf?url=.. — Stream PDFs through this server,
                                    carrying the upstream x-client-id
                                    header (a normal browser fetch fails)

UI flow:
  - Address search → resolves gush/חלקה → shows BOTH deals (Govmap) AND
    appraiser decisions (gov.il) for the same parcel side-by-side in tabs.
  - Block+plot search → goes straight to appraisals.
  - Appraiser-name search → all decisions by that appraiser.

Stack chosen for RTL-first usability and longevity: React 19, Vite 6,
TypeScript, Tailwind, shadcn/ui (Radix primitives), TanStack Query,
Lucide icons. ~295KB gzipped JS, no SSR overhead.

Multi-stage Dockerfile: Node 22 builds web/ in stage 1, Python 3.13
runtime serves the dist + the FastAPI app in stage 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 12:35:08 +00:00