Files
legal-ai/web-ui/AGENTS.md
Chaim b0efa700da
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 7s
feat(ui): IA redesign → production · /home pending-approvals card + Claude Design gate (2/17)
- /home: כרטיס "מה ממתין להכרעתך" ב-aside (מצביע INV-IA1 ל-/approvals; usePendingApprovals,
  ללא מונה-מתחרה) — תואם מוקאפ 04-home המאושר.
- web-ui/AGENTS.md: §"שער-עיצוב חובה — Claude Design קודם" — כל יצירת/שינוי עמוד-UI
  עוברת קודם דרך פרויקט Claude Design "עוזר משפטי — IA Redesign (X17)"
  (7a85b323-d880-4b6d-bac5-d4aa396fe93c) לאישור, ורק אז מוטמע (הנחיית חיים).

בדיקה: npx tsc --noEmit ✓.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 22:10:56 +00:00

262 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
<!-- END:nextjs-agent-rules -->
---
## ⚠️ שער-עיצוב חובה — Claude Design קודם (הנחיית חיים, 2026-06-11)
**כל יצירת עמוד/דף חדש, וכל שינוי-UI בעמוד/דף קיים — מכל סיבה — חייב לעבור קודם דרך Claude Design לאישור, ורק לאחר אישור מטמיעים בקוד.** אין לשנות/ליצור עמוד-UI ישירות בלי מעבר דרך השער.
**הפרויקט הקנוני (כל הדפים נמצאים שם):**
- שם: **`עוזר משפטי — IA Redesign (X17)`** ב-[claude.ai/design](https://claude.ai/design).
- מזהה-פרויקט: `7a85b323-d880-4b6d-bac5-d4aa396fe93c`.
- גישה: כלי `DesignSync` (claude.ai/design). מכיל את כל 17 הדפים כ-preview-cards תחת קבוצה `IA Redesign (X17)`, בנויים מטוקני-העיצוב האמיתיים (`globals.css`: navy `#0f172a`, gold `#a97d3a`, cream `#f5f1e8`, parchment, rule…), Heebo, RTL.
**הפרוטוקול לכל בקשת-עמוד/שינוי-UI:**
1. **בקשת-עיצוב ל-Claude Design** — לבנות/לעדכן את ה-preview של העמוד בפרויקט הזה (HTML self-contained, `<!-- @dsCard group="IA Redesign (X17)" -->` כשורה ראשונה, טוקנים+Heebo+RTL זהים), `write_files` + `register_assets` דרך `DesignSync`.
2. **להציג לחיים לאישור** — ולהמתין לאישור מפורש.
3. **רק אחרי אישור** — להטמיע בקוד (Next 16 + Tailwind v4 + shadcn), לשמר hooks/לוגיקה, tsc/lint, worktree + PR.
חריג יחיד: תיקון-באג שאינו משנה את ה-UI הוויזואלי (לוגיקה/נתון/hook בלבד) — לא דורש מעבר דרך השער. בכל ספק — דרך השער.
> רקע: יוזמת ה-IA (X17, #127/#130132) → מוקאפי-Claude-Design ל-17 הדפים (מאושרים) → תרגום לפרודקשן. ראה memory `feedback_claude_design_gate` ו-`project_ia_redesign_waves`.
---
## Stack
| Layer | Technology | Version |
|-------|-----------|---------|
| Framework | Next.js | 16.2.3 |
| UI | React | 19.2.4 |
| Styles | Tailwind CSS | v4 |
| Components | shadcn/ui | latest via `shadcn` CLI |
| Data fetching | TanStack Query | v5 |
| Forms | react-hook-form + zod | v7 / v4 |
| Language | TypeScript | 5 |
| Direction | Hebrew RTL | `dir="rtl"` throughout |
---
## Commands
```bash
# Regenerate API types from the live FastAPI schema — RUN AFTER EVERY BACKEND CHANGE
npm run api:types
# Validate before every push
npm run lint
npm run build
# Local dev (rare — prod runs inside Docker; no local Python env exists)
npm run dev # requires NEXT_PUBLIC_API_ORIGIN=http://127.0.0.1:8000 or similar
```
**`npm run api:types` is mandatory** any time a FastAPI endpoint is added, removed, or its request/response shape changes. It fetches `https://legal-ai.nautilus.marcusgroup.org/openapi.json` and writes `src/lib/api/types.ts`.
---
## Backend Proxy — `/api/*`
`next.config.ts` transparently rewrites all `/api/*` requests to the FastAPI backend:
- In Docker (production): `http://127.0.0.1:8000`
- Override via env var: `NEXT_PUBLIC_API_ORIGIN`
**Never hardcode the backend origin in component code.** Always use relative paths like `/api/cases`.
The typed fetch wrapper lives in `src/lib/api/client.ts` — use `apiRequest<T>(path, options)`. It throws `ApiError` on non-2xx responses with the parsed body and status code.
---
## API Types — Never Edit by Hand
`src/lib/api/types.ts` is **auto-generated** by `openapi-typescript` from the live FastAPI OpenAPI schema.
- **Do NOT edit `src/lib/api/types.ts` manually** — changes will be overwritten on the next `npm run api:types` run.
- The typed helper modules in `src/lib/api/` (e.g. `cases.ts`, `documents.ts`, `precedents.ts`) ARE hand-written and import from `types.ts`. These are safe to edit.
- When adding a new API domain, create a new typed module in `src/lib/api/<domain>.ts` following the existing pattern.
---
## Tailwind CSS v4 — Breaking Changes from v3
Tailwind v4 has a completely different configuration model.
**What does NOT exist in v4:**
- `tailwind.config.ts` / `tailwind.config.js` — there is no config file
- `@tailwind base;` / `@tailwind components;` / `@tailwind utilities;` directives
- `tailwind.config.theme.extend` object
**What v4 uses instead:**
```css
/* globals.css — already set up, do not change */
@import "tailwindcss";
@import "tw-animate-css";
@import "shadcn/tailwind.css";
@theme {
/* Design tokens defined here as CSS custom properties */
--color-navy: #0f172a;
/* ... */
}
```
- Custom tokens go inside `@theme {}` in `globals.css`.
- Custom variants use `@custom-variant`.
- Class names are the same (e.g. `bg-navy`, `text-gold`), but the config source is CSS, not JS.
- PostCSS is configured via `@tailwindcss/postcss` (devDependency).
---
## shadcn/ui Components
Adding a new component:
```bash
npx shadcn add <component-name>
# e.g. npx shadcn add table
```
Installed components live in `src/components/ui/`. They are editable (shadcn copies the source, not a package import). The `radix-ui` package (v1.4) is the underlying primitive.
- Do NOT `npm install @radix-ui/react-*` directly — use `npx shadcn add` which installs the correct Radix version and generates the shadcn wrapper.
- Design tokens in `globals.css` (`--color-navy`, `--color-gold`, etc.) are already mapped to the shadcn semantic tokens (`background`, `foreground`, `primary`, etc.), so shadcn components inherit the editorial/judicial aesthetic automatically.
---
## TanStack Query v5
**v5 has breaking API changes from v4.** Key patterns used in this codebase:
```typescript
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
// Reading data
const { data, isLoading, isError } = useQuery({
queryKey: ["cases"],
queryFn: () => apiRequest<CaseListResponse>("/api/cases"),
});
// Writing data
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: (body: CreateCaseRequest) =>
apiRequest<Case>("/api/cases", { method: "POST", body }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["cases"] });
},
});
```
**v5 changes from v4:**
- `useQuery` no longer accepts positional arguments — always use the options object.
- `isLoading` is replaced by `isPending` for mutations (but `isLoading` still works for queries).
- `onSuccess`/`onError`/`onSettled` callbacks on `useQuery` are removed — use mutation callbacks or `useEffect` instead.
- `getQueryData` / `setQueryData` are unchanged.
The shared `QueryClient` is created in `src/lib/api/client.ts` via `makeQueryClient()` and provided by `src/lib/providers.tsx`.
---
## RTL — Hebrew UI Rules
**All UI is Hebrew, right-to-left.** The `<html>` element has `dir="rtl"` and `lang="he"`.
Use **logical CSS properties** instead of directional ones:
| Avoid (directional) | Use (logical) |
|---------------------|--------------|
| `ml-*` / `mr-*` | `ms-*` (start) / `me-*` (end) |
| `pl-*` / `pr-*` | `ps-*` (start) / `pe-*` (end) |
| `text-left` | `text-start` |
| `text-right` | `text-end` |
| `float-left` | `float-start` |
| `border-l-*` | `border-s-*` |
In RTL, "start" = right side, "end" = left side. Using logical properties means the layout works automatically without RTL overrides.
Flexbox direction: `flex-row` in RTL naturally flows right-to-left. Use `flex-row-reverse` only when you need LTR inside an RTL context.
---
## Project Structure
```
src/
├── app/ # Next.js App Router pages
│ ├── layout.tsx # Root layout — sets dir="rtl", applies fonts
│ ├── globals.css # Tailwind v4 imports + design tokens + :root vars
│ ├── cases/ # Case management pages
│ ├── precedents/ # Precedent library pages
│ ├── methodology/ # Methodology browser
│ ├── training/ # Training document management
│ ├── settings/ # Application settings
│ └── skills/ # Skills management
├── components/
│ ├── ui/ # shadcn primitives (editable copies)
│ ├── app-shell.tsx # Top-level shell with nav
│ ├── cases/ # Case-domain components
│ ├── documents/ # Document viewer components
│ ├── precedents/ # Precedent components
│ └── compose/ # Decision drafting / block editor
├── lib/
│ ├── api/
│ │ ├── types.ts # AUTO-GENERATED — never edit
│ │ ├── client.ts # apiRequest<T> + QueryClient factory
│ │ ├── cases.ts # Typed case API helpers
│ │ ├── documents.ts # Typed document API helpers
│ │ └── ... # One file per API domain
│ ├── providers.tsx # TanStack Query + theme providers
│ ├── utils.ts # cn() and other shared utilities
│ ├── doc-types.ts # Document type constants
│ └── sse.ts # Server-Sent Events helper for streaming
```
---
## Forms
Forms use **react-hook-form** (v7) with **zod** (v4) validation via `@hookform/resolvers`:
```typescript
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
const schema = z.object({ title: z.string().min(1) });
type FormValues = z.infer<typeof schema>;
const form = useForm<FormValues>({ resolver: zodResolver(schema) });
```
---
## Notifications / Toasts
Use **sonner** (`import { toast } from "sonner"`). The `<Toaster>` is mounted in `src/lib/providers.tsx`.
```typescript
toast.success("התיק נשמר בהצלחה");
toast.error("שגיאה בשמירה");
```
---
## Streaming (SSE)
Server-sent events are used for long-running AI operations (drafting, analysis). The helper is in `src/lib/sse.ts`. Use it instead of raw `EventSource`.
---
## Deploy
This frontend runs **inside Docker via Coolify** — not as a standalone Node process.
- **No `npm run dev` on the server** — there is no local Python environment for the backend.
- To see changes in production: `git commit` + `git push origin main` → Gitea Actions builds image → Coolify redeploys (~2-4 min).
- Prod URL: `https://legal-ai.nautilus.marcusgroup.org`
- The Next.js output is `standalone` (see `next.config.ts: output: "standalone"`).