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:
2026-04-11 16:21:21 +00:00
parent 03b25bc273
commit 9fcf4f2dc7
14 changed files with 808 additions and 15 deletions

View File

@@ -0,0 +1,49 @@
"use client"
import { useTheme } from "next-themes"
import { Toaster as Sonner, type ToasterProps } from "sonner"
import { CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon } from "lucide-react"
const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme()
return (
<Sonner
theme={theme as ToasterProps["theme"]}
className="toaster group"
icons={{
success: (
<CircleCheckIcon className="size-4" />
),
info: (
<InfoIcon className="size-4" />
),
warning: (
<TriangleAlertIcon className="size-4" />
),
error: (
<OctagonXIcon className="size-4" />
),
loading: (
<Loader2Icon className="size-4 animate-spin" />
),
}}
style={
{
"--normal-bg": "var(--popover)",
"--normal-text": "var(--popover-foreground)",
"--normal-border": "var(--border)",
"--border-radius": "var(--radius)",
} as React.CSSProperties
}
toastOptions={{
classNames: {
toast: "cn-toast",
},
}}
{...props}
/>
)
}
export { Toaster }