"use client"; import { useCallback, useEffect, useState } from "react"; interface Campaign { id: string; name: string; channel: string; audience: string; subject?: string | null; body_html?: string | null; template_code?: string | null; status: string; total_count: number; sent_count: number; failed_count: number; created_at: string; } const card = "rounded-xl border border-[#1e2235] bg-[#0f1120] p-5"; const btn = "rounded-lg bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-500 disabled:opacity-50"; const ghost = "rounded-lg border border-[#262b40] px-3 py-1.5 text-xs text-gray-300 hover:bg-[#161a2e] disabled:opacity-50"; const inp = "w-full rounded-lg border border-[#262b40] bg-[#0c0e1a] px-3 py-2 text-sm text-gray-100 outline-none focus:border-indigo-500"; const lbl = "mb-1 block text-xs font-medium text-gray-400"; const empty = { name: "", channel: "email", audience: "all", subject: "", body_html: "", template_code: "" }; export function MarketingAdmin() { const [rows, setRows] = useState([]); const [form, setForm] = useState({ ...empty }); const [saving, setSaving] = useState(false); const [busy, setBusy] = useState(null); const [msg, setMsg] = useState(null); const reload = useCallback(async () => { const r = await fetch("/api/admin/resource/campaigns", { cache: "no-store" }).then((x) => x.json()).catch(() => null); setRows(r?.data ?? (Array.isArray(r) ? r : [])); }, []); useEffect(() => { reload(); }, [reload]); const create = async () => { setSaving(true); setMsg(null); const res = await fetch("/api/admin/resource/campaigns", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: form.name, channel: form.channel, audience: form.audience, subject: form.subject || null, body_html: form.body_html || null, template_code: form.template_code || null, }), }); const d = await res.json().catch(() => null); setMsg(res.ok ? "کمپین ساخته شد ✓" : (d?.error ?? "خطا")); setSaving(false); if (res.ok) { setForm({ ...empty }); reload(); } }; const send = async (camp: Campaign) => { if (!confirm(`ارسال کمپین «${camp.name}» به مخاطبان؟`)) return; setBusy(camp.id); setMsg(null); const res = await fetch(`/api/admin/resource/campaigns/${camp.id}/send`, { method: "POST", headers: { "Content-Type": "application/json" }, body: "{}" }); const d = await res.json().catch(() => null); setMsg(res.ok ? `ارسال شد: ${d.sent}/${d.total} (ناموفق ${d.failed})` : (d?.error ?? "ارسال ناموفق")); setBusy(null); reload(); }; const remove = async (camp: Campaign) => { if (!confirm(`حذف کمپین «${camp.name}»؟`)) return; const res = await fetch(`/api/admin/resource/campaigns/${camp.id}`, { method: "DELETE" }); if (res.ok) reload(); }; const statusBadge = (s: string) => { const map: Record = { Sent: "bg-emerald-500/15 text-emerald-300", Sending: "bg-amber-500/15 text-amber-300", Failed: "bg-red-500/15 text-red-300", Draft: "bg-gray-500/15 text-gray-400", }; return {s}; }; return (

Marketing — Campaigns

ارسال پیامک/ایمیل به گروهی از کاربران از طریق کانال‌های پیکربندی‌شده.

{msg &&

{msg}

}

کمپین جدید

setForm({ ...form, name: e.target.value })} />
{form.channel === "email" && (
setForm({ ...form, template_code: e.target.value })} />
)} {form.channel === "email" && (
setForm({ ...form, subject: e.target.value })} />
)}