"use client" import * as React from "react" import { toast } from "sonner" import { z } from "zod" import { Card, CardAction, CardContent, CardFooter, CardHeader, } from "@/styles/base-nova/ui/card" import { Questionnaire, QuestionnaireActions, QuestionnaireChoice, QuestionnaireChoices, QuestionnaireDescription, QuestionnaireError, QuestionnaireItem, QuestionnaireNext, QuestionnairePrevious, QuestionnaireProgress, QuestionnaireSubmit, QuestionnaireTitle, } from "@/styles/base-nova/ui/questionnaire" const items = [ { name: "detail", required: true }, { name: "audience", required: true }, ] as const const questionnaireSchema = z .object({ detail: z.enum(["summary", "complete"]), audience: z.enum(["team", "public"]), }) .superRefine((answers, context) => { if (answers.audience === "public" && answers.detail === "summary") { context.addIssue({ code: z.ZodIssueCode.custom, message: "Public answers need enough context. Choose a complete answer.", path: ["detail"], }) } }) type QuestionnaireItemName = keyof z.infer type QuestionnaireErrors = Partial> function ValidationProgress() { return ( (
{state.current} / {state.total}
)} /> ) } export function QuestionnaireValidation() { const [item, setItem] = React.useState("detail") const [errors, setErrors] = React.useState({}) function clearError(name: QuestionnaireItemName) { setErrors((currentErrors) => { if (!currentErrors[name]) { return currentErrors } const nextErrors = { ...currentErrors } delete nextErrors[name] return nextErrors }) } function handleSubmit(event: React.FormEvent) { event.preventDefault() const result = questionnaireSchema.safeParse( Object.fromEntries(new FormData(event.currentTarget)) ) if (result.success) { setErrors({}) toast("Agent response configured", { description: `Detail: ${result.data.detail} ยท Audience: ${result.data.audience}`, }) return } const nextErrors: QuestionnaireErrors = {} for (const issue of result.error.issues) { const name = issue.path[0] if ((name === "detail" || name === "audience") && !nextErrors[name]) { nextErrors[name] = issue.message } } const firstInvalidItem = result.error.issues[0]?.path[0] setErrors(nextErrors) if (firstInvalidItem === "detail" || firstInvalidItem === "audience") { setItem(firstInvalidItem) } } return ( How much detail should the answer include? Choose the response depth. clearError("detail")} > Concise summary clearError("detail")} > Complete answer {errors.detail} Who will read the answer? Public answers require complete context. clearError("audience")} > My team clearError("audience")} > Public audience {errors.audience} Next Validate answers ) }