Phase 2 UI Adjustments/Edits by bonamin
This commit is contained in:
@@ -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)}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user