The analysis-and-research.md content has markdown tables (ציר דיוני)
and inline formatting like **label:** strong runs, which were
rendering as raw pipes and dashes because the compose page used
whitespace-pre-line on plain text.
Add a reusable <Markdown> component backed by react-markdown +
remark-gfm with a custom `components` map that styles paragraphs,
lists, blockquotes, strong runs, and especially GFM tables for RTL
+ aligned columns:
- table: table-auto + border-collapse, wrapped in overflow-x-auto
so very wide tables don't push the parent card out
- th: whitespace-nowrap so the header row sets column widths and
every row border lines up row-to-row
- everything text-right + the whole block gets dir="rtl" at the root
Use it in three places on the compose screen:
- ProseSection (represented_party, procedural_background,
agreed_facts, disputed_facts)
- Conclusions card
- SubsectionCard field content — threshold_claims and issues have
the same markdown shape in their fields[]
react-markdown + remark-gfm added (~30KB gzipped).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Drop the max-w-4xl wrapper so the compose cards fill the available
width of the AppShell main (which is already capped at 1400px
upstream). Threshold claim / issue cards with long Hebrew prose
now get the room they need without horizontal dead space.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The right sidebar with "רקע לניתוח" and "מסקנות" was stealing
horizontal space and forced the editable cards (threshold claims,
issues, chair positions, now precedents) into a narrow column. Move
both cards into the main stack, after the issues list, so the chair
sees the decision points first and the surrounding context after.
Collapse the lg:grid-cols-[1fr_320px] layout into a single max-w-4xl
stack since there's no longer a sidebar. Bump the moved cards from
px-5 py-4 to px-6 py-5 to match the rest of the compose page's
card padding.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Drop the defaultOpen={i===0} on the first threshold_claim — when a
case has a lot of material already on screen (research background
+ chair positions + now precedents), auto-opening the first card
creates a wall of text on page load. All cards now start collapsed,
same as the issues list already did.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Surface the new POST/GET/DELETE /api/cases/{n}/precedents endpoints
in the compose screen as two insertion points:
1. A new case-level card "פסיקה כללית לדיון" at the top of the
main column, for precedents that support the discussion intro
rather than a specific threshold_claim / issue.
2. An inline "פסיקה תומכת" section inside each SubsectionCard,
below the ChairEditor.
Both insertion points render a `<PrecedentsSection>` which shows a
list of `<PrecedentCard>` (citation + blockquote + optional chair
note + 📄 chip if a PDF was archived) followed by a `<PrecedentAttacher>`
popover trigger.
The Attacher is a Popover with cross-case typeahead: typing 2+
characters into the citation field hits /api/precedents/search and
shows distinct library matches; picking one prefills quote + chair
note but leaves them editable so customizing the quote for this
case doesn't mutate the library. An optional PDF/DOCX/DOC file can
be attached — it uploads first via POST .../upload-pdf and the
returned document_id is passed into the precedent create call.
The parent compose page issues a single useCasePrecedents query
and partitions the result by section_id into a Map so each
SubsectionCard renders its own slice without re-fetching.
shadcn Popover installed as a new primitive. sonner toasts wired
for success/error in both attach and delete flows.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three user-reported bugs on /cases/[caseNumber]:
1. Documents tab showed "9 מסמכים" in the count but rendered nothing —
DocumentsPanel was reading filename/category/status/size_bytes/uploaded_at,
but the real FastAPI payload (case_get → db.list_documents) returns
title/doc_type/extraction_status/page_count/created_at. Rewrote the
panel against the actual document row shape, added a CaseDocument
type alias in lib/api/cases.ts, mapped doc_type to Hebrew labels
(כתב ערר / כתב תשובה / ...) and extraction_status likewise.
2. The "פעולות" tab showed a debug-flavoured paragraph "עריכת פרטי התיק
נשמרת מיד דרך PUT /api/cases/1033-25" — that was internal wording,
not user copy. Removed.
3. Overview tab showed the raw enum value "full_acceptance" in the
expected-outcome line. Mapped through the existing expectedOutcomes
label array so it now reads "קבלה מלאה".
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New UploadSheet on the case detail page wraps react-dropzone + a
selector for doc_type. Files post to
POST /api/cases/{n}/documents/upload-tagged as multipart form-data;
the returned task_id is streamed via GET /api/progress/{task_id}
through the new lib/sse.ts EventSource wrapper.
Each upload row shows a per-file progress bar that transitions to
success/error on the terminal SSE payload. Closing the stream inside
the message handler avoids EventSource's auto-reconnect after EOF.
Phase 4 (task 86) is now complete end-to-end: create, upload, edit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add dialog/select/textarea/label/progress/sonner components and wire
a Toaster into Providers. New zod schemas in lib/schemas/case.ts
mirror CaseCreateRequest/CaseUpdateRequest and feed react-hook-form
validation.
CaseEditDialog on the case detail Actions tab posts PUT /api/cases/{n}
with optimistic cache patching via useUpdateCase, showing toast
feedback on success/error.
shadcn's <Form> registry entry skipped at init (missing from the
nova preset); the dialog uses RHF directly against the same Input/
Textarea/Select primitives.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New /cases/[caseNumber]/compose route ports the research analysis +
chair-position editing flow from the vanilla UI onto the Next.js
stack. Reads /api/cases/{n}/research/analysis, renders background
prose in the side column and threshold claims + issues as collapsible
cards in the main column, each with a blur-autosaved chair editor
wired through a TanStack Query mutation with optimistic cache patching
(so concurrent reads don't steal editor focus).
Handles the common "analysis not yet generated" 404 with a dedicated
empty state rather than an error card.
Phase 3 task 85 is now ready for review end-to-end.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New dynamic route /cases/[caseNumber] wired to the FastAPI details
endpoint, using Next 16's async params pattern with React's use()
hook. TanStack Query handles 5s refetchInterval so the page
self-updates during long-running processing without manual polling.
New components: CaseHeader (breadcrumb + meta), WorkflowTimeline
(5-phase RTL pipeline view), DocumentsPanel (categorized list).
Tabs split overview/documents/actions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>