Phase 4a: shadcn form primitives + case inline edit
Add dialog/select/textarea/label/progress/sonner components and wire
a Toaster into Providers. New zod schemas in lib/schemas/case.ts
mirror CaseCreateRequest/CaseUpdateRequest and feed react-hook-form
validation.
CaseEditDialog on the case detail Actions tab posts PUT /api/cases/{n}
with optimistic cache patching via useUpdateCase, showing toast
feedback on success/error.
shadcn's <Form> registry entry skipped at init (missing from the
nova preset); the dialog uses RHF directly against the same Input/
Textarea/Select primitives.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,8 +8,9 @@
|
||||
* surfaces as a runtime TypeScript error the first time a property is touched.
|
||||
*/
|
||||
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { apiRequest } from "./client";
|
||||
import type { CaseCreateInput, CaseUpdateInput } from "@/lib/schemas/case";
|
||||
|
||||
export type CaseStatus =
|
||||
| "new"
|
||||
@@ -95,6 +96,41 @@ export type WorkflowStatus = {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
export function useCreateCase() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (input: CaseCreateInput) =>
|
||||
apiRequest<{ case_number?: string; message?: string; [k: string]: unknown }>(
|
||||
`/api/cases/create`,
|
||||
{ method: "POST", body: input },
|
||||
),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: casesKeys.all });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useUpdateCase(caseNumber: string | undefined) {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (input: CaseUpdateInput) =>
|
||||
apiRequest<CaseDetail>(`/api/cases/${caseNumber}`, {
|
||||
method: "PUT",
|
||||
body: input,
|
||||
}),
|
||||
onSuccess: (data) => {
|
||||
/* Patch cached detail and nudge the list to refetch on next focus */
|
||||
if (caseNumber) {
|
||||
qc.setQueryData<CaseDetail | undefined>(
|
||||
casesKeys.detail(caseNumber),
|
||||
(prev) => (prev ? { ...prev, ...data } : prev),
|
||||
);
|
||||
}
|
||||
qc.invalidateQueries({ queryKey: casesKeys.all });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useWorkflowStatus(caseNumber: string | undefined) {
|
||||
return useQuery({
|
||||
queryKey: [...casesKeys.all, "workflow", caseNumber ?? ""] as const,
|
||||
|
||||
Reference in New Issue
Block a user