Phase 2 UI Adjustments/Edits by bonamin

This commit is contained in:
2026-02-17 09:56:07 +02:00
parent 2b48426fe5
commit 59c5049305
16 changed files with 1588 additions and 609 deletions

View File

@@ -5,6 +5,7 @@ import { useAuth } from "../auth/AuthContext";
import SearchBar from "../components/SearchBar";
import DataTable from "../components/DataTable";
import ConfirmDialog from "../components/ConfirmDialog";
import { getLocalizedValue, getLanguageName } from "./melodyUtils";
const MELODY_TYPES = ["", "orthodox", "catholic", "all"];
const MELODY_TONES = ["", "normal", "festive", "cheerful", "lamentation"];
@@ -17,11 +18,20 @@ export default function MelodyList() {
const [search, setSearch] = useState("");
const [typeFilter, setTypeFilter] = useState("");
const [toneFilter, setToneFilter] = useState("");
const [displayLang, setDisplayLang] = useState("en");
const [melodySettings, setMelodySettings] = useState(null);
const [deleteTarget, setDeleteTarget] = useState(null);
const navigate = useNavigate();
const { hasRole } = useAuth();
const canEdit = hasRole("superadmin", "melody_editor");
useEffect(() => {
api.get("/settings/melody").then((ms) => {
setMelodySettings(ms);
setDisplayLang(ms.primary_language || "en");
});
}, []);
const fetchMelodies = async () => {
setLoading(true);
setError("");
@@ -57,13 +67,17 @@ export default function MelodyList() {
}
};
const getDisplayName = (nameDict) => {
return getLocalizedValue(nameDict, displayLang, "Untitled");
};
const columns = [
{
key: "name",
label: "Name",
render: (row) => (
<span className="font-medium text-gray-900">
{row.information?.name || "Untitled"}
{getDisplayName(row.information?.name)}
</span>
),
},
@@ -133,6 +147,8 @@ export default function MelodyList() {
: []),
];
const languages = melodySettings?.available_languages || ["en"];
return (
<div>
<div className="flex items-center justify-between mb-6">
@@ -152,7 +168,7 @@ export default function MelodyList() {
onSearch={setSearch}
placeholder="Search by name, description, or tags..."
/>
<div className="flex gap-3">
<div className="flex flex-wrap gap-3">
<select
value={typeFilter}
onChange={(e) => setTypeFilter(e.target.value)}
@@ -177,6 +193,19 @@ export default function MelodyList() {
</option>
))}
</select>
{languages.length > 1 && (
<select
value={displayLang}
onChange={(e) => setDisplayLang(e.target.value)}
className="px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
>
{languages.map((l) => (
<option key={l} value={l}>
{getLanguageName(l)}
</option>
))}
</select>
)}
<span className="flex items-center text-sm text-gray-500">
{total} {total === 1 ? "melody" : "melodies"}
</span>
@@ -203,7 +232,7 @@ export default function MelodyList() {
<ConfirmDialog
open={!!deleteTarget}
title="Delete Melody"
message={`Are you sure you want to delete "${deleteTarget?.information?.name}"? This will also delete any uploaded files.`}
message={`Are you sure you want to delete "${getDisplayName(deleteTarget?.information?.name)}"? This will also delete any uploaded files.`}
onConfirm={handleDelete}
onCancel={() => setDeleteTarget(null)}
/>