"use client"; import * as React from "react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { Edit3, Plus, Trash2 } from "lucide-react"; import AdminDateTimeField from "@/components/AdminDateTimeField"; import ConfirmAction from "@/components/ConfirmAction"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Switch } from "@/components/ui/switch"; import type { DiscountCodeSchema, DiscountCodeWriteSchema } from "@/lib/types"; import { api } from "@/lib/api"; import { formatNumberPersian, resolveErrorMessage } from "@/lib/utils"; import { useToast } from "@/hooks/use-toast"; const PAGE_SIZE = 20; const emptyForm: DiscountCodeWriteSchema = { code: "", type: "percent", value: 0, max_discount: null, is_active: true, starts_at: null, ends_at: null, usage_limit_total: null, usage_limit_per_user: null, min_amount: null, applicable_event_ids: [], }; export default function AdminCoupons() { const { toast } = useToast(); const queryClient = useQueryClient(); const [search, setSearch] = React.useState(""); const [debouncedSearch, setDebouncedSearch] = React.useState(""); const [page, setPage] = React.useState(1); const [editing, setEditing] = React.useState(null); const [open, setOpen] = React.useState(false); const [form, setForm] = React.useState(emptyForm); React.useEffect(() => { const timer = window.setTimeout(() => setDebouncedSearch(search.trim()), 300); return () => window.clearTimeout(timer); }, [search]); const query = useQuery({ queryKey: ["admin", "coupons", debouncedSearch, page], queryFn: () => api.listDiscountCodes({ search: debouncedSearch || undefined, limit: PAGE_SIZE, offset: (page - 1) * PAGE_SIZE }), }); const saveMutation = useMutation({ mutationFn: () => (editing ? api.updateDiscountCode(editing.id, form) : api.createDiscountCode(form)), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["admin", "coupons"] }); setOpen(false); toast({ title: "کد تخفیف ذخیره شد", variant: "success" }); }, onError: (error) => toast({ title: "خطا", description: resolveErrorMessage(error), variant: "destructive" }), }); const deleteMutation = useMutation({ mutationFn: (id: number) => api.deleteDiscountCode(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["admin", "coupons"] }); toast({ title: "کد تخفیف حذف شد", variant: "success" }); }, onError: (error) => toast({ title: "خطا", description: resolveErrorMessage(error), variant: "destructive" }), }); const openCreate = () => { setEditing(null); setForm(emptyForm); setOpen(true); }; const openEdit = (item: DiscountCodeSchema) => { setEditing(item); setForm({ code: item.code, type: item.type, value: item.value, max_discount: item.max_discount, is_active: item.is_active, starts_at: item.starts_at, ends_at: item.ends_at, usage_limit_total: item.usage_limit_total, usage_limit_per_user: item.usage_limit_per_user, min_amount: item.min_amount, applicable_event_ids: item.applicable_event_ids, }); setOpen(true); }; const items = query.data?.results ?? []; const count = query.data?.count ?? 0; const hasMore = page * PAGE_SIZE < count; return (

کدهای تخفیف

مدیریت کدهای تخفیف رویدادها

فهرست کدها جستجو و مدیریت وضعیت کدهای تخفیف { setSearch(event.target.value); setPage(1); }} placeholder="جستجو بر اساس کد..." className="max-w-md" />
{query.isLoading ? ( ) : items.length === 0 ? ( ) : ( items.map((item) => ( )) )}
کد نوع مقدار استفاده وضعیت
در حال بارگذاری...
کدی یافت نشد.
{item.code} {item.type === "percent" ? "درصدی" : "مبلغ ثابت"} {formatNumberPersian(item.value)} {formatNumberPersian(item.usage_count)} {item.is_active ? "فعال" : "غیرفعال"}
deleteMutation.mutate(item.id)} disabled={deleteMutation.isPending} trigger={ } />
صفحه {formatNumberPersian(page)} از {formatNumberPersian(Math.max(1, Math.ceil(count / PAGE_SIZE)))}
{editing ? "ویرایش کد تخفیف" : "افزودن کد تخفیف"}
setForm((current) => ({ ...current, code: event.target.value }))} />
setForm((current) => ({ ...current, value: Number(event.target.value) }))} />
setForm((current) => ({ ...current, max_discount: event.target.value ? Number(event.target.value) : null }))} />
setForm((current) => ({ ...current, min_amount: event.target.value ? Number(event.target.value) : null }))} />
setForm((current) => ({ ...current, usage_limit_total: event.target.value ? Number(event.target.value) : null }))} />
setForm((current) => ({ ...current, usage_limit_per_user: event.target.value ? Number(event.target.value) : null }))} />
setForm((current) => ({ ...current, is_active: checked }))} />
setForm((current) => ({ ...current, starts_at: value }))} /> setForm((current) => ({ ...current, ends_at: value }))} />
); }