"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, Badge, } from "@/components/ui"; import { EditIcon, PlusIcon, TrashIcon } from "@/components/icons"; import { toFa } from "@/lib/utils"; interface Question { id: number; title?: string; category?: string; tags?: string[] | string; } function asTags(value: Question["tags"]): string[] { if (Array.isArray(value)) return value.map((t) => String(t)); if (typeof value === "string" && value.trim() !== "") { return value .split(",") .map((t) => t.trim()) .filter(Boolean); } return []; } function parseTagsInput(input: string): string[] { // Accept both Latin "," and Persian "،" separators. return input .split(/[,،]/) .map((t) => t.trim()) .filter(Boolean); } export default function QuestionsPage() { const [filterTag, setFilterTag] = useState(""); const [filterCategory, setFilterCategory] = useState(""); const { data, loading, error, reload } = useList("/questions", { tag: filterTag || undefined, category: filterCategory || undefined, }); const toast = useToast(); const [editing, setEditing] = useState(null); const [open, setOpen] = useState(false); const [title, setTitle] = useState(""); const [category, setCategory] = useState(""); const [tagsInput, setTagsInput] = useState(""); const [saving, setSaving] = useState(false); const [deleting, setDeleting] = useState(null); const [removing, setRemoving] = useState(false); function openCreate() { setEditing(null); setTitle(""); setCategory(""); setTagsInput(""); setOpen(true); } function openEdit(row: Question) { setEditing(row); setTitle(row.title ?? ""); setCategory(row.category ?? ""); setTagsInput(asTags(row.tags).join("، ")); setOpen(true); } async function save(e: React.FormEvent) { e.preventDefault(); setSaving(true); try { const tags = parseTagsInput(tagsInput); if (editing) { // Update is JSON on /questions/:id await apiFetch(`/questions/${editing.id}`, { method: "PUT", body: { title, category, tags }, }); toast.success("پرسش ویرایش شد."); } else { // Create is multipart on /questions (toFormData expands tags -> tags[]) await apiFetch("/questions", { method: "POST", body: toFormData({ title, category, tags }), }); 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(`/questions/${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: "title", header: "عنوان", render: (r) => r.title ?? "—" }, { key: "category", header: "دسته", render: (r) => r.category ?? "—" }, { key: "tags", header: "برچسب‌ها", render: (r) => { const tags = asTags(r.tags); return tags.length ? (
{tags.map((t, i) => ( {t} ))}
) : ( ); }, }, ]; return (
} onClick={openCreate}> پرسش جدید } />
setFilterTag(e.target.value)} placeholder="مثلاً انگیزشی" /> setFilterCategory(e.target.value)} placeholder="مثلاً صبحگاهی" />
} onClick={openCreate}> پرسش جدید } actions={(row) => ( <> )} /> setOpen(false)} title={editing ? "ویرایش پرسش" : "پرسش جدید"} footer={ <> } >
setTitle(e.target.value)} placeholder="متن پرسش" required autoFocus /> setCategory(e.target.value)} placeholder="مثلاً صبحگاهی" /> setTagsInput(e.target.value)} placeholder="انگیزشی، آرامش، تمرکز" />
setDeleting(null)} />
); }