Added Draft Melodies. Further improvements to the UI

This commit is contained in:
2026-02-18 19:33:59 +02:00
parent a6e0b1d46e
commit aad8942d65
12 changed files with 1080 additions and 518 deletions

View File

@@ -32,6 +32,8 @@ export default function MelodyDetail() {
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
const [showDelete, setShowDelete] = useState(false);
const [showUnpublish, setShowUnpublish] = useState(false);
const [actionLoading, setActionLoading] = useState(false);
const [displayLang, setDisplayLang] = useState("en");
const [melodySettings, setMelodySettings] = useState(null);
@@ -72,6 +74,32 @@ export default function MelodyDetail() {
}
};
const handlePublish = async () => {
setActionLoading(true);
try {
await api.post(`/melodies/${id}/publish`);
await loadData();
} catch (err) {
setError(err.message);
} finally {
setActionLoading(false);
}
};
const handleUnpublish = async () => {
setActionLoading(true);
try {
await api.post(`/melodies/${id}/unpublish`);
setShowUnpublish(false);
await loadData();
} catch (err) {
setError(err.message);
setShowUnpublish(false);
} finally {
setActionLoading(false);
}
};
if (loading) {
return <div className="text-center py-8" style={{ color: "var(--text-muted)" }}>Loading...</div>;
}
@@ -116,6 +144,15 @@ export default function MelodyDetail() {
</button>
<div className="flex items-center gap-3">
<h1 className="text-2xl font-bold" style={{ color: "var(--text-heading)" }}>{displayName}</h1>
<span
className="px-2.5 py-0.5 text-xs font-semibold rounded-full"
style={melody.status === "published"
? { backgroundColor: "rgba(22,163,74,0.15)", color: "#22c55e" }
: { backgroundColor: "rgba(156,163,175,0.15)", color: "#9ca3af" }
}
>
{melody.status === "published" ? "LIVE" : "DRAFT"}
</span>
{languages.length > 1 && (
<select
value={displayLang}
@@ -133,6 +170,25 @@ export default function MelodyDetail() {
</div>
{canEdit && (
<div className="flex gap-2">
{melody.status === "draft" ? (
<button
onClick={handlePublish}
disabled={actionLoading}
className="px-4 py-2 text-sm rounded-md transition-colors disabled:opacity-50"
style={{ backgroundColor: "#16a34a", color: "#fff" }}
>
{actionLoading ? "Publishing..." : "Publish"}
</button>
) : (
<button
onClick={() => setShowUnpublish(true)}
disabled={actionLoading}
className="px-4 py-2 text-sm rounded-md transition-colors disabled:opacity-50"
style={{ backgroundColor: "#ea580c", color: "#fff" }}
>
Unpublish
</button>
)}
<button
onClick={() => navigate(`/melodies/${id}/edit`)}
className="px-4 py-2 text-sm rounded-md transition-colors"
@@ -326,6 +382,14 @@ export default function MelodyDetail() {
onConfirm={handleDelete}
onCancel={() => setShowDelete(false)}
/>
<ConfirmDialog
open={showUnpublish}
title="Unpublish Melody"
message={`This melody may be in use by devices. Unpublishing will remove it from Firestore and devices will no longer have access to "${displayName}". The melody will be kept as a draft. Continue?`}
onConfirm={handleUnpublish}
onCancel={() => setShowUnpublish(false)}
/>
</div>
);
}