diff --git a/src/app/bottles/[id]/edit/edit-bottle-form.tsx b/src/app/bottles/[id]/edit/edit-bottle-form.tsx index 0c50dfc..f1d11f6 100644 --- a/src/app/bottles/[id]/edit/edit-bottle-form.tsx +++ b/src/app/bottles/[id]/edit/edit-bottle-form.tsx @@ -1,233 +1,50 @@ "use client"; -import { useState } from "react"; import { useRouter } from "next/navigation"; -import { Controller, useForm } from "react-hook-form"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { bottleSchema, REGIONS } from "@/lib/schemas/bottle"; import type { Bottle } from "@/generated/prisma/client"; -import { Button } from "@/components/ui/button"; -import { Checkbox } from "@/components/ui/checkbox"; -import { - Field, - FieldError, - FieldGroup, - FieldLabel, -} from "@/components/ui/field"; -import { Input } from "@/components/ui/input"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; -import { Textarea } from "@/components/ui/textarea"; - -// 数値入力:空欄は「未入力」として undefined を渡す(zod 側で NAS/既定値の扱いを決める)。 -const asOptionalNumber = (value: unknown) => - value === "" || value == null ? undefined : Number(value); - -// 国の「未選択」用センチネル。Radix の SelectItem は空文字値を禁止するため、 -// 空でないダミー値を持たせ、選択時に null(=クリア)へ正規化する(送信データには出さない)。 -const NONE = "__none__"; +import { REGIONS } from "@/lib/schemas/bottle"; +import { BottleForm } from "../../bottle-form"; +// 編集用ラッパー:共有フォームに既存値・文言・送信処理(PATCH)を渡す。 export function EditBottleForm({ bottle }: { bottle: Bottle }) { const router = useRouter(); - const [serverError, setServerError] = useState(null); - const { - register, - control, - handleSubmit, - formState: { errors, isSubmitting }, - } = useForm({ - resolver: zodResolver(bottleSchema), - // 既存値で初期化。任意テキストの null はフォーム用に "" へ、 - // 国は DB では string 型だが値は REGIONS のいずれか(未設定は undefined)。 - defaultValues: { - name: bottle.name, - region: (bottle.region as (typeof REGIONS)[number] | null) ?? undefined, - subRegion: bottle.subRegion ?? "", - age: bottle.age ?? undefined, - caskType: bottle.caskType ?? "", - isLimited: bottle.isLimited, - quantity: bottle.quantity, - note: bottle.note ?? "", - }, - }); - - const onSubmit = handleSubmit(async (data) => { - setServerError(null); - // 空欄の任意項目は明示 null で送る(undefined だと JSON から落ち、PATCH で「変更なし」=消せないため)。 - const payload = { - ...data, - region: data.region ?? null, - subRegion: data.subRegion ?? null, - age: data.age ?? null, - caskType: data.caskType ?? null, - note: data.note ?? null, - }; - try { - const response = await fetch(`/api/bottles/${bottle.id}`, { - method: "PATCH", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(payload), - }); - if (!response.ok) { - setServerError("更新に失敗しました。もう一度お試しください。"); - return; - } - router.push(`/bottles/${bottle.id}`); - router.refresh(); - } catch { - setServerError("更新に失敗しました。もう一度お試しください。"); - } - }); - return ( -
- - {/* - 銘柄名・地域は Chrome に氏名・住所と誤認され、autocomplete="off" だけでは - 住所サジェストを抑止できない(Chrome は off を無視して name/id から用途を推測する)。 - 認識されない name/id に変えるのが確実な回避策だが、register は DOM の name 属性に - 依存するため、この 2 フィールドだけ Controller で接続して属性を自由にしている。 - */} - - 銘柄名(必須) - ( - - )} - /> - - - - - - ( - - )} - /> - - - - 地域 - ( - - )} - /> - - - - 年数 - - - - - - - - - - - ( - - )} - /> - 限定版 - - - - 本数 - - - - - - メモ -