Initial commit

This commit is contained in:
2026-10-05 20:38:28 +02:00
commit 60a68b420e
107 changed files with 21716 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useState } from "react";
import { playlistsApi } from "../lib/api";
import { Modal } from "./Modal";
export function CreatePlaylistModal({
open,
onClose,
onCreated,
}: {
open: boolean;
onClose: () => void;
onCreated?: (id: string) => void;
}) {
const qc = useQueryClient();
const [form, setForm] = useState<{
title: string;
description: string;
visibility: "public" | "unlisted" | "private";
}>({ title: "", description: "", visibility: "private" });
const [error, setError] = useState("");
const create = useMutation({
mutationFn: () =>
playlistsApi.create({
title: form.title,
description: form.description || null,
visibility: form.visibility,
}),
onSuccess: (pl) => {
void qc.invalidateQueries({ queryKey: ["library"] });
void qc.invalidateQueries({ queryKey: ["my-playlists"] });
setForm({ title: "", description: "", visibility: "private" });
onCreated?.(pl.id);
onClose();
},
onError: (e: any) => setError(e?.response?.data?.error ?? "Ошибка"),
});
return (
<Modal open={open} onClose={onClose} title="Новый плейлист">
<div className="space-y-3">
<div>
<label className="label">Название</label>
<input
className="input"
autoFocus
value={form.title}
onChange={(e) => setForm({ ...form, title: e.target.value })}
placeholder="Мой плейлист"
/>
</div>
<div>
<label className="label">Описание</label>
<textarea
className="input min-h-20"
value={form.description}
onChange={(e) => setForm({ ...form, description: e.target.value })}
/>
</div>
<div>
<label className="label">Доступ</label>
<select
className="input"
value={form.visibility}
onChange={(e) => setForm({ ...form, visibility: e.target.value as typeof form.visibility })} >
<option value="private">Приватный</option>
<option value="unlisted">По ссылке</option>
<option value="public">Публичный</option>
</select>
</div>
{error && <p className="text-sm text-red-300">{error}</p>}
<button
className="btn-primary w-full"
onClick={() => create.mutate()}
disabled={!form.title.trim() || create.isPending}
>
Создать
</button>
</div>
</Modal>
);
}