Files
admin/src/app/(root)/coupon/page.tsx

151 lines
4.5 KiB
TypeScript
Raw Normal View History

"use client"
import { format } from "date-fns"
import { Suspense, useState } from "react"
import { toast } from "sonner"
import { deleteCoupon, getPagCoupon } from "@/actions/coupon"
import { DataTable, useDataTable } from "@/components/data-table"
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog"
import { Button } from "@/components/ui/button"
import type { Coupon } from "@/models/coupon"
import { CreateDiscount } from "./create"
import { UpdateCoupon } from "./update"
export default function CouponPage() {
const table = useDataTable((page, size) => getPagCoupon({ page, size }))
return (
<div className="flex flex-col gap-3">
<div className="flex justify-between items-stretch">
<div className="flex gap-3">
<CreateDiscount onSuccess={table.refresh} />
</div>
</div>
<Suspense>
<DataTable<Coupon>
{...table}
columns={[
{ header: "ID", accessorKey: "id" },
{ header: "所属用户", accessorKey: "user_id" },
{ header: "代码", accessorKey: "code" },
{ header: "备注", accessorKey: "remark" },
{ header: "金额", accessorKey: "amount" },
{ header: "最低消费金额", accessorKey: "min_amount" },
{
header: "状态",
accessorKey: "status",
cell: ({ row }) => {
const status = row.original.status
if (status === 0) {
return <span className="text-yellow-600">使</span>
}
if (status === 1) {
return <span className="text-green-600">使</span>
}
return <span>-</span>
},
},
{
header: "过期时间",
accessorKey: "expire_at",
cell: ({ row }) =>
format(new Date(row.original.created_at), "yyyy-MM-dd HH:mm"),
},
{
header: "创建时间",
accessorKey: "created_at",
cell: ({ row }) =>
format(new Date(row.original.created_at), "yyyy-MM-dd HH:mm"),
},
{
header: "更新时间",
accessorKey: "updated_at",
cell: ({ row }) =>
format(new Date(row.original.updated_at), "yyyy-MM-dd HH:mm"),
},
{
2026-03-28 15:36:08 +08:00
id: "action",
meta: { pin: "right" },
header: "操作",
cell: ({ row }) => (
<div className="flex gap-2">
<UpdateCoupon
coupon={row.original}
onSuccess={table.refresh}
/>
<DeleteCoupon
coupon={row.original}
onSuccess={table.refresh}
/>
</div>
),
},
]}
/>
</Suspense>
</div>
)
}
function DeleteCoupon({
coupon,
onSuccess,
}: {
coupon: Coupon
onSuccess?: () => void
}) {
const [loading, setLoading] = useState(false)
const handleConfirm = async () => {
setLoading(true)
try {
const resp = await deleteCoupon(coupon.id)
if (resp.success) {
toast.success("删除成功")
onSuccess?.()
} else {
toast.error(resp.message ?? "删除失败")
}
} catch (error) {
const message = error instanceof Error ? error.message : error
toast.error(`接口请求错误: ${message}`)
} finally {
setLoading(false)
}
}
return (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button size="sm" variant="destructive" disabled={loading}>
</Button>
</AlertDialogTrigger>
<AlertDialogContent size="sm">
<AlertDialogHeader>
<AlertDialogTitle></AlertDialogTitle>
<AlertDialogDescription>
{coupon.code}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel></AlertDialogCancel>
<AlertDialogAction variant="destructive" onClick={handleConfirm}>
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
)
}