Phase 4b: Case create wizard

New /cases/new route with a 3-step wizard (basics / parties / details)
backed by react-hook-form + the caseCreateSchema. Each step validates
only its own fields so the user fixes errors in context. On success
useCreateCase invalidates the case list and the router pushes to the
freshly created case detail page.

PartiesField is a small chip-style editor for the appellants/respondents
arrays. The Home page now has a navy "+ תיק חדש" button that links to
the wizard.

Dropped .default() from the create schema — zod's input/output type
mismatch broke the RHF zodResolver generics; dropping the defaults is
simpler than plumbing z.input vs z.output through the mutation hook.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-11 16:23:37 +00:00
parent 9fcf4f2dc7
commit b67dc47dc7
5 changed files with 412 additions and 9 deletions

View File

@@ -51,15 +51,15 @@ export const caseCreateSchema = z.object({
respondents: z
.array(z.string().trim().min(1).refine((v) => hebrewPartyRe.test(v), "שם לא תקין"))
.min(1, "חייב להיות לפחות משיב אחד"),
subject: z.string().trim().max(500).default(""),
property_address: z.string().trim().max(200).default(""),
permit_number: z.string().trim().max(100).default(""),
committee_type: z.enum(committeeTypes).default("ועדה מקומית"),
hearing_date: dateString.default(""),
notes: z.string().trim().max(2000).default(""),
expected_outcome: z
.enum(expectedOutcomes.map((o) => o.value) as [string, ...string[]])
.default(""),
subject: z.string().trim().max(500),
property_address: z.string().trim().max(200),
permit_number: z.string().trim().max(100),
committee_type: z.enum(committeeTypes),
hearing_date: dateString,
notes: z.string().trim().max(2000),
expected_outcome: z.enum(
expectedOutcomes.map((o) => o.value) as [string, ...string[]],
),
});
export type CaseCreateInput = z.infer<typeof caseCreateSchema>;