Edit document doc_type and appraiser side from the case UI
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m26s
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m26s
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.
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Progress } from "@/components/ui/progress";
|
||||
import {
|
||||
@@ -23,40 +22,19 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { apiRequest } from "@/lib/api/client";
|
||||
import { casesKeys } from "@/lib/api/cases";
|
||||
import type { CaseDetail, CaseDocument } from "@/lib/api/cases";
|
||||
import { DocumentTypeEditor } from "@/components/cases/document-type-editor";
|
||||
|
||||
/*
|
||||
* Document list for the case detail "מסמכים" tab. Uses the real document
|
||||
* row shape returned by the FastAPI case_get endpoint — see db.list_documents
|
||||
* and the `documents` schema in legal_mcp/services/db.py:
|
||||
* id · case_id · doc_type · title · file_path · extraction_status ·
|
||||
* page_count · created_at · practice_area · appeal_subtype
|
||||
* page_count · created_at · practice_area · appeal_subtype · metadata
|
||||
*
|
||||
* Doc-type labels and tone classes live in @/lib/doc-types so the upload
|
||||
* sheet, the inline editor, and this panel all stay in sync.
|
||||
*/
|
||||
|
||||
const DOC_TYPE_LABELS: Record<string, string> = {
|
||||
appeal: "כתב ערר",
|
||||
response: "כתב תשובה",
|
||||
protocol: "פרוטוקול",
|
||||
decision: "החלטת ועדה מקומית",
|
||||
plan: "תכנית",
|
||||
appraisal: "שומה",
|
||||
reference: "חומר רקע",
|
||||
auto: "—",
|
||||
};
|
||||
|
||||
function doctypeLabel(t: string): string {
|
||||
return DOC_TYPE_LABELS[t] ?? t;
|
||||
}
|
||||
|
||||
function doctypeTone(t: string): string {
|
||||
switch (t) {
|
||||
case "appeal": return "bg-info-bg text-info border-info/40";
|
||||
case "response": return "bg-gold-wash text-gold-deep border-gold/40";
|
||||
case "decision": return "bg-success-bg text-success border-success/40";
|
||||
case "protocol": return "bg-warn-bg text-warn border-warn/40";
|
||||
default: return "bg-rule-soft text-ink-muted border-rule";
|
||||
}
|
||||
}
|
||||
|
||||
const STATUS_LABELS: Record<string, string> = {
|
||||
pending: "בהמתנה",
|
||||
processing: "בעיבוד",
|
||||
@@ -272,12 +250,15 @@ function DocumentRow({
|
||||
</div>
|
||||
</button>
|
||||
{doc.doc_type && (
|
||||
<Badge
|
||||
variant="outline"
|
||||
className={`rounded-full px-2 py-0.5 text-[0.7rem] shrink-0 ${doctypeTone(doc.doc_type)}`}
|
||||
>
|
||||
{doctypeLabel(doc.doc_type)}
|
||||
</Badge>
|
||||
<DocumentTypeEditor
|
||||
caseNumber={caseNumber}
|
||||
docId={doc.id}
|
||||
docType={doc.doc_type}
|
||||
appraiserSide={
|
||||
(doc.metadata as { appraiser_side?: string } | undefined)
|
||||
?.appraiser_side
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
|
||||
Reference in New Issue
Block a user