Merge pull request 'fix(#77 frontend): separate מספר-תיק field on committee upload + editable case_number' (#41) from fix/77-precedent-identity-frontend into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 38s
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 38s
This commit was merged in pull request #41.
This commit is contained in:
@@ -35,7 +35,7 @@ type Props = {
|
|||||||
* each time the sheet opens so the form reflects any auto-fill that
|
* each time the sheet opens so the form reflects any auto-fill that
|
||||||
* happened in the background. */
|
* happened in the background. */
|
||||||
type FormState = {
|
type FormState = {
|
||||||
citation: string;
|
case_number: string;
|
||||||
citation_formatted: string;
|
citation_formatted: string;
|
||||||
case_name: string;
|
case_name: string;
|
||||||
court: string;
|
court: string;
|
||||||
@@ -54,7 +54,7 @@ type FormState = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const EMPTY: FormState = {
|
const EMPTY: FormState = {
|
||||||
citation: "", citation_formatted: "",
|
case_number: "", citation_formatted: "",
|
||||||
case_name: "", court: "", district: "", chair_name: "",
|
case_name: "", court: "", district: "", chair_name: "",
|
||||||
decision_date: "", practice_area: "", appeal_subtype: "", source_type: "",
|
decision_date: "", practice_area: "", appeal_subtype: "", source_type: "",
|
||||||
precedent_level: "", is_binding: true, subject_tags: "",
|
precedent_level: "", is_binding: true, subject_tags: "",
|
||||||
@@ -76,7 +76,7 @@ export function PrecedentEditSheet({ caseLawId, onOpenChange }: Props) {
|
|||||||
if (record && record.id !== syncedRecordId) {
|
if (record && record.id !== syncedRecordId) {
|
||||||
setSyncedRecordId(record.id as string);
|
setSyncedRecordId(record.id as string);
|
||||||
setForm({
|
setForm({
|
||||||
citation: record.case_number || "",
|
case_number: record.case_number || "",
|
||||||
citation_formatted: record.citation_formatted || "",
|
citation_formatted: record.citation_formatted || "",
|
||||||
case_name: record.case_name || "",
|
case_name: record.case_name || "",
|
||||||
court: record.court || "",
|
court: record.court || "",
|
||||||
@@ -117,8 +117,10 @@ export function PrecedentEditSheet({ caseLawId, onOpenChange }: Props) {
|
|||||||
key_quote: form.key_quote.trim(),
|
key_quote: form.key_quote.trim(),
|
||||||
};
|
};
|
||||||
if (form.decision_date) patch.decision_date = form.decision_date;
|
if (form.decision_date) patch.decision_date = form.decision_date;
|
||||||
// citation (case_number) is the unique key; we don't allow editing it
|
// case_number is the canonical identifier. Editing it is safe —
|
||||||
// here to avoid orphaning halachot. To rename, delete + re-upload.
|
// halachot/chunks reference case_law_id (UUID), not the case_number
|
||||||
|
// text — so a wrong id captured at upload can be corrected here.
|
||||||
|
if (form.case_number.trim()) patch.case_number = form.case_number.trim();
|
||||||
await update.mutateAsync({ id: caseLawId, patch });
|
await update.mutateAsync({ id: caseLawId, patch });
|
||||||
toast.success("נשמר");
|
toast.success("נשמר");
|
||||||
onOpenChange(false);
|
onOpenChange(false);
|
||||||
@@ -148,7 +150,7 @@ export function PrecedentEditSheet({ caseLawId, onOpenChange }: Props) {
|
|||||||
<DialogHeader className="px-6 pt-6">
|
<DialogHeader className="px-6 pt-6">
|
||||||
<DialogTitle className="text-navy">עריכת פרטי פסיקה</DialogTitle>
|
<DialogTitle className="text-navy">עריכת פרטי פסיקה</DialogTitle>
|
||||||
<DialogDescription className="text-ink-muted">
|
<DialogDescription className="text-ink-muted">
|
||||||
כל השדות ניתנים לעריכה חוץ ממספר התיק (מזהה ייחודי במערכת).
|
כל השדות ניתנים לעריכה, כולל מספר התיק (המזהה הייחודי).
|
||||||
כפתור "חלץ מטא-דאטה" שולח בקשה לתור מקומי שאני מרוקן
|
כפתור "חלץ מטא-דאטה" שולח בקשה לתור מקומי שאני מרוקן
|
||||||
מ-Claude Code (ה-LLM רץ מקומית עם <code>claude session</code>,
|
מ-Claude Code (ה-LLM רץ מקומית עם <code>claude session</code>,
|
||||||
לא ב-API).
|
לא ב-API).
|
||||||
@@ -162,12 +164,17 @@ export function PrecedentEditSheet({ caseLawId, onOpenChange }: Props) {
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<form onSubmit={onSubmit} className="px-6 pb-6 space-y-4 mt-4">
|
<form onSubmit={onSubmit} className="px-6 pb-6 space-y-4 mt-4">
|
||||||
<div className="rounded-lg border border-rule bg-rule-soft/40 p-3 flex items-start gap-3">
|
<div className="rounded-lg border border-rule bg-rule-soft/40 p-3 flex items-end gap-3">
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0 space-y-1">
|
||||||
<div className="text-[0.78rem] text-ink-muted">מספר תיק (מזהה ייחודי — לא ניתן לעריכה)</div>
|
<Label htmlFor="case-number" className="text-[0.78rem] text-ink-muted">
|
||||||
<div className="text-navy font-mono text-sm break-all" dir="ltr">
|
מספר תיק (מזהה ייחודי)
|
||||||
{record.case_number}
|
</Label>
|
||||||
</div>
|
<Input
|
||||||
|
id="case-number" value={form.case_number}
|
||||||
|
onChange={(e) => setForm({ ...form, case_number: e.target.value })}
|
||||||
|
className="font-mono text-sm" dir="ltr"
|
||||||
|
placeholder="8027-25"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
type="button" size="sm" variant="outline"
|
type="button" size="sm" variant="outline"
|
||||||
|
|||||||
@@ -50,6 +50,10 @@ export function PrecedentUploadSheet({ open, onOpenChange }: Props) {
|
|||||||
// require chair_name + district. Routing is by citation prefix.
|
// require chair_name + district. Routing is by citation prefix.
|
||||||
const [chairName, setChairName] = useState("");
|
const [chairName, setChairName] = useState("");
|
||||||
const [district, setDistrict] = useState<CommitteeDistrict | "">("");
|
const [district, setDistrict] = useState<CommitteeDistrict | "">("");
|
||||||
|
// Canonical identifier for committee decisions (e.g. "8027-25"), kept
|
||||||
|
// distinct from the citation (מראה-מקום). Previously the citation was sent
|
||||||
|
// as case_number, polluting the identifier.
|
||||||
|
const [caseNumber, setCaseNumber] = useState("");
|
||||||
const isCommittee = isCommitteeCitation(citation);
|
const isCommittee = isCommitteeCitation(citation);
|
||||||
|
|
||||||
const [taskId, setTaskId] = useState<string | null>(null);
|
const [taskId, setTaskId] = useState<string | null>(null);
|
||||||
@@ -72,7 +76,7 @@ export function PrecedentUploadSheet({ open, onOpenChange }: Props) {
|
|||||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||||
setHeadnote(""); setIsBinding(true); setTaskId(null);
|
setHeadnote(""); setIsBinding(true); setTaskId(null);
|
||||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||||
setChairName(""); setDistrict("");
|
setChairName(""); setDistrict(""); setCaseNumber("");
|
||||||
}, [open]);
|
}, [open]);
|
||||||
|
|
||||||
// Auto-close on completion + refresh library list/stats so the new
|
// Auto-close on completion + refresh library list/stats so the new
|
||||||
@@ -110,6 +114,10 @@ export function PrecedentUploadSheet({ open, onOpenChange }: Props) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (isCommittee) {
|
if (isCommittee) {
|
||||||
|
if (!caseNumber.trim()) {
|
||||||
|
toast.error("מספר תיק (מזהה ייחודי) חובה להחלטת ועדת ערר");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!chairName.trim()) {
|
if (!chairName.trim()) {
|
||||||
toast.error("שם יו\"ר חובה להחלטת ועדת ערר");
|
toast.error("שם יו\"ר חובה להחלטת ועדת ערר");
|
||||||
return;
|
return;
|
||||||
@@ -120,7 +128,8 @@ export function PrecedentUploadSheet({ open, onOpenChange }: Props) {
|
|||||||
}
|
}
|
||||||
const res = await uploadInternal.mutateAsync({
|
const res = await uploadInternal.mutateAsync({
|
||||||
file,
|
file,
|
||||||
case_number: citation.trim(),
|
case_number: caseNumber.trim(),
|
||||||
|
citation: citation.trim(),
|
||||||
chair_name: chairName.trim(),
|
chair_name: chairName.trim(),
|
||||||
district,
|
district,
|
||||||
case_name: caseName.trim(),
|
case_name: caseName.trim(),
|
||||||
@@ -202,7 +211,20 @@ export function PrecedentUploadSheet({ open, onOpenChange }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isCommittee && (
|
{isCommittee && (
|
||||||
<div className="grid grid-cols-2 gap-3 rounded-md border border-gold/40 bg-gold-wash/40 p-3">
|
<div className="space-y-3 rounded-md border border-gold/40 bg-gold-wash/40 p-3">
|
||||||
|
<div className="space-y-1">
|
||||||
|
<Label htmlFor="committee-case-number">מספר תיק — מזהה ייחודי (חובה)</Label>
|
||||||
|
<Input
|
||||||
|
id="committee-case-number" value={caseNumber}
|
||||||
|
onChange={(e) => setCaseNumber(e.target.value)}
|
||||||
|
placeholder="8027-25"
|
||||||
|
disabled={isProcessing} dir="rtl"
|
||||||
|
/>
|
||||||
|
<p className="text-[0.72rem] text-ink-muted">
|
||||||
|
המזהה הנקי בלבד (למשל 8027-25) — לא המראה-מקום המלא.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-2 gap-3">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<Label htmlFor="chair-name">שם יו"ר (חובה)</Label>
|
<Label htmlFor="chair-name">שם יו"ר (חובה)</Label>
|
||||||
<Input
|
<Input
|
||||||
@@ -231,6 +253,7 @@ export function PrecedentUploadSheet({ open, onOpenChange }: Props) {
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<details className="group rounded-md border border-rule bg-rule-soft/30">
|
<details className="group rounded-md border border-rule bg-rule-soft/30">
|
||||||
|
|||||||
@@ -387,6 +387,9 @@ export function isCommitteeCitation(citation: string): boolean {
|
|||||||
export type InternalDecisionUploadInput = {
|
export type InternalDecisionUploadInput = {
|
||||||
file: File;
|
file: File;
|
||||||
case_number: string;
|
case_number: string;
|
||||||
|
/** Full citation (מראה-מקום), stored as citation_formatted. Distinct from
|
||||||
|
* the canonical case_number identifier. */
|
||||||
|
citation?: string;
|
||||||
chair_name: string;
|
chair_name: string;
|
||||||
district: CommitteeDistrict | string;
|
district: CommitteeDistrict | string;
|
||||||
case_name?: string;
|
case_name?: string;
|
||||||
@@ -406,6 +409,7 @@ export function useUploadInternalDecision() {
|
|||||||
const fd = new FormData();
|
const fd = new FormData();
|
||||||
fd.append("file", input.file);
|
fd.append("file", input.file);
|
||||||
fd.append("case_number", input.case_number);
|
fd.append("case_number", input.case_number);
|
||||||
|
if (input.citation) fd.append("citation", input.citation);
|
||||||
fd.append("chair_name", input.chair_name);
|
fd.append("chair_name", input.chair_name);
|
||||||
fd.append("district", input.district);
|
fd.append("district", input.district);
|
||||||
if (input.case_name) fd.append("case_name", input.case_name);
|
if (input.case_name) fd.append("case_name", input.case_name);
|
||||||
@@ -488,6 +492,7 @@ export function useUnlinkRelatedCase(caseId: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type PrecedentPatch = Partial<{
|
export type PrecedentPatch = Partial<{
|
||||||
|
case_number: string;
|
||||||
case_name: string;
|
case_name: string;
|
||||||
court: string;
|
court: string;
|
||||||
decision_date: string;
|
decision_date: string;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user