import { useState } from "react"; import { Plus, Pencil, Trash2, X, Ban } from "lucide-react"; import { useNotificationsOverview, useNotificationTypes, useNotifications, useSmsBlacklist, useNotificationTypeCreate, useNotificationTypeUpdate, useNotificationTypeDelete, useSmsBlacklistDelete, type NotificationTypeRow, type NotificationRow, type SmsBlacklistRow, } from "~/requestHandler/use-admin-hooks"; import { AdminTable, AdminPagination, AdminToolbar, AdminSearch, AdminSelect, AdminPageTitle, StatusBadge, faNum, faDate, useDebouncedValue, type Column, } from "~/components/admin/DataTable"; import { KpiCard } from "~/components/admin/KpiCard"; import { cn } from "~/lib/utils"; const PAGE_SIZE = 25; export default function AdminNotifications() { const [tab, setTab] = useState<"types" | "sent" | "blacklist">("types"); const TABS = [ { k: "types", label: "قالب‌ها" }, { k: "sent", label: "ارسال‌ها" }, { k: "blacklist", label: "لیست سیاه" }, ] as const; return (
اعلان‌ها
{TABS.map((t) => ( ))}
{tab === "types" && } {tab === "sent" && } {tab === "blacklist" && }
); } /* ------------------------------- templates ------------------------------- */ function TypesTab() { const [page, setPage] = useState(1); const [search, setSearch] = useState(""); const [editing, setEditing] = useState(null); const [creating, setCreating] = useState(false); const debouncedSearch = useDebouncedValue(search); const { data, isLoading } = useNotificationTypes({ page, page_size: PAGE_SIZE, search: debouncedSearch }); const del = useNotificationTypeDelete(); const columns: Column[] = [ { header: "عنوان", render: (r) => (

{r.title}

{r.code}

), }, { header: "کانال‌ها", render: (r) => (
{r.defaultInApp && } {r.defaultSms && }
), }, { header: "قالب", render: (r) => ( {r.template || "—"} ), }, { header: "", render: (r) => (
), }, ]; return (
{ setSearch(v); setPage(1); }} placeholder="جستجوی کد / عنوان…" /> String(r.id)} emptyText="قالبی ثبت نشده است" /> {(creating || editing) && ( { setCreating(false); setEditing(null); }} /> )}
); } function TypeModal({ row, onClose }: { row: NotificationTypeRow | null; onClose: () => void }) { const [code, setCode] = useState(row?.code ?? ""); const [title, setTitle] = useState(row?.title ?? ""); const [defaultSms, setDefaultSms] = useState(row?.defaultSms ?? false); const [defaultInApp, setDefaultInApp] = useState(row?.defaultInApp ?? true); const [template, setTemplate] = useState(row?.template ?? ""); const [variables, setVariables] = useState((row?.variables ?? []).join(", ")); const [error, setError] = useState(""); const create = useNotificationTypeCreate(); const update = useNotificationTypeUpdate(); const busy = create.isPending || update.isPending; const submit = () => { setError(""); if (!code || !title) return setError("کد و عنوان الزامی است."); const payload = { code, title, defaultSms, defaultInApp, template, variables: variables.split(/[,\s]+/).map((s) => s.trim()).filter(Boolean), }; const onErr = (e: unknown) => setError(e instanceof Error ? e.message : "خطا در ذخیره"); if (row) update.mutate({ id: row.id, data: payload }, { onSuccess: onClose, onError: onErr }); else create.mutate(payload, { onSuccess: onClose, onError: onErr }); }; return (
e.stopPropagation()}>

{row ? "ویرایش قالب" : "قالب جدید"}

setCode(e.target.value)} dir="ltr" />
setTitle(e.target.value)} />