Fix admin regressions from Biome refactor: theme init, mobile nav, i18n.
Local Build and Deploy / deploy (push) Successful in 54s

Restore valid browser JS in theme-init, close mobile sidebar on navigation, and split autoDjForm title/trackTitle across locales.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
SimoandCursor committed 2026-07-15 20:02:25 +02:00
1 parent 59b63d6e70
commit bae543baf6
23 files changed
+87 -44

No files matched your search

+3 -3
View File
@@ -1,8 +1,8 @@
(() => {
let theme: string | null = null;
let theme = null;
let defaultDark = false;
let navbarColor: string | null = null;
let navbarTextColor: string | null = null;
let navbarColor = null;
let navbarTextColor = null;
try {
theme = localStorage.getItem("theme");
const dd = document.querySelector('meta[name="theme-default-dark"]');
+21 -1
View File
@@ -1,7 +1,23 @@
"use client";
import { Menu, X } from "lucide-react";
import { type ReactNode, useEffect, useState } from "react";
import {
createContext,
type ReactNode,
useCallback,
useContext,
useEffect,
useMemo,
useState,
} from "react";
const AdminMobileContext = createContext<{ close: () => void }>({
close: () => {},
});
export function useAdminMobile() {
return useContext(AdminMobileContext);
}
export function AdminMobileWrapper({
sidebar,
@@ -11,6 +27,8 @@ export function AdminMobileWrapper({
children: ReactNode;
}) {
const [open, setOpen] = useState(false);
const close = useCallback(() => setOpen(false), []);
const mobile = useMemo(() => ({ close }), [close]);
useEffect(() => {
if (!open) return;
@@ -22,6 +40,7 @@ export function AdminMobileWrapper({
}, [open]);
return (
<AdminMobileContext.Provider value={mobile}>
<div className="min-h-screen bg-[var(--admin-canvas)] flex flex-col lg:flex-row">
{/* Mobile header */}
<div
@@ -72,5 +91,6 @@ export function AdminMobileWrapper({
{/* Content */}
<div className="flex flex-col flex-1 min-w-0">{children}</div>
</div>
</AdminMobileContext.Provider>
);
}
+3
View File
@@ -3,6 +3,7 @@
import Link from "next/link";
import { usePathname } from "next/navigation";
import type { ReactNode } from "react";
import { useAdminMobile } from "@/components/admin/admin-mobile-wrapper";
/**
* Sidebar link that highlights when its route is active. "/admin" matches
@@ -19,6 +20,7 @@ export function AdminNavLink({
children: ReactNode;
}) {
const pathname = usePathname() ?? "";
const { close } = useAdminMobile();
const active =
href === "/admin"
? pathname === "/admin"
@@ -27,6 +29,7 @@ export function AdminNavLink({
return (
<Link
href={href}
onClick={close}
aria-current={active ? "page" : undefined}
className={`group flex items-center gap-2.5 rounded-xl px-3 py-2 text-sm no-underline transition-colors duration-150
focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--admin-accent)] focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--admin-sidebar-background)] ${
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Запазване на настройките за точки"
},
"autoDjForm": {
"title": "Заглавие",
"title": "Radio AutoDJ",
"subtitle": "Резервен плейлист (radio_auto_dj_playlist), през който радиото се върти, когато няма DJ на живо. Подредени по ред на сортиране и след това по заглавие.",
"dbError": "Плейлистът на AutoDJ не можа да се зареди (няма налична база данни).",
"tracks": "Писти",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "неактивен",
"deactivate": "Деактивирайте",
"activate": "Активирайте",
"delete": "Изтриване"
"delete": "Изтриване",
"trackTitle": "Заглавие"
},
"moderationPage": {
"title": "DJ модериране",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Uložte nastavení bodů"
},
"autoDjForm": {
"title": "Název",
"title": "Radio AutoDJ",
"subtitle": "Záložní seznam skladeb (radio_auto_dj_playlist) rádio rotuje, když nevysílá žádný živý DJ. Seřazeno podle pořadí řazení a poté názvu.",
"dbError": "Nelze načíst seznam stop AutoDJ (databáze není k dispozici).",
"tracks": "Skladby",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "neaktivní",
"deactivate": "Deaktivovat",
"activate": "Aktivovat",
"delete": "Smazat"
"delete": "Smazat",
"trackTitle": "Název"
},
"moderationPage": {
"title": "DJ moderování",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Gem pointindstillinger"
},
"autoDjForm": {
"title": "Titel",
"title": "Radio AutoDJ",
"subtitle": "Fallback-afspilningsliste (radio_auto_dj_playlist), som radioen roterer igennem, når ingen live-dj streamer. Bestilles efter sorteringsrækkefølge og derefter titel.",
"dbError": "Kunne ikke indlæse AutoDJ-afspilningslisten (databasen er ikke tilgængelig).",
"tracks": "Spor",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "inaktiv",
"deactivate": "Deaktiver",
"activate": "Aktiver",
"delete": "Slet"
"delete": "Slet",
"trackTitle": "Titel"
},
"moderationPage": {
"title": "DJ moderation",
+3 -2
View File
@@ -1630,7 +1630,7 @@
"save": "Punkteeinstellungen speichern"
},
"autoDjForm": {
"title": "Title",
"title": "Radio AutoDJ",
"subtitle": "Fallback playlist (radio_auto_dj_playlist) the radio rotates through when no live DJ is streaming. Ordered by sort order then title.",
"dbError": "Could not load the AutoDJ playlist (database unavailable).",
"tracks": "Tracks",
@@ -1660,7 +1660,8 @@
"inactiveLabel": "inactive",
"deactivate": "Deactivate",
"activate": "Activate",
"delete": "Delete"
"delete": "Delete",
"trackTitle": "Title"
},
"moderationPage": {
"title": "DJ Moderation",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Αποθήκευση ρυθμίσεων πόντων"
},
"autoDjForm": {
"title": "Τίτλος",
"title": "Radio AutoDJ",
"subtitle": "Εναλλακτική λίστα αναπαραγωγής (radio_auto_dj_playlist) το ραδιόφωνο περιστρέφεται όταν δεν υπάρχει ζωντανός DJ σε ροή. Ταξινόμηση κατά σειρά ταξινόμησης και κατόπιν τίτλου.",
"dbError": "Δεν ήταν δυνατή η φόρτωση της λίστας αναπαραγωγής AutoDJ (μη διαθέσιμη βάση δεδομένων).",
"tracks": "Κομμάτια",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "ανενεργός",
"deactivate": "Απενεργοποίηση",
"activate": "Ενεργοποίηση",
"delete": "Διαγραφή"
"delete": "Διαγραφή",
"trackTitle": "Τίτλος"
},
"moderationPage": {
"title": "DJ Moderation",
+3 -2
View File
@@ -1630,7 +1630,7 @@
"save": "Guardar configuración de puntos"
},
"autoDjForm": {
"title": "Title",
"title": "Radio AutoDJ",
"subtitle": "Fallback playlist (radio_auto_dj_playlist) the radio rotates through when no live DJ is streaming. Ordered by sort order then title.",
"dbError": "Could not load the AutoDJ playlist (database unavailable).",
"tracks": "Tracks",
@@ -1660,7 +1660,8 @@
"inactiveLabel": "inactive",
"deactivate": "Deactivate",
"activate": "Activate",
"delete": "Delete"
"delete": "Delete",
"trackTitle": "Title"
},
"moderationPage": {
"title": "DJ Moderation",
+3 -2
View File
@@ -1630,7 +1630,7 @@
"save": "Enregistrer les paramètres de points"
},
"autoDjForm": {
"title": "Title",
"title": "Radio AutoDJ",
"subtitle": "Fallback playlist (radio_auto_dj_playlist) the radio rotates through when no live DJ is streaming. Ordered by sort order then title.",
"dbError": "Could not load the AutoDJ playlist (database unavailable).",
"tracks": "Tracks",
@@ -1660,7 +1660,8 @@
"inactiveLabel": "inactive",
"deactivate": "Deactivate",
"activate": "Activate",
"delete": "Delete"
"delete": "Delete",
"trackTitle": "Title"
},
"moderationPage": {
"title": "DJ Moderation",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Spremi postavke bodova"
},
"autoDjForm": {
"title": "Naslov",
"title": "Radio AutoDJ",
"subtitle": "Zamjenski popis za reprodukciju (radio_auto_dj_playlist) kroz koji se radio vrti kada nijedan DJ ne emitira uživo. Poredano prema redoslijedu sortiranja pa naslovu.",
"dbError": "Nije moguće učitati AutoDJ popis za reprodukciju (baza podataka nije dostupna).",
"tracks": "Pjesme",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "neaktivan",
"deactivate": "Deaktiviraj",
"activate": "Aktiviraj",
"delete": "Izbriši"
"delete": "Izbriši",
"trackTitle": "Naslov"
},
"moderationPage": {
"title": "DJ moderiranje",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Mentse el a pontbeállításokat"
},
"autoDjForm": {
"title": "Cím",
"title": "Radio AutoDJ",
"subtitle": "Tartalék lejátszási lista (radio_auto_dj_playlist) a rádió végigpörög, ha nincs élő DJ. Rendezési sorrend, majd cím szerint.",
"dbError": "Nem sikerült betölteni az AutoDJ lejátszási listát (az adatbázis nem érhető el).",
"tracks": "Pályák",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "inaktív",
"deactivate": "Deaktiválás",
"activate": "Aktiválja",
"delete": "Törölje"
"delete": "Törölje",
"trackTitle": "Cím"
},
"moderationPage": {
"title": "DJ moderálás",
+3 -2
View File
@@ -1630,7 +1630,7 @@
"save": "Salva impostazioni punti"
},
"autoDjForm": {
"title": "Title",
"title": "Radio AutoDJ",
"subtitle": "Fallback playlist (radio_auto_dj_playlist) the radio rotates through when no live DJ is streaming. Ordered by sort order then title.",
"dbError": "Could not load the AutoDJ playlist (database unavailable).",
"tracks": "Tracks",
@@ -1660,7 +1660,8 @@
"inactiveLabel": "inactive",
"deactivate": "Deactivate",
"activate": "Activate",
"delete": "Delete"
"delete": "Delete",
"trackTitle": "Title"
},
"moderationPage": {
"title": "DJ Moderation",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Lagre poenginnstillinger"
},
"autoDjForm": {
"title": "Tittel",
"title": "Radio AutoDJ",
"subtitle": "Reservespilleliste (radio_auto_dj_playlist) radioen roterer gjennom når ingen live DJ strømmer. Sortert etter sorteringsrekkefølge og deretter tittel.",
"dbError": "Kunne ikke laste AutoDJ-spillelisten (database utilgjengelig).",
"tracks": "Spor",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "inaktiv",
"deactivate": "Deaktiver",
"activate": "Aktiver",
"delete": "Slett"
"delete": "Slett",
"trackTitle": "Tittel"
},
"moderationPage": {
"title": "DJ-moderasjon",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Zapisz ustawienia punktów"
},
"autoDjForm": {
"title": "Tytuł",
"title": "Radio AutoDJ",
"subtitle": "Zastępcza lista odtwarzania (radio_auto_dj_playlist) radio zmienia się, gdy żaden DJ nie transmituje na żywo. Uporządkowane według kolejności sortowania, a następnie tytułu.",
"dbError": "Nie można załadować listy odtwarzania AutoDJ (baza danych jest niedostępna).",
"tracks": "Utwory",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "nieaktywny",
"deactivate": "Dezaktywuj",
"activate": "Aktywuj",
"delete": "Usuń"
"delete": "Usuń",
"trackTitle": "Tytuł"
},
"moderationPage": {
"title": "Moderacja DJ-a",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Salvar configurações de pontos"
},
"autoDjForm": {
"title": "Título",
"title": "Radio AutoDJ",
"subtitle": "Lista de reprodução alternativa (radio_auto_dj_playlist) pela qual o rádio alterna quando nenhum DJ ao vivo está transmitindo. Ordenado por ordem de classificação e depois por título.",
"dbError": "Não foi possível carregar a playlist do AutoDJ (banco de dados indisponível).",
"tracks": "Faixas",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "inativo",
"deactivate": "Desativar",
"activate": "Ativar",
"delete": "Excluir"
"delete": "Excluir",
"trackTitle": "Título"
},
"moderationPage": {
"title": "Moderação de DJ",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Salvați setările punctelor"
},
"autoDjForm": {
"title": "Titlu",
"title": "Radio AutoDJ",
"subtitle": "Lista de redare alternativă (radio_auto_dj_playlist) prin care radioul se rotește atunci când niciun DJ live nu este transmis în flux. Ordonat după ordine de sortare, apoi titlu.",
"dbError": "Nu s-a putut încărca lista de redare AutoDJ (baza de date indisponibilă).",
"tracks": "Urme",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "inactiv",
"deactivate": "Dezactivați",
"activate": "Activați",
"delete": "Ștergeți"
"delete": "Ștergeți",
"trackTitle": "Titlu"
},
"moderationPage": {
"title": "Moderație DJ",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Save points settings"
},
"autoDjForm": {
"title": "Title",
"title": "Radio AutoDJ",
"subtitle": "Fallback playlist (radio_auto_dj_playlist) the radio rotates through when no live DJ is streaming. Ordered by sort order then title.",
"dbError": "Could not load the AutoDJ playlist (database unavailable).",
"tracks": "Tracks",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "inactive",
"deactivate": "Deactivate",
"activate": "Activate",
"delete": "Delete"
"delete": "Delete",
"trackTitle": "Title"
},
"moderationPage": {
"title": "DJ Moderation",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Uložte nastavenia bodov"
},
"autoDjForm": {
"title": "Názov",
"title": "Radio AutoDJ",
"subtitle": "Záložný zoznam skladieb (radio_auto_dj_playlist) rádio rotuje, keď nevysiela žiadny živý DJ. Zoradené podľa zoradenia a potom podľa názvu.",
"dbError": "Nepodarilo sa načítať zoznam skladieb AutoDJ (databáza nie je k dispozícii).",
"tracks": "Skladby",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "neaktívne",
"deactivate": "Deaktivovať",
"activate": "Aktivovať",
"delete": "Odstrániť"
"delete": "Odstrániť",
"trackTitle": "Názov"
},
"moderationPage": {
"title": "Moderovanie DJ",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Сачувајте подешавања поена"
},
"autoDjForm": {
"title": "Наслов",
"title": "Radio AutoDJ",
"subtitle": "Резервна листа за репродукцију (радио_ауто_дј_плаилист) радио ротира када ниједан ДЈ не емитује уживо. Поредано по редоследу сортирања, а затим наслову.",
"dbError": "Није могуће учитати АутоДЈ листу за репродукцију (база података није доступна).",
"tracks": "Стазе",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "неактиван",
"deactivate": "Деактивирај",
"activate": "Активирај",
"delete": "Избриши"
"delete": "Избриши",
"trackTitle": "Наслов"
},
"moderationPage": {
"title": "ДЈ Модератион",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Spara poänginställningar"
},
"autoDjForm": {
"title": "Titel",
"title": "Radio AutoDJ",
"subtitle": "Reservspellista (radio_auto_dj_playlist) som radion roterar genom när ingen live-DJ strömmar. Beställs efter sorteringsordning sedan titel.",
"dbError": "Det gick inte att ladda AutoDJ-spellistan (databasen är inte tillgänglig).",
"tracks": "Spår",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "inaktiv",
"deactivate": "Inaktivera",
"activate": "Aktivera",
"delete": "Ta bort"
"delete": "Ta bort",
"trackTitle": "Titel"
},
"moderationPage": {
"title": "DJ Moderering",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Puan ayarlarını kaydet"
},
"autoDjForm": {
"title": "Başlık",
"title": "Radio AutoDJ",
"subtitle": "Geri dönüş çalma listesi (radio_auto_dj_playlist) hiçbir canlı DJ akışı olmadığında radyo döner. Sıralama düzenine ve ardından başlığa göre sıralanır.",
"dbError": "AutoDJ çalma listesi yüklenemedi (veritabanı mevcut değil).",
"tracks": "Parçalar",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "aktif değil",
"deactivate": "Devre dışı bırak",
"activate": "Etkinleştir",
"delete": "Sil"
"delete": "Sil",
"trackTitle": "Başlık"
},
"moderationPage": {
"title": "DJ Moderasyon",
+3 -2
View File
@@ -1666,7 +1666,7 @@
"save": "Зберегти налаштування балів"
},
"autoDjForm": {
"title": "Назва",
"title": "Radio AutoDJ",
"subtitle": "Запасний список відтворення (radio_auto_dj_playlist), у якому радіо обертається, коли ді-джей не транслює пряму трансляцію. Упорядковано за порядком сортування, а потім за назвою.",
"dbError": "Не вдалося завантажити список відтворення AutoDJ (база даних недоступна).",
"tracks": "Доріжки",
@@ -1696,7 +1696,8 @@
"inactiveLabel": "неактивний",
"deactivate": "Дезактивувати",
"activate": "активувати",
"delete": "Видалити"
"delete": "Видалити",
"trackTitle": "Назва"
},
"moderationPage": {
"title": "Модерація DJ",