- Wrap date.fromisoformat() in try/except in case_update tool — prevents
unhandled ValueError from surfacing as 500; FastAPI now catches it as 422
- Add DialogDescription (sr-only) to 5 dialogs missing aria-describedby:
documents-panel preview + delete, drafts-panel delete + feedback, link-related-dialog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The list's scroll container had only overflow-y:auto, which CSS computes
overflow-x to auto too. Combined with the row's -mx-2 hover-background
extension, this surfaced an unwanted horizontal scrollbar.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Until now changing a document's doc_type required a manual SQL update.
Adds an inline editor on the document badge so the chair can retag
without leaving the case page, and threads an appraiser_side tag
(committee / appellant / deciding) through the appraisal pipeline so
betterment-levy cases — which usually have 2-3 appraisers — render
conflicts with the deciding appraiser's view marked as governing.
Backend
- New appraiser_facts.appraiser_side column (V5.1) populated from
documents.metadata.appraiser_side at extraction time.
- extract_appraiser_facts now returns status='sides_missing' with the
list of untagged appraisals instead of running with empty side
labels — chair must tag every appraisal first via the UI.
- Conflict detection orders entries committee → appellant → deciding so
the deciding appraiser appears last; block-tet's prompt instructs the
writer to phrase the deciding appraiser's view as the governing
factual finding ("ואולם, השמאי המכריע קבע...").
- New PATCH /api/cases/{n}/documents/{doc_id} (Pydantic model with
whitelist validation) and matching document_update MCP tool. Both
merge appraiser_side into metadata JSONB instead of touching the
schema.
UI
- New shared doc-types module exports the canonical 11 doc_type
options plus the 3 appraiser-side options; both upload-sheet and
the document badge now read from it instead of duplicating Hebrew
labels.
- New DocumentTypeEditor renders a Popover off the doc-type Badge
with two Selects. The save button stays disabled while doc_type is
appraisal but no side has been picked, mirroring the backend
enforcement so the user finds out before triggering extraction.
- usePatchDocument React-Query mutation invalidates the case detail
on success so the badge updates without a manual refresh.
The backend (app.py, documents.py, models.py) already maps appraisal→שומה
but the frontend DOC_TYPE_LABELS and upload DOC_TYPES dropdowns were
missing the entry, so appraisal documents rendered as the raw English
string instead of the Hebrew label.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ScrollArea (Radix) injected display:table on viewport, preventing
scroll — replaced with plain div + overflow-y-auto. Preview dialog
never loaded text because onOpenChange doesn't fire on initial mount —
replaced with useEffect that fetches on open.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Documents tab was limited to ~9 visible items due to fixed max-height
without overflow-hidden. Now uses 70vh with proper overflow. Added
click-to-preview (shows extracted text in dialog) and delete button
with confirmation dialog + backend DELETE endpoint.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Force the title + meta column to the inline-start (visual right in
RTL) and the doc_type badge to the inline-end (visual left). The
previous layout used justify-between with an ambient dir="rtl"
inherited from <html>, but the Radix ScrollArea Viewport was eating
the direction context and flipping the row to LTR.
Fix: set dir="rtl" explicitly on both ScrollArea and the inner ul,
drop justify-between, and use ms-auto on the badge so it grows its
inline-start margin regardless of ambient direction. Title column
gets an explicit text-right for good measure.
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 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>