From 77bc36b765bc8d389e184e482a63bf04f04a4b9f Mon Sep 17 00:00:00 2001 From: Benoit Date: Mon, 1 Jun 2026 23:04:57 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20am=C3=A9lioration=20UX=20interface=20ad?= =?UTF-8?q?min=20audio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Admin : regroupement des 3 dropdowns cartes son dans une seule section - Admin : suppression du mode édition pour noms de canaux (directement éditables) - Admin : unification des boutons de sauvegarde en bas de chaque section - Admin : routing par hash URL pour persistance des onglets (#groups, #audio, etc.) - AudioRoutingMatrix : bouton sauvegarde déplacé en bas de la matrice - AudioRoutingMatrix : dropdowns de gain en nuance de bleu (cohérence visuelle) --- client/src/Admin.jsx | 225 ++++++++++--------- client/src/components/AudioRoutingMatrix.css | 18 +- client/src/components/AudioRoutingMatrix.jsx | 27 +-- 3 files changed, 145 insertions(+), 125 deletions(-) diff --git a/client/src/Admin.jsx b/client/src/Admin.jsx index bb285ee..80b3f99 100644 --- a/client/src/Admin.jsx +++ b/client/src/Admin.jsx @@ -5,7 +5,13 @@ import AudioRoutingMatrix from './components/AudioRoutingMatrix'; const API_URL = import.meta.env.VITE_API_URL || '/api'; function Admin() { - const [activeTab, setActiveTab] = useState('groups'); + // Lire l'onglet depuis l'URL hash (ex: #audio) ou utiliser 'groups' par défaut + const getInitialTab = () => { + const hash = window.location.hash.slice(1); // Enlever le # + return ['groups', 'audio', 'users', 'stats', 'logs'].includes(hash) ? hash : 'groups'; + }; + + const [activeTab, setActiveTab] = useState(getInitialTab()); const [groups, setGroups] = useState([]); const [users, setUsers] = useState([]); const [stats, setStats] = useState(null); @@ -23,8 +29,6 @@ function Admin() { // Channel names (Phase 2.5) const [channelNames, setChannelNames] = useState({ inputs: {}, outputs: {} }); - const editingChannelNamesRef = useRef(false); - const [, forceUpdate] = useState({}); // Gestion formulaire nouveau groupe const [showGroupForm, setShowGroupForm] = useState(false); @@ -34,6 +38,19 @@ function Admin() { audioBitrate: 96 }); + // Synchroniser l'onglet avec l'URL hash + useEffect(() => { + const handleHashChange = () => { + const hash = window.location.hash.slice(1); + if (['groups', 'audio', 'users', 'stats', 'logs'].includes(hash)) { + setActiveTab(hash); + } + }; + + window.addEventListener('hashchange', handleHashChange); + return () => window.removeEventListener('hashchange', handleHashChange); + }, []); + // Rafraîchissement automatique useEffect(() => { loadData(); @@ -105,11 +122,7 @@ function Admin() { const device = currentData.device || { inputChannels: 8, outputChannels: 8 }; setCurrentDevice(device); - - // Ne pas écraser les noms de canaux pendant l'édition - if (!editingChannelNamesRef.current) { - setChannelNames(channelNamesData.channelNames || { inputs: {}, outputs: {} }); - } + setChannelNames(channelNamesData.channelNames || { inputs: {}, outputs: {} }); // Ne réinitialiser les sélections que lors du chargement initial (pas en train d'éditer) if (!isEditingAudioRef.current) { @@ -221,8 +234,6 @@ function Admin() { if (res.ok) { alert('Noms de canaux sauvegardés avec succès!'); - editingChannelNamesRef.current = false; - forceUpdate({}); await loadAudioDevices(); } else { const error = await res.json(); @@ -317,31 +328,31 @@ function Admin() {