/* eslint-disable @next/next/no-img-element */ import type { WineType } from "@prisma/client"; import { useSession } from "next-auth/react"; import Head from "next/head"; import Link from "next/link"; import { useRouter } from "next/router"; import { useState } from "react"; import { Button, buttonVariants } from "~/components/ui/button"; import { Input } from "~/components/ui/input"; import { Popover, PopoverContent, PopoverTrigger, } from "~/components/ui/popover"; import { cn } from "~/lib/utils"; import { api, type RouterInputs } from "~/utils/api"; import { Check, ChevronsUpDown, Loader2, XIcon } from "lucide-react"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, } from "~/components/ui/command"; import { wineries } from "~/lib/data"; import { UploadButton } from "~/utils/uploadthing"; import { Textarea } from "~/components/ui/textarea"; const WINE_TYPES: WineType[] = [ "RED", "WHITE", "ROSE", ]; type WineInput = RouterInputs["wine"]["createWine"]; const DEFAULT_WINE: WineInput = { name: "", imageUrl: "", year: new Date().getFullYear(), type: "RED", varietal: "", rating: 0, wineryKey: "", note: "", }; import { z } from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "~/components/ui/form"; const currentYear = new Date().getFullYear(); const yearValidator = z .number({ invalid_type_error: "A value for this field is required" }) .or(z.literal(0)) .refine((value) => value === 0 || (value >= 1800 && value <= currentYear), { message: "Number must be 0 or between 1800 and the current year", }); const formSchema = z.object({ name: z.string().min(2).max(50), imageUrl: z.string().nullable(), year: yearValidator, type: z.enum(["RED", "WHITE", "ROSE"]), varietal: z.string(), rating: z .number({ invalid_type_error: "Number must be less than or equal to 5" }) .min(0) .max(5) .step(0.1), wineryKey: z.string().min(1, { message: "A selected winery is required" }), note: z.string().max(500), }); export default function CreateWine() { useSession({ required: true }); const router = useRouter(); const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: DEFAULT_WINE, }); // const [wine, setWine] = useState(DEFAULT_WINE); const createWine = api.wine.createWine.useMutation(); const [creatingWine, setCreatingWine] = useState(false); const handleSaveWine = async (values: z.infer) => { setCreatingWine(true); await createWine.mutateAsync(values); setCreatingWine(false); await router.push("/"); }; const [winerySelectorOpen, setWinerySelectorOpen] = useState(false); const [typeSelectorOpen, setTypeSelectorOpen] = useState(false); const [uploadBusy, setUploadBusy] = useState(false); const { data: version } = api.wine.getApplicationVersion.useQuery(); return ( <> Wine Demo App

Create Wine

( {field.value ? (
Uploaded wine label
) : uploadBusy ? ( ) : ( , }} onClientUploadComplete={(res) => { setUploadBusy(false); field.onChange(res.at(0)?.url ?? ""); }} onUploadError={(error: Error) => { console.error("Upload error", error); setUploadBusy(false); }} onUploadBegin={() => { setUploadBusy(true); }} /> )}
)} /> ( Name )} /> ( Winery No wineries found. {wineries .sort((a, b) => a.name.localeCompare(b.name)) .map((winery) => ( { field.onChange(currentValue); setWinerySelectorOpen(false); }} > {winery.name} ))} )} /> ( Year { field.onChange(parseInt(e.target.value, 10)); }} /> )} /> ( Type {WINE_TYPES.map((type) => ( { field.onChange(type); setTypeSelectorOpen(false); }} > {type} ))} )} /> ( Varietal )} /> ( Rating { version === 1 ? field.onChange(parseFloat(e.target.value)) : field.onChange(e.target.value.toString()); }} /> )} /> ( Note