84 lines
2.6 KiB
TypeScript
84 lines
2.6 KiB
TypeScript
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>
|
||
);
|
||
}
|