"use client"; import { useState } from "react"; import { apiFetch, ApiError, toFormData } from "@/lib/api"; import { useList } from "@/lib/useResource"; import { useToast } from "@/components/toast"; import { DataTable, type Column } from "@/components/DataTable"; import { Button, ConfirmDialog, Field, Input, Modal, PageHeader, Textarea, } from "@/components/ui"; import { EditIcon, PlusIcon, TrashIcon } from "@/components/icons"; import { toFa } from "@/lib/utils"; import { MediaPreview } from "@/components/MediaPreview"; import { ImagePicker } from "@/components/ImagePicker"; import { pickUrl, IMAGE_KEYS } from "@/lib/media"; interface Announcement { id: number; title?: string; description?: string; link?: string; start_date?: string | null; end_date?: string | null; image_id?: number | null; image?: unknown; } // Datetime ISO string -> "YYYY-MM-DD" for a . function toDateInput(value?: string | null): string { return value ? value.slice(0, 10) : ""; } // "YYYY-MM-DD" Gregorian -> Persian display, or "—". function toFaDate(value?: string | null): string { if (!value) return "—"; const d = value.slice(0, 10); try { return new Intl.DateTimeFormat("fa-IR").format(new Date(d)); } catch { return d; } } export default function AnnouncementsPage() { const { data, loading, error, reload } = useList("/announcements"); const toast = useToast(); const [editing, setEditing] = useState(null); const [open, setOpen] = useState(false); const [title, setTitle] = useState(""); const [description, setDescription] = useState(""); const [link, setLink] = useState(""); const [startDate, setStartDate] = useState(""); const [endDate, setEndDate] = useState(""); const [imageId, setImageId] = useState(null); const [imageFile, setImageFile] = useState(null); const [saving, setSaving] = useState(false); const [deleting, setDeleting] = useState(null); const [removing, setRemoving] = useState(false); function openCreate() { setEditing(null); setTitle(""); setDescription(""); setLink(""); setStartDate(""); setEndDate(""); setImageId(null); setImageFile(null); setOpen(true); } function openEdit(row: Announcement) { setEditing(row); setTitle(row.title ?? ""); setDescription(row.description ?? ""); setLink(row.link ?? ""); setStartDate(toDateInput(row.start_date)); setEndDate(toDateInput(row.end_date)); setImageId(row.image_id ?? null); setImageFile(null); setOpen(true); } async function save(e: React.FormEvent) { e.preventDefault(); setSaving(true); try { // Multipart (the image is a file). Edit posts to /announcements/:id, // which the backend also accepts as a multipart update. const body = toFormData({ title, description, link, start_date: startDate, end_date: endDate, image_id: imageId, image: imageFile, }); if (editing) { await apiFetch(`/announcements/${editing.id}`, { method: "POST", body }); toast.success("اعلان ویرایش شد."); } else { await apiFetch("/announcements", { method: "POST", body }); toast.success("اعلان افزوده شد."); } setOpen(false); reload(); } catch (err) { toast.error(err instanceof ApiError ? err.message : "خطا در ذخیرهسازی"); } finally { setSaving(false); } } async function confirmDelete() { if (!deleting) return; setRemoving(true); try { await apiFetch(`/announcements/${deleting.id}`, { method: "DELETE" }); toast.success("اعلان حذف شد."); setDeleting(null); reload(); } catch (err) { toast.error(err instanceof ApiError ? err.message : "خطا در حذف"); } finally { setRemoving(false); } } const columns: Column[] = [ { key: "id", header: "شناسه", render: (r) => toFa(r.id), className: "w-20" }, { key: "thumbnail", header: "تصویر", className: "w-20", render: (r) => ( ), }, { key: "title", header: "عنوان", render: (r) => r.title ?? "—" }, { key: "link", header: "لینک", render: (r) => r.link ? ( {r.link} ) : ( "—" ), }, { key: "start_date", header: "تاریخ شروع", render: (r) => toFaDate(r.start_date), className: "w-32", }, { key: "end_date", header: "تاریخ پایان", render: (r) => toFaDate(r.end_date), className: "w-32", }, ]; return ( } onClick={openCreate}> اعلان جدید } /> } onClick={openCreate}> اعلان جدید } actions={(row) => ( <> openEdit(row)} aria-label="ویرایش"> setDeleting(row)} aria-label="حذف" className="text-danger" > > )} /> setOpen(false)} title={editing ? "ویرایش اعلان" : "اعلان جدید"} footer={ <> setOpen(false)}> انصراف ذخیره > } > setTitle(e.target.value)} placeholder="مثلاً تخفیف ویژه نوروز" required autoFocus /> setDescription(e.target.value)} placeholder="توضیح کوتاه درباره اعلان" /> setLink(e.target.value)} placeholder="https://" dir="ltr" /> setStartDate(e.target.value)} dir="ltr" /> setEndDate(e.target.value)} dir="ltr" /> setDeleting(null)} /> ); }