"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, Select, Modal, PageHeader, } from "@/components/ui"; import { EditIcon, PlusIcon, TrashIcon } from "@/components/icons"; import { toFa, formatDuration } from "@/lib/utils"; import { MediaPreview } from "@/components/MediaPreview"; import { pickUrl, SOUND_KEYS, IMAGE_KEYS } from "@/lib/media"; interface Track { id: number; title?: string; artist?: string; duration?: number | null; type?: string; order?: number; playlist_id?: number; } interface Playlist { id: number; name?: string; } export default function MusicTracksPage() { const { data, loading, error, reload } = useList("/music"); const { data: playlists } = useList("/music-playlists"); const toast = useToast(); const [editing, setEditing] = useState(null); const [open, setOpen] = useState(false); const [saving, setSaving] = useState(false); const [title, setTitle] = useState(""); const [artist, setArtist] = useState(""); const [type, setType] = useState(""); const [duration, setDuration] = useState(""); const [playlistId, setPlaylistId] = useState(""); const [imageId, setImageId] = useState(""); const [order, setOrder] = useState(""); const [file, setFile] = useState(null); const [deleting, setDeleting] = useState(null); const [removing, setRemoving] = useState(false); function openCreate() { setEditing(null); setTitle(""); setArtist(""); setType(""); setDuration(""); setPlaylistId(""); setImageId(""); setOrder(""); setFile(null); setOpen(true); } function openEdit(row: Track) { setEditing(row); setTitle(row.title ?? ""); setArtist(row.artist ?? ""); setType(row.type ?? ""); setDuration(row.duration != null ? String(row.duration) : ""); setPlaylistId(row.playlist_id != null ? String(row.playlist_id) : ""); setImageId(""); setOrder(row.order != null ? String(row.order) : ""); setFile(null); setOpen(true); } async function save(e: React.FormEvent) { e.preventDefault(); setSaving(true); try { if (editing) { // Update is JSON on /music/:id await apiFetch(`/music/${editing.id}`, { method: "PUT", body: { title, artist, order: order === "" ? undefined : Number(order), }, }); toast.success("آهنگ ویرایش شد."); } else { // Create is multipart on /music await apiFetch("/music", { method: "POST", body: toFormData({ title, artist, type, duration, playlist_id: playlistId, image_id: imageId, file, }), }); 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(`/music/${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: "play", header: "پخش", className: "w-20", render: (r) => ( ), }, { key: "thumbnail", header: "تصویر", className: "w-20", render: (r) => ( ), }, { key: "title", header: "عنوان" }, { key: "artist", header: "هنرمند", render: (r) => r.artist ?? "—" }, { key: "duration", header: "مدت زمان", render: (r) => formatDuration(r.duration), }, { key: "type", header: "نوع", render: (r) => r.type ?? "—" }, ]; return (
} onClick={openCreate}> آهنگ جدید } /> } onClick={openCreate}> آهنگ جدید } actions={(row) => ( <> )} /> setOpen(false)} title={editing ? "ویرایش آهنگ" : "آهنگ جدید"} footer={ <> } >
setTitle(e.target.value)} placeholder="مثلاً آرامش شبانه" required autoFocus /> setArtist(e.target.value)} placeholder="نام هنرمند" /> {editing ? ( setOrder(e.target.value)} dir="ltr" /> ) : ( <> setType(e.target.value)} placeholder="مثلاً music" /> setDuration(e.target.value)} dir="ltr" /> setImageId(e.target.value)} dir="ltr" placeholder="image_id" /> setFile(e.target.files?.[0] ?? null)} required /> )}
setDeleting(null)} />
); }