v3: code quality pass

This commit is contained in:
khannurien
2026-03-24 18:47:05 +00:00
parent cd4076343b
commit c293f3e706
39 changed files with 1464 additions and 1555 deletions

View File

@@ -1,10 +1,10 @@
import { useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { useEffect, useState } from "react";
import { API_URL } from "../config/api.ts";
import { useAuth } from "../hooks/useAuth.ts";
import type { PlaylistMembership, RawPlaylistMembership } from "../model.ts";
import { deserializePlaylistMembership } from "../model.ts";
import { PlaylistCreateForm } from "./PlaylistCreateForm.tsx";
import { Modal } from "./Modal.tsx";
import { PlaylistMembershipPanel } from "./PlaylistMembershipPanel.tsx";
interface AddToPlaylistModalProps {
dumpId: string;
@@ -17,23 +17,6 @@ export function AddToPlaylistModal(
const { authFetch } = useAuth();
const [memberships, setMemberships] = useState<PlaylistMembership[]>([]);
const [loading, setLoading] = useState(true);
const [showNewForm, setShowNewForm] = useState(false);
const backdropRef = useRef<HTMLDivElement>(null);
useEffect(() => {
document.body.style.overflow = "hidden";
return () => {
document.body.style.overflow = "";
};
}, []);
useEffect(() => {
const handler = (e: KeyboardEvent) => {
if (e.key === "Escape") onClose();
};
document.addEventListener("keydown", handler);
return () => document.removeEventListener("keydown", handler);
}, [onClose]);
useEffect(() => {
authFetch(`${API_URL}/api/playlists/by-dump/${dumpId}/memberships`)
@@ -76,84 +59,16 @@ export function AddToPlaylistModal(
}
};
return createPortal(
<div
className="modal-backdrop"
ref={backdropRef}
onClick={(e) => {
if (e.target === backdropRef.current) onClose();
}}
>
<div className="modal-card">
<div className="modal-header">
<span className="modal-title">Add to playlist</span>
<button
type="button"
className="modal-close-btn"
onClick={onClose}
aria-label="Close"
>
✕
</button>
</div>
<div className="modal-body">
{loading
? <p className="page-loading">Loading…</p>
: memberships.length === 0 && !showNewForm
? <p className="empty-state">No playlists yet.</p>
: (
<ul className="playlist-membership-list">
{memberships.map((m) => (
<li
key={m.playlist.id}
className={`playlist-membership-row${
m.hasDump ? " playlist-membership-row--active" : ""
}`}
onClick={() => toggleMembership(m)}
>
<span className="playlist-membership-check">
{m.hasDump ? "✓" : "○"}
</span>
<span className="playlist-membership-name">
{m.playlist.title}
</span>
{!m.playlist.isPublic && (
<span className="playlist-badge playlist-badge--private">
private
</span>
)}
</li>
))}
</ul>
)}
{showNewForm
? (
<PlaylistCreateForm
dumpId={dumpId}
onCreated={(playlist) => {
setMemberships((prev) => [
{ playlist, hasDump: true },
...prev,
]);
setShowNewForm(false);
}}
onCancel={() => setShowNewForm(false)}
/>
)
: (
<button
type="button"
className="modal-new-playlist-toggle"
onClick={() => setShowNewForm(true)}
>
+ New playlist
</button>
)}
</div>
</div>
</div>,
document.body,
return (
<Modal title="Add to playlist" onClose={onClose}>
<PlaylistMembershipPanel
dumpId={dumpId}
memberships={memberships}
loading={loading}
onToggle={toggleMembership}
onPlaylistCreated={(membership) =>
setMemberships((prev) => [membership, ...prev])}
/>
</Modal>
);
}