"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 AppVersion { id: number; title?: string; description?: string; version_name?: string; version_code?: number; link?: string; button_text?: string; image_id?: number | null; image?: unknown; } export default function VersionsPage() { const { data, loading, error, reload } = useList("/versions"); const toast = useToast(); const [editing, setEditing] = useState(null); const [open, setOpen] = useState(false); const [title, setTitle] = useState(""); const [description, setDescription] = useState(""); const [versionName, setVersionName] = useState(""); const [versionCode, setVersionCode] = useState(""); const [link, setLink] = useState(""); const [buttonText, setButtonText] = 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(""); setVersionName(""); setVersionCode(""); setLink(""); setButtonText(""); setImageId(null); setImageFile(null); setOpen(true); } function openEdit(row: AppVersion) { setEditing(row); setTitle(row.title ?? ""); setDescription(row.description ?? ""); setVersionName(row.version_name ?? ""); setVersionCode(row.version_code != null ? String(row.version_code) : ""); setLink(row.link ?? ""); setButtonText(row.button_text ?? ""); 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 /versions/:id, which the // backend also accepts as a multipart update. const body = toFormData({ title, description, version_name: versionName, version_code: versionCode, link, button_text: buttonText, image_id: imageId, image: imageFile, }); if (editing) { await apiFetch(`/versions/${editing.id}`, { method: "POST", body }); toast.success("نسخه ویرایش شد."); } else { await apiFetch("/versions", { 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(`/versions/${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: "version_name", header: "نام نسخه", render: (r) => ( {r.version_name ?? "—"} ), className: "w-28", }, { key: "version_code", header: "کد نسخه", render: (r) => (r.version_code != null ? toFa(r.version_code) : "—"), className: "w-24", }, { key: "link", header: "لینک", render: (r) => r.link ? ( {r.link} ) : ( "—" ), }, ]; return (
} onClick={openCreate}> نسخه جدید } /> } onClick={openCreate}> نسخه جدید } actions={(row) => ( <> )} /> setOpen(false)} title={editing ? "ویرایش نسخه" : "نسخه جدید"} footer={ <> } >
setTitle(e.target.value)} placeholder="مثلاً نسخه ۱.۲.۰" required autoFocus />