import { zodResolver } from "@hookform/resolvers/zod" import { useState } from "react" import { Controller, useForm } from "react-hook-form" import { toast } from "sonner" import z from "zod" import { updateCoupon } from "@/actions/coupon" import { Button } from "@/components/ui/button" import { Dialog, DialogClose, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" import { FieldError, FieldGroup, FieldLabel } from "@/components/ui/field" import { Input } from "@/components/ui/input" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import type { Coupon } from "@/models/coupon" const schema = z.object({ name: z.string().min(1, "请输入优惠券名称"), amount: z.string() .min(1, "请输入优惠券金额") .regex(/^\d+(\.\d+)?$/, "请输入有效的金额数字") .refine(val => Number(val) > 0, "优惠券金额必须大于0"), count: z.string() .min(1, "请输入优惠券数量") .regex(/^\d+$/, "请输入正整数") .refine(val => Number(val) >= 1, "优惠券数量至少为1"), min_amount: z.string() .min(1, "请输入最低消费金额") .regex(/^\d+(\.\d+)?$/, "请输入有效的金额数字") .refine(val => Number(val) >= 0, "最低消费金额不能为负数"), expire_at: z.string().optional(), expire_type: z.string().min(1, "请选择过期类型"), expire_in: z.string().optional(), status:z.string().optional() }).superRefine((data, ctx) => { const expireType = Number(data.expire_type); if (!data.expire_type) return; if (expireType === 1 && !data.expire_at) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: "请选择过期时间", path: ["expire_at"] }); } if (expireType === 2 && !data.expire_in) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: "请输入过期时长天数", path: ["expire_in"] }); } }) export function UpdateCoupon(props: { coupon: Coupon onSuccess?: () => void }) { const [open, setOpen] = useState(false) const form = useForm({ resolver: zodResolver(schema), defaultValues: { name: props.coupon.name, amount: String(props.coupon.amount), min_amount: String(props.coupon.min_amount), expire_at: props?.coupon.expire_at ? new Date(props?.coupon.expire_at).toISOString().split("T")[0] : "", status: String(props.coupon.status), count: String(props.coupon.count), expire_in: String(props?.coupon.expire_in), }, mode: "onChange", }) const { control, handleSubmit, reset, watch } = form const watchExpireType = watch("expire_type") const onSubmit = async (data: z.infer) => { try { const expireType = Number(data.expire_type) const payload = { id: props.coupon.id, name: data.name, amount: Number(data.amount), min_amount: Number(data.min_amount), count: Number(data.count), status: Number(data.status), expire_type: expireType, expire_at: data.expire_at ? new Date(data.expire_at) : undefined, expire_in: expireType === 2 ? Number(data.expire_in) : undefined, } const resp = await updateCoupon(payload) if (resp.success) { toast.success("优惠券修改成功") props.onSuccess?.() setOpen(false) } else { toast.error(resp.message) } } catch (error) { const message = error instanceof Error ? error.message : error toast.error(`接口请求错误: ${message}`) } } const handleOpenChange = (value: boolean) => { if (value) { reset({ name: props.coupon.name, count: String(props.coupon.count), amount: String(props.coupon.amount ), min_amount: String(props.coupon.min_amount), expire_at: props.coupon.expire_at ? new Date(props.coupon.expire_at).toISOString().split("T")[0] : "", status: String(props.coupon.status), expire_type: String(props.coupon.expire_type), expire_in: String(props.coupon.expire_in), }) } setOpen(value) } return ( 修改优惠券
(
优惠券名称:
{fieldState.error?.message}
)} /> (
优惠券数量:
{fieldState.error?.message}
)} /> (
优惠券金额:
{fieldState.error?.message}
)} /> (
最低消费金额:
{fieldState.error?.message}
)} /> (
优惠券状态:
{fieldState.error?.message}
)} /> (
过期类型:
{fieldState.error?.message}
)} /> {watchExpireType === "1" && ( (
过期时间:
{fieldState.error?.message}
)} /> )} {watchExpireType === "2" && ( (
过期时长(天):
{fieldState.error?.message}
)} /> )}
) }