Added Draft Melodies. Further improvements to the UI
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user