feat: add playlist

This commit is contained in:
2026-06-11 12:00:39 +03:30
parent 7c6d16693c
commit e374829358
+44 -5
View File
@@ -20,6 +20,14 @@ import { MediaPreview } from "@/components/MediaPreview";
import { ImagePicker } from "@/components/ImagePicker"; import { ImagePicker } from "@/components/ImagePicker";
import { pickUrl, SOUND_KEYS, IMAGE_KEYS } from "@/lib/media"; import { pickUrl, SOUND_KEYS, IMAGE_KEYS } from "@/lib/media";
interface Playlist {
id: number;
name?: string;
// Some endpoints nest the playlist's sub-categories; key casing varies.
subcategories?: Playlist[];
subCategories?: Playlist[];
}
interface Track { interface Track {
id: number; id: number;
title?: string; title?: string;
@@ -28,11 +36,12 @@ interface Track {
type?: string; type?: string;
playlist_id?: number; playlist_id?: number;
image_id?: number | null; image_id?: number | null;
} // A track belongs to many playlists; the /music row embeds them as an array.
playlists?: Playlist[];
interface Playlist { // Sub-categories may also be embedded directly on the track (key casing varies).
id: number; subcategories?: Playlist[];
name?: string; subCategories?: Playlist[];
sub_categories?: Playlist[];
} }
export default function MusicTracksPage() { export default function MusicTracksPage() {
@@ -56,6 +65,26 @@ export default function MusicTracksPage() {
const [deleting, setDeleting] = useState<Track | null>(null); const [deleting, setDeleting] = useState<Track | null>(null);
const [removing, setRemoving] = useState(false); const [removing, setRemoving] = useState(false);
// A track belongs to many playlists — list their names.
function playlistName(r: Track): string {
const names = (r.playlists ?? []).map((p) => p.name).filter(Boolean);
return names.length ? (names as string[]).join("، ") : "—";
}
// Sub-categories may sit on the track directly or come through its playlists;
// key casing varies between endpoints, so gather from every shape.
function subCategoryNames(r: Track): string {
const subs: Playlist[] = [
...(r.subcategories ?? r.subCategories ?? r.sub_categories ?? []),
...(r.playlists ?? []).flatMap(
(p) => p.subcategories ?? p.subCategories ?? [],
),
];
const names = subs.map((s) => s.name).filter(Boolean) as string[];
const unique = Array.from(new Set(names));
return unique.length ? unique.join("، ") : "—";
}
function resetForm() { function resetForm() {
setTitle(""); setTitle("");
setArtist(""); setArtist("");
@@ -163,6 +192,16 @@ export default function MusicTracksPage() {
}, },
{ key: "title", header: "عنوان" }, { key: "title", header: "عنوان" },
{ key: "artist", header: "هنرمند", render: (r) => r.artist ?? "—" }, { key: "artist", header: "هنرمند", render: (r) => r.artist ?? "—" },
{
key: "playlist",
header: "پلی‌لیست",
render: (r) => playlistName(r),
},
{
key: "subcategory",
header: "زیر‌دسته",
render: (r) => subCategoryNames(r),
},
{ {
key: "duration", key: "duration",
header: "مدت زمان", header: "مدت زمان",