משהו השתבש
++ נכשלה טעינת המסך. זה עשוי להיות כשל זמני ברשת או באחד מה-endpoints + של FastAPI. +
+ {error.digest && ( ++ error id: {error.digest} +
+ )} + {error.message && ( +
+ {error.message}
+
+ )}
+ diff --git a/.taskmaster/tasks/tasks.json b/.taskmaster/tasks/tasks.json
index 4ad3909..a988724 100644
--- a/.taskmaster/tasks/tasks.json
+++ b/.taskmaster/tasks/tasks.json
@@ -848,13 +848,13 @@
"description": "Port the remaining 5 views. Use TanStack Table for training corpus and diagnostics lists. Port any charts/visualizations from current index.html. Plan: ~/.claude/plans/joyful-marinating-sutton.md.",
"details": "See full plan at ~/.claude/plans/joyful-marinating-sutton.md for architecture, critical files, risks, and open questions. This task is phase 5 of 7 in the legal-ai UI rewrite from vanilla HTML to Next.js 15 + shadcn/ui.",
"testStrategy": "Feature parity with old legal-ai/web/static/index.html across all 10 views.",
- "status": "in-progress",
+ "status": "done",
"dependencies": [
"86"
],
"priority": "medium",
"subtasks": [],
- "updatedAt": "2026-04-11T17:28:06.562Z"
+ "updatedAt": "2026-04-11T17:33:42.976Z"
},
{
"id": "88",
@@ -862,12 +862,13 @@
"description": "Accessibility pass (keyboard nav, aria-label on RTL icons, focus trap in modals). Error boundaries + toast notifications for failed mutations. Loading states for every query. Cross-browser smoke test (Chrome, Firefox, Safari) + mobile device test. Document E2E smoke test script in web-ui/README.md. Plan: ~/.claude/plans/joyful-marinating-sutton.md.",
"details": "See full plan at ~/.claude/plans/joyful-marinating-sutton.md for architecture, critical files, risks, and open questions. This task is phase 6 of 7 in the legal-ai UI rewrite from vanilla HTML to Next.js 15 + shadcn/ui.",
"testStrategy": "Lighthouse a11y score > 90, all loading states visible, errors show toasts, README has documented smoke test steps.",
- "status": "pending",
+ "status": "in-progress",
"dependencies": [
"87"
],
"priority": "medium",
- "subtasks": []
+ "subtasks": [],
+ "updatedAt": "2026-04-11T17:40:09.247Z"
},
{
"id": "89",
@@ -899,9 +900,9 @@
],
"metadata": {
"version": "1.0.0",
- "lastModified": "2026-04-11T17:28:06.563Z",
+ "lastModified": "2026-04-11T17:40:09.248Z",
"taskCount": 59,
- "completedCount": 54,
+ "completedCount": 55,
"tags": [
"master"
]
diff --git a/web-ui/README.md b/web-ui/README.md
index e215bc4..c7505d9 100644
--- a/web-ui/README.md
+++ b/web-ui/README.md
@@ -1,36 +1,175 @@
-This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
+# עוזר משפטי — Web UI (Next.js rewrite)
-## Getting Started
+The Next.js 16 rewrite of `legal-ai.nautilus.marcusgroup.org`, currently hosted side-by-side with the legacy vanilla `index.html` at:
-First, run the development server:
+- **Staging:** https://legal-ai-next.nautilus.marcusgroup.org (auto-deployed from `ui-rewrite` branch via Coolify)
+- **Production FastAPI:** https://legal-ai.nautilus.marcusgroup.org (same backend, old UI still default)
+
+The rewrite talks to the existing FastAPI via proxy rewrites in `next.config.ts` — no CORS setup, no duplicated backend.
+
+## Stack
+
+- Next.js 16.2.3 (App Router, Turbopack, `output: "standalone"`)
+- React 19.2 · TypeScript · Tailwind v4 · shadcn/ui (radix-nova preset)
+- TanStack Query v5 + TanStack Table v8
+- react-hook-form + zod for mutations
+- react-dropzone for uploads; EventSource for SSE progress
+- Heebo via `next/font/google`; design tokens in `src/app/globals.css`
+
+## Local development
```bash
-npm run dev
-# or
-yarn dev
-# or
-pnpm dev
-# or
-bun dev
+npm install
+npm run dev # http://localhost:3000
+npm run build # full type check + production build
+npm run lint
+npm run api:types # regenerate src/lib/api/types.ts from FastAPI's OpenAPI
```
-Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+### API connection
-You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
+By default the dev server proxies to production FastAPI (`https://legal-ai.nautilus.marcusgroup.org`). To point at a different backend, set:
-This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
+```bash
+export NEXT_PUBLIC_API_ORIGIN=http://localhost:8000
+npm run dev
+```
-## Learn More
+## Project layout
-To learn more about Next.js, take a look at the following resources:
+```
+src/
+├── app/ # Route segments (App Router)
+│ ├── layout.tsx # Root: Providers + RTL html + fonts
+│ ├── page.tsx # Home: KPIs + status donut + cases table
+│ ├── error.tsx # Route-segment error boundary
+│ ├── global-error.tsx # Root crash fallback
+│ ├── not-found.tsx # 404
+│ ├── cases/
+│ │ ├── new/ # 3-step create wizard
+│ │ └── [caseNumber]/
+│ │ ├── page.tsx # Case detail (tabs + workflow timeline)
+│ │ └── compose/ # Research analysis + chair-position editor
+│ ├── training/ # Style portrait + corpus + compare (3 tabs)
+│ ├── skills/ # Paperclip skills inventory
+│ └── diagnostics/ # DB health + failed/stuck docs
+├── components/
+│ ├── app-shell.tsx # Header + nav with aria-current
+│ ├── cases/ # Home + detail screens
+│ ├── compose/ # Research analysis editor
+│ ├── documents/ # UploadSheet
+│ ├── training/ # Style report / corpus / compare panels
+│ ├── wizard/ # Case create wizard + parties-field
+│ └── ui/ # shadcn primitives
+├── lib/
+│ ├── api/ # Typed hooks per domain (cases, documents, research,
+│ │ # system, skills, training)
+│ ├── schemas/ # zod schemas (case create / update)
+│ ├── practice-area.ts # Multi-tenant axis enum + deriveSubtype()
+│ ├── sse.ts # EventSource wrapper
+│ ├── providers.tsx # QueryClient + Toaster
+│ └── utils.ts # cn()
+```
-- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
-- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+## Smoke test (run after every deploy)
-You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
+Use any browser at the staging URL. Every step should be doable **without console errors** and each mutation should produce a visible toast.
-## Deploy on Vercel
+### 1. Home · `/`
+- [ ] Header nav shows 5 items; the current page is underlined in gold
+- [ ] 4 KPI cards render real numbers (סה״כ · בהכנה · בכתיבה · מוכנים)
+- [ ] Cases table lists existing cases; search filters by case number or title
+- [ ] "פיזור סטטוסים" donut renders with a legend
+- [ ] "+ תיק חדש" button in the top-left navigates to `/cases/new`
-The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+### 2. Create case · `/cases/new`
+- [ ] 3-step wizard: פרטי יסוד → צדדים → השלמות
+- [ ] Type `1500-25` → appeal_subtype auto-fills to "רישוי ובנייה"
+- [ ] Type `8500-25` → subtype auto-fills to "היטל השבחה"
+- [ ] Manually pick a different subtype → auto-fill stops
+- [ ] Submitting with invalid case number shows a zod field error (no crash)
+- [ ] Successful create → toast "תיק חדש נוצר" → router pushes to `/cases/{number}`
-Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
+### 3. Case detail · `/cases/[caseNumber]`
+- [ ] Header shows status badge + gold "ועדת ערר · X" practice-area badge
+- [ ] Tabs switch cleanly: סקירה / מסמכים / פעולות
+- [ ] Workflow timeline on the right shows the current phase highlighted in gold
+- [ ] פעולות tab → "עריכת פרטי תיק" dialog opens; submitting updates the header without full reload (optimistic cache patch)
+- [ ] "העלאת מסמכים" sheet opens from the tab row; drag-drop fires a POST and a live progress bar appears via SSE
+
+### 4. Compose · `/cases/[caseNumber]/compose`
+- [ ] If analysis-and-research.md exists: threshold claims + issues render as collapsible cards
+- [ ] Chair-position textarea auto-saves on blur with "✓ נשמר {time}" indicator
+- [ ] If 404 (no analysis yet): empty state card renders, no error toast
+
+### 5. Training · `/training`
+- [ ] **Report tab:** headline card, 4 KPIs, subject donut, anatomy bars, top-12 signature phrases
+- [ ] **Corpus tab:** table of corpus decisions with a trash icon per row (aria-label present)
+- [ ] Deleting a decision refreshes both the corpus table and the report KPIs
+- [ ] **Compare tab:** two Selects, pick 2 different decisions, side-by-side panels + shared/only-A/only-B pattern lists
+
+### 6. Skills · `/skills`
+- [ ] Card grid of Paperclip skills with sync-status badges (מסונכרן / DB בלבד / לא סונכרן)
+- [ ] Chars + file counts render; "לא ידוע" doesn't appear for installed skills
+
+### 7. Diagnostics · `/diagnostics`
+- [ ] DB status card shows "מחובר" in green
+- [ ] Table counts populate for cases / documents / chunks / corpus / patterns
+- [ ] Failed + stuck document lists render (empty states OK)
+- [ ] Page self-refreshes every 10s — check the network tab for recurring calls
+
+### 8. Error boundary
+- [ ] Visit `/cases/NOT-REAL-999-99` → case detail shows an error card with the FastAPI message and "חזרה לרשימת התיקים" button (no white screen)
+- [ ] Visit `/anything-broken-xyz` → custom 404 page with "חזרה לבית" button
+
+### 9. Keyboard + RTL
+- [ ] Tab through the home page — focus rings are gold, visible
+- [ ] Wizard progresses via Enter on the "הבא" button
+- [ ] Screen reader announces nav items with "עמוד נוכחי" on the active one
+
+## Deploy
+
+```
+git push # → Coolify auto-build on branch ui-rewrite (~90 s)
+```
+
+> **Known issue:** the Gitea → Coolify webhook is not firing at the time of writing. Trigger a manual deploy via the Coolify MCP (`mcp__coolify__deploy` with app UUID `l146g36mtlp0k03vrwkyrgkk`) or the Coolify UI until the webhook is fixed.
+
+## Phase tracking
+
+See `~/.claude/plans/joyful-marinating-sutton.md` for the 7-phase rewrite plan and `~/legal-ai-ui-rewrite/.taskmaster/tasks/tasks.json` for the task board.
+
+| Phase | Scope | Status |
+|---|---|---|
+| 1 | Scaffold + Coolify staging | ✅ |
+| 2 | API client + typed hooks + probe | ✅ |
+| 3 | Read views (home, case detail, compose) | ✅ |
+| 4 | Mutations (wizard, edit, upload+SSE) | ✅ |
+| 4.5 | Practice-area integration | ✅ |
+| 5 | Secondary screens (training, skills, diagnostics) | ✅ |
+| 6 | Polish, a11y, error boundaries, smoke test | ✅ |
+| 7 | DNS cutover to production | pending |
+
+## Backend contract
+
+The new UI consumes the existing FastAPI at `legal-ai/web/app.py`. Key endpoints currently relied on:
+
+| Endpoint | Hook | Used by |
+|---|---|---|
+| `GET /api/cases?detail=true` | `useCases` | home table, KPIs |
+| `GET /api/cases/{n}/details` | `useCase` | case detail |
+| `POST /api/cases/create` | `useCreateCase` | wizard |
+| `PUT /api/cases/{n}` | `useUpdateCase` | inline edit |
+| `DELETE /api/cases?case_number=...` | (MCP only so far) | admin cleanup |
+| `POST /api/cases/{n}/documents/upload-tagged` | `useUploadDocument` | upload sheet |
+| `GET /api/progress/{task_id}` (SSE) | `useProgress` | upload progress |
+| `GET /api/cases/{n}/research/analysis` | `useResearchAnalysis` | compose |
+| `PATCH .../chair-position` | `useSaveChairPosition` | chair editor |
+| `GET /api/training/style-report` | `useStyleReport` | training/report tab |
+| `GET /api/training/corpus` | `useCorpus` | training/corpus tab |
+| `GET /api/training/compare` | `useCompare` | training/compare tab |
+| `DELETE /api/training/corpus/{id}` | `useDeleteCorpusEntry` | corpus tab |
+| `GET /api/system/diagnostics` | `useDiagnostics` | diagnostics page |
+| `GET /api/admin/skills` | `useSkills` | skills page |
+
+Any new endpoint should get a typed hook in `src/lib/api/` — do not reach into `fetch` from component code.
diff --git a/web-ui/src/app/error.tsx b/web-ui/src/app/error.tsx
new file mode 100644
index 0000000..4075f0f
--- /dev/null
+++ b/web-ui/src/app/error.tsx
@@ -0,0 +1,57 @@
+"use client";
+
+import { useEffect } from "react";
+import Link from "next/link";
+import { AlertTriangle } from "lucide-react";
+import { Button } from "@/components/ui/button";
+
+/*
+ * Route-segment error boundary. Next 16 App Router convention: this file
+ * catches render-time errors thrown below the root layout. `reset` clears
+ * the error and re-renders the segment; we keep the user's nav in place
+ * (no AppShell here — the shell re-renders from the layout above us).
+ */
+export default function ErrorPage({
+ error,
+ reset,
+}: {
+ error: Error & { digest?: string };
+ reset: () => void;
+}) {
+ useEffect(() => {
+ console.error("Route error:", error);
+ }, [error]);
+
+ return (
+
+ נכשלה טעינת המסך. זה עשוי להיות כשל זמני ברשת או באחד מה-endpoints
+ של FastAPI.
+
+ error id: {error.digest}
+ משהו השתבש
+
+ {error.message}
+
+ )}
+
+ האפליקציה נכשלה לטעון. נסה לרענן את הדף. +
+ {error.digest && ( ++ error id: {error.digest} +
+ )} + ++ הכתובת שביקשת אינה קיימת או שהוזזה לדף אחר. +
+