Full code review of the case-detail page (14 components) surfaced these,
all fixed here:
Logic bugs
- case-edit-dialog: form.reset ran on the 5s useCase refetch while the dialog
was open, clobbering in-progress edits. Now resets only on open→true.
- status-changer: `selected` never synced to async/external `currentStatus`
(stale dropdown). Reworked to track currentStatus until an explicit pick;
resets to tracking after save.
- decision-blocks-panel: `block.content`/`word_count` accessed without null
guards (endpoint has no response model) → potential render crash. Coerced
with `?? ""` / `?? 0`. `STATUS_LABELS[status]` now falls back to the raw
status instead of rendering literal "undefined".
- document-type-editor: `await mutateAsync()` in async click handlers without
try/catch → unhandled promise rejection. Wrapped (errors still surface via
isError).
Resilience / hygiene
- page.tsx: a transient 5xx on the background poll flipped the WHOLE page to
the error card and discarded loaded data. Now gated on `!data`, plus a
"נסה שוב" retry.
- cases.ts useUpdateCase: invalidated casesKeys.all, which re-invalidated the
detail it had just optimistically patched. Scoped to the list prefix.
RTL correctness (logical properties)
- agent-status-widget `mr-auto`→`ms-auto`; agent-activity-feed `mr-auto`→
`me-auto`, icon `ml-1/ml-2`→`me-1/me-2`, required `*` `mr-1`→`ms-1`;
document-type-editor list `pr-4`→`ps-4`.
Minors
- drafts-panel: `<a href>`→`next/link` (operations + citation links) for SPA
nav. agent-activity-feed: issueMap memoized; comment Textarea aria-label.
upload-sheet: `unknown` status no longer shown as green success (neutral
icon + "רענן לאישור"). citations.ts: case_name typed `string | null`.
Design gate: visual-touching items (RTL gap side, retry button, neutral
upload icon) were chair-authorized via the reviewed-findings approval ("fix
all"); none alter an approved page layout — they are correctness fixes.
tsc clean; eslint clean (1 pre-existing form.watch warning, untouched line).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
39 lines
996 B
TypeScript
39 lines
996 B
TypeScript
/**
|
|
* Citations domain — precedents CITED inside a case's signed decision.
|
|
* Powers the case-page "פסיקה שצוטטה בהחלטה" panel.
|
|
*/
|
|
|
|
import { useQuery } from "@tanstack/react-query";
|
|
import { apiRequest } from "./client";
|
|
|
|
export type LinkedCitation = {
|
|
citation: string;
|
|
cited_id: string;
|
|
/** May be null/empty — the panel guards with `c.case_name && …`. */
|
|
case_name: string | null;
|
|
court: string;
|
|
precedent_level: string;
|
|
};
|
|
|
|
export type MissingCitation = {
|
|
citation: string;
|
|
flagged: boolean;
|
|
};
|
|
|
|
export type CaseCitations = {
|
|
in_library: boolean;
|
|
case_law_id?: string;
|
|
linked: LinkedCitation[];
|
|
missing: MissingCitation[];
|
|
};
|
|
|
|
export function useCaseCitations(caseNumber: string | undefined) {
|
|
return useQuery({
|
|
queryKey: ["case-citations", caseNumber ?? ""],
|
|
queryFn: ({ signal }) =>
|
|
apiRequest<CaseCitations>(`/api/cases/${caseNumber}/citations`, { signal }),
|
|
enabled: Boolean(caseNumber),
|
|
staleTime: 10_000,
|
|
});
|
|
}
|