/** * Client-side mirror of mcp-server/src/legal_mcp/services/practice_area.py. * * Keep the enum values and derivation logic in sync with the backend — the * server is the authority, but the UI needs the labels and derivation for * UX (auto-fill, badges, filters). If the server adds a new practice_area * or subtype, extend the arrays below. * * See also: legal-ai/docs/practice-area-separation.md */ export type PracticeArea = | "appeals_committee" | "national_insurance" | "labor_law"; export type AppealSubtype = | "building_permit" | "betterment_levy" | "compensation_197" /* בל"מ — בקשה להארכת מועד להגשת ערר. שלושה מסלולים נפרדים. */ | "extension_request_building_permit" | "extension_request_betterment_levy" | "extension_request_compensation" | "unknown"; export const PRACTICE_AREAS: ReadonlyArray<{ value: PracticeArea; label: string; enabled: boolean; }> = [ { value: "appeals_committee", label: "ועדת ערר", enabled: true }, { value: "national_insurance", label: "ביטוח לאומי", enabled: false }, { value: "labor_law", label: "דיני עבודה", enabled: false }, ]; export const APPEAL_SUBTYPES: ReadonlyArray<{ value: AppealSubtype; label: string; }> = [ { value: "building_permit", label: "רישוי ובנייה" }, { value: "betterment_levy", label: "היטל השבחה" }, { value: "compensation_197", label: "פיצויים (ס' 197)" }, /* The "בל\"מ" prefix is dropped from these labels because the * proceeding_type field now drives the בל"מ badge. Keeping the domain * label here lets a row show "רישוי ובנייה" with a separate בל"מ * pill instead of double-marking it. */ { value: "extension_request_building_permit", label: "רישוי ובנייה" }, { value: "extension_request_betterment_levy", label: "היטל השבחה" }, { value: "extension_request_compensation", label: "פיצויים (ס' 197)" }, { value: "unknown", label: "לא ידוע" }, ]; /* בל"מ subtypes — תת-קבוצה. שימוש: badges, filters */ export const BLAM_SUBTYPES: ReadonlySet = new Set([ "extension_request_building_permit", "extension_request_betterment_levy", "extension_request_compensation", ]); export function isBlamSubtype(s?: AppealSubtype | null): boolean { return s != null && BLAM_SUBTYPES.has(s); } export const PRACTICE_AREA_LABELS: Record = Object.fromEntries(PRACTICE_AREAS.map((p) => [p.value, p.label])) as Record< PracticeArea, string >; export const APPEAL_SUBTYPE_LABELS: Record = Object.fromEntries(APPEAL_SUBTYPES.map((s) => [s.value, s.label])) as Record< AppealSubtype, string >; /* * Derive the appeal_subtype from a case number. Mirrors the Python * `derive_subtype` in practice_area.py. The convention is the case-number * first digit: 1xxx → building_permit, 8xxx → betterment_levy, * 9xxx → compensation_197. Everything else, including non-appeals_committee * domains, returns 'unknown'. */ export function deriveSubtype( caseNumber: string, practiceArea: PracticeArea = "appeals_committee", ): AppealSubtype { if (practiceArea !== "appeals_committee") return "unknown"; const first = caseNumber.trim().match(/^(\d)/)?.[1]; if (first === "1") return "building_permit"; if (first === "8") return "betterment_levy"; if (first === "9") return "compensation_197"; return "unknown"; } /* * Detect a בל"מ subject (בקשה להארכת מועד). Mirrors the Python * `is_blam_subject` in practice_area.py. Accepts common variants. */ const BLAM_SUBJECT_RE = /(?:בקשה\s+להארכת\s+מועד|בל["״]מ|הארכת\s+מועד\s+להגשת)/i; export function isBlamSubject(subject: string): boolean { return Boolean(subject) && BLAM_SUBJECT_RE.test(subject); } /* * Like deriveSubtype() but also detects בל"מ from the subject. Mirrors * `derive_subtype_with_blam()` in practice_area.py. */ export function deriveSubtypeWithBlam( caseNumber: string, subject: string = "", practiceArea: PracticeArea = "appeals_committee", ): AppealSubtype { const base = deriveSubtype(caseNumber, practiceArea); if (!isBlamSubject(subject)) return base; if (base === "building_permit") return "extension_request_building_permit"; if (base === "betterment_levy") return "extension_request_betterment_levy"; if (base === "compensation_197") return "extension_request_compensation"; return base; }