PUT /api/cases/{n}/research/analysis/upload accepts a markdown file and
validates: UTF-8 encoding, parseable structure, at least one threshold
or issue section, matching case number. Backs up existing file before
replacing. UI adds "העלה ניתוח מעודכן" button with status feedback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New GET /api/cases/{n}/research/analysis/download endpoint returns the
raw markdown file. UI adds a "הורד ניתוח" button next to "חזרה לתיק"
on the compose page, visible only when analysis data is loaded.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
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>