"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, Select, Textarea, Badge, Switch, } from "@/components/ui"; import { EditIcon, PlusIcon, TrashIcon } from "@/components/icons"; import { MediaPreview } from "@/components/MediaPreview"; import { ImagePicker } from "@/components/ImagePicker"; import { pickUrl, SOUND_KEYS, VIDEO_KEYS, IMAGE_KEYS } from "@/lib/media"; import { formatMinutes, fileNameToTitle } from "@/lib/utils"; interface Cat { id: number; name?: string; } interface Media { id: number; title?: string; caption?: string; type?: string; duration?: number; visibility?: string; is_deeplink_only?: boolean; is_premium?: boolean; external_url?: string | null; deep_link?: string | null; image_id?: number | null; image?: unknown; detail_image_id?: number | null; detail_image?: unknown; categories?: Cat[]; sub_categories?: Cat[]; subcategories?: Cat[]; subCategories?: Cat[]; } function DeepLink({ deep_link }: { deep_link?: string | null }) { return (
{deep_link ? ( {deep_link} ) : ( — )}
); } export default function MediaDeepLinksPage() { const { data, loading, error, reload } = useList("/media", { deeplink_only: 1, }); const { data: allMedia, loading: allLoading } = useList("/media", { count: 500, }); const toast = useToast(); const [editing, setEditing] = useState(null); const [open, setOpen] = useState(false); const [saving, setSaving] = useState(false); // Source: 'new' (upload / external url) or 'existing' (pick a media record). const [source, setSource] = useState<"new" | "existing">("new"); const [existingId, setExistingId] = useState(""); // Fields for creating a new hidden media. const [title, setTitle] = useState(""); const [caption, setCaption] = useState(""); const [type, setType] = useState("audio"); const [duration, setDuration] = useState(""); const [file, setFile] = useState(null); const [externalUrl, setExternalUrl] = useState(""); const [imageId, setImageId] = useState(null); const [imageFile, setImageFile] = useState(null); const [deleting, setDeleting] = useState(null); const [removing, setRemoving] = useState(false); function resetForm() { setSource("new"); setExistingId(""); setTitle(""); setCaption(""); setType("audio"); setDuration(""); setFile(null); setExternalUrl(""); setImageId(null); setImageFile(null); } function openCreate() { setEditing(null); resetForm(); setOpen(true); } async function toggleHidden(row: Media) { try { await apiFetch(`/media/${row.id}`, { method: "POST", body: toFormData({ is_deeplink_only: !row.is_deeplink_only ? 1 : 0, }), }); toast.success( row.is_deeplink_only ? "از لینک مستقیم خارج شد." : "به لینک مستقیم تبدیل شد.", ); reload(); } catch (err) { toast.error(err instanceof ApiError ? err.message : "خطا در ذخیره‌سازی"); } } async function save(e: React.FormEvent) { e.preventDefault(); setSaving(true); try { if (editing) { setOpen(false); reload(); toast.success("لینک مستقیم بهروزرسانی شد."); return; } if (source === "existing") { // Toggle the chosen existing media to deeplink-only. if (!existingId) { toast.error("رسانهای را انتخاب کنید."); return; } await apiFetch(`/media/${existingId}`, { method: "POST", body: toFormData({ is_deeplink_only: 1 }), }); toast.success("رسانه به لینک مستقیم تبدیل شد."); } else { // Create a brand new hidden media (upload / external url). const body = toFormData({ title, caption, type, duration, file, external_url: externalUrl, image_id: imageId, image: imageFile, is_deeplink_only: true, }); await apiFetch("/media", { 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(`/media/${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) => r.type === "video" ? ( ) : ( ), }, { key: "thumbnail", header: "تصویر", className: "w-20", render: (r) => ( ), }, { key: "title", header: "عنوان", render: (r) => r.title ?? "—" }, { key: "deep_link", header: "لینک مستقیم", render: (r) => , }, { key: "duration", header: "مدت", render: (r) => formatMinutes(r.duration), }, ]; return (
} onClick={openCreate}> لینک مستقیم جدید } /> } onClick={openCreate}> لینک مستقیم جدید } actions={(row) => ( <> )} /> setOpen(false)} title="لینک مستقیم رسانه جدید" footer={ <> } >