Phase 4.5: practice area integration in the Next.js UI
Backend commit 26d09d6 introduced a multi-tenant axis (practice_area +
appeal_subtype) that the vanilla UI picked up but the new Next.js
rewrite did not. Close the gap in the screens we already shipped so
future search/filter work in Phase 5 has the right data on screen.
- lib/practice-area.ts — new: enum + label maps + deriveSubtype(),
mirrors mcp-server/src/legal_mcp/services/practice_area.py.
- lib/schemas/case.ts — two new z.enum fields on caseCreateSchema.
- lib/api/cases.ts — Case / CaseDetail gain practice_area and
appeal_subtype as optional (cached pre-migration responses still
parse cleanly).
- wizard/case-wizard.tsx — basics step gains a practice_area dropdown
(future domains disabled with "(בקרוב)") and an appeal_subtype
dropdown with auto-fill effect tracking a userTouchedSubtype ref,
same behaviour as wireSubtypeAutofill() in the vanilla UI.
- cases/case-header.tsx — gold badge next to the status shows
"ועדת ערר · רישוי ובנייה" when both fields are populated.
- cases/cases-table.tsx — new "תחום" column showing subtype label
(dash for unknown). No filter yet — that's phase 5 when a second
domain actually exists.
Plan: ~/.claude/plans/woolly-cooking-graham.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import Link from "next/link";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { StatusBadge } from "@/components/cases/status-badge";
|
||||
import {
|
||||
PRACTICE_AREA_LABELS,
|
||||
APPEAL_SUBTYPE_LABELS,
|
||||
} from "@/lib/practice-area";
|
||||
import type { CaseDetail } from "@/lib/api/cases";
|
||||
|
||||
function formatDate(iso?: string | null) {
|
||||
@@ -30,11 +35,22 @@ export function CaseHeader({ data }: { data?: CaseDetail }) {
|
||||
|
||||
<div className="flex items-start justify-between gap-6 flex-wrap">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex items-center gap-3 flex-wrap">
|
||||
<span className="font-display text-[2rem] font-black text-navy leading-none tabular-nums">
|
||||
ערר {data?.case_number ?? "—"}
|
||||
</span>
|
||||
{data?.status && <StatusBadge status={data.status} />}
|
||||
{data?.practice_area && (
|
||||
<Badge
|
||||
variant="outline"
|
||||
className="rounded-full px-2.5 py-0.5 text-[0.72rem] font-medium bg-gold-wash text-gold-deep border-gold/40"
|
||||
>
|
||||
{PRACTICE_AREA_LABELS[data.practice_area]}
|
||||
{data.appeal_subtype && data.appeal_subtype !== "unknown" && (
|
||||
<> · {APPEAL_SUBTYPE_LABELS[data.appeal_subtype]}</>
|
||||
)}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<h1 className="text-navy text-xl font-bold leading-snug max-w-2xl mb-0">
|
||||
{data?.title ?? "טוען…"}
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { StatusBadge } from "@/components/cases/status-badge";
|
||||
import { APPEAL_SUBTYPE_LABELS } from "@/lib/practice-area";
|
||||
import type { Case } from "@/lib/api/cases";
|
||||
|
||||
function formatDate(iso?: string) {
|
||||
@@ -59,6 +60,15 @@ const columns: ColumnDef<Case>[] = [
|
||||
header: "סטטוס",
|
||||
cell: ({ row }) => <StatusBadge status={row.original.status} />,
|
||||
},
|
||||
{
|
||||
accessorKey: "appeal_subtype",
|
||||
header: "תחום",
|
||||
cell: ({ row }) => {
|
||||
const s = row.original.appeal_subtype;
|
||||
if (!s || s === "unknown") return <span className="text-ink-muted">—</span>;
|
||||
return <span className="text-ink-soft text-sm">{APPEAL_SUBTYPE_LABELS[s]}</span>;
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "document_count",
|
||||
header: "מסמכים",
|
||||
|
||||
Reference in New Issue
Block a user