Initial commit
This commit is contained in:
83
apps/web/src/components/CreatePlaylistModal.tsx
Normal file
83
apps/web/src/components/CreatePlaylistModal.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user