From 0b1a6cdea473efe633e685c7626dc3cfc7d1c2f9 Mon Sep 17 00:00:00 2001 From: chad Date: Sat, 4 Oct 2025 08:08:45 -0400 Subject: [PATCH] updated navbar and ui --- backend/index.js | 25 ++++++++- checklist.md | 11 ++++ frontend/src/App.js | 2 - frontend/src/components/Dashboard.js | 5 +- frontend/src/components/HelpPage.js | 4 +- frontend/src/components/NavBar.js | 63 ++++++++++++++++------- frontend/src/components/ServerSettings.js | 48 ++++++++++++----- 7 files changed, 118 insertions(+), 40 deletions(-) diff --git a/backend/index.js b/backend/index.js index 23746fb..7d2d28a 100644 --- a/backend/index.js +++ b/backend/index.js @@ -73,13 +73,34 @@ app.get('/api/servers/:guildId/settings', (req, res) => { app.post('/api/servers/:guildId/settings', (req, res) => { const { guildId } = req.params; - const { pingCommand } = req.body; + const newSettings = req.body || {}; const db = readDb(); - db[guildId] = { pingCommand }; + if (!db[guildId]) db[guildId] = {}; + // Merge incoming settings with existing settings to avoid overwriting unrelated keys + db[guildId] = { ...db[guildId], ...newSettings }; writeDb(db); res.json({ success: true }); }); +// Toggle a single command for a guild (preserves other toggles) +app.post('/api/servers/:guildId/commands/:cmdName/toggle', (req, res) => { + const { guildId, cmdName } = req.params; + const { enabled } = req.body; // boolean + const protectedCommands = ['help', 'manage-commands']; + if (protectedCommands.includes(cmdName)) { + return res.status(403).json({ success: false, message: 'This command is locked and cannot be toggled.' }); + } + const db = readDb(); + if (!db[guildId]) db[guildId] = {}; + if (!db[guildId].commandToggles) db[guildId].commandToggles = {}; + if (typeof enabled === 'boolean') { + db[guildId].commandToggles[cmdName] = enabled; + writeDb(db); + return res.json({ success: true, cmdName, enabled }); + } + return res.status(400).json({ success: false, message: 'Missing or invalid "enabled" boolean in request body' }); +}); + app.get('/api/servers/:guildId/bot-status', (req, res) => { const { guildId } = req.params; const guild = bot.client.guilds.cache.get(guildId); diff --git a/checklist.md b/checklist.md index aeed8f6..b5c40ad 100644 --- a/checklist.md +++ b/checklist.md @@ -33,6 +33,13 @@ - [x] Further fine-tune card UI - [x] Add Commands section to server settings page - [x] Refine 'Back to Dashboard' button + - [x] Remove 'Open Help Page' button from individual command controls (moved to dedicated Commands List page) + - [x] Rename Help nav/button to 'Commands List' and update page title + - [x] Restructure Commands list UI to show per-command toggles and cleaner layout + - [x] Ensure frontend persists selections and doesn't overwrite other settings + - [x] Improve NavBar layout and styling for clarity and compactness + - [x] Implement single-hamburger NavBar (hamburger toggles to X; buttons hidden when collapsed) + - [x] Commands List button added above Commands accordion in Server Settings - [x] Place 'Invite' button beside the server title on dashboard/server cards - Acceptance criteria: the invite button appears horizontally adjacent to the server title (to the right), remains visible and usable on tablet and desktop layouts, is keyboard-focusable, and has an accessible aria-label (e.g. "Invite bot to SERVER_NAME"). - [x] Show the server name in a rounded "bubble" and render it bold @@ -108,6 +115,10 @@ - [x] Ensure the `/help` command is locked (protected) and cannot be disabled via `/manage-commands`. - [x] Add a Help tab in the frontend Server Settings that lists all bot commands and their descriptions per-server. - [x] Move Help to a dedicated page within the server dashboard and add a top NavBar (collapsible) with Dashboard, Discord!, Contact, and Help (when on a server) buttons. Ensure Help page has a back arrow to return to the Commands section. + - [x] Move Help to a dedicated page within the server dashboard and add a top NavBar (collapsible) with Dashboard, Discord!, and Commands List (when on a server) buttons. Ensure Help page has a back arrow to return to the Commands section. + - [x] Remove Contact page from the frontend and App routes (no longer needed). + - [x] Redesign NavBar for cleaner layout and prettier appearance. + - [x] Redesign NavBar for cleaner layout and prettier appearance. (Title updated to 'ECS - EHDCHADSWORTH') - [x] Added `/help` slash command that lists commands and their descriptions and shows per-server enable/disable status. - [x] **Autorole** - [x] Add "Autorole" section to server settings. diff --git a/frontend/src/App.js b/frontend/src/App.js index ec99ff8..e360feb 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -8,7 +8,6 @@ import Dashboard from './components/Dashboard'; import ServerSettings from './components/ServerSettings'; import NavBar from './components/NavBar'; import HelpPage from './components/HelpPage'; -import ContactPage from './components/ContactPage'; import DiscordPage from './components/DiscordPage'; function App() { @@ -23,7 +22,6 @@ function App() { } /> } /> } /> - } /> } /> diff --git a/frontend/src/components/Dashboard.js b/frontend/src/components/Dashboard.js index 1623762..9253e12 100644 --- a/frontend/src/components/Dashboard.js +++ b/frontend/src/components/Dashboard.js @@ -2,7 +2,6 @@ import React, { useState, useEffect, useLayoutEffect, useContext } from 'react'; import { useNavigate } from 'react-router-dom'; import { Grid, Card, CardContent, Typography, Box, CardMedia, IconButton, Snackbar, Alert } from '@mui/material'; import { UserContext } from '../contexts/UserContext'; -import UserSettings from './UserSettings'; import PersonAddIcon from '@mui/icons-material/PersonAdd'; import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline'; import axios from 'axios'; @@ -119,9 +118,7 @@ const Dashboard = () => { return (
- - - + {/* UserSettings moved to NavBar */} Dashboard diff --git a/frontend/src/components/HelpPage.js b/frontend/src/components/HelpPage.js index d2c6426..63d93fb 100644 --- a/frontend/src/components/HelpPage.js +++ b/frontend/src/components/HelpPage.js @@ -24,8 +24,8 @@ const HelpPage = () => { return (
- - Help - Commands for this Server + + Commands List {commands.length === 0 && No commands available.} diff --git a/frontend/src/components/NavBar.js b/frontend/src/components/NavBar.js index 7cd2a64..27cc4ab 100644 --- a/frontend/src/components/NavBar.js +++ b/frontend/src/components/NavBar.js @@ -1,31 +1,58 @@ import React, { useState } from 'react'; -import { AppBar, Toolbar, Button, Box, IconButton, Collapse } from '@mui/material'; +import { AppBar, Toolbar, IconButton, Typography, Box, Menu, MenuItem } from '@mui/material'; +import UserSettings from './UserSettings'; import MenuIcon from '@mui/icons-material/Menu'; -import HelpOutlineIcon from '@mui/icons-material/HelpOutline'; -import { useNavigate, useLocation, useParams } from 'react-router-dom'; +import CloseIcon from '@mui/icons-material/Close'; +import { useNavigate, useLocation } from 'react-router-dom'; const NavBar = () => { - const [open, setOpen] = useState(true); const navigate = useNavigate(); const location = useLocation(); - // Pull guildId from URL if present + const [open, setOpen] = useState(false); + const [anchorEl, setAnchorEl] = useState(null); const guildIdMatch = location.pathname.match(/\/server\/(\d+)/); const guildId = guildIdMatch ? guildIdMatch[1] : null; + const toggleOpen = (e) => { + if (!open) { + setAnchorEl(e.currentTarget); + setOpen(true); + } else { + setAnchorEl(null); + setOpen(false); + } + }; + const closeMenu = () => { setAnchorEl(null); setOpen(false); }; + return ( - - - setOpen(prev => !prev)} aria-label="toggle menu"> - - - - - - {guildId && ( - - )} - - + + + + + {open ? : } + + + + { navigate('/dashboard'); closeMenu(); }}> + ECS - EHDCHADSWORTH + + + + + + + + { navigate('/dashboard'); closeMenu(); }}>Dashboard + { window.open('https://discord.gg/EAqNqWjJMQ', '_blank'); closeMenu(); }}>Join The Discord! + {guildId && { navigate(`/server/${guildId}/help`); closeMenu(); }}>Commands List} + ); diff --git a/frontend/src/components/ServerSettings.js b/frontend/src/components/ServerSettings.js index 97c24f6..175ef62 100644 --- a/frontend/src/components/ServerSettings.js +++ b/frontend/src/components/ServerSettings.js @@ -4,7 +4,7 @@ import axios from 'axios'; import { Button, Typography, Box, IconButton, Switch, Select, MenuItem, FormControl, FormControlLabel, Radio, RadioGroup, TextField, Accordion, AccordionSummary, AccordionDetails } from '@mui/material'; import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; -import UserSettings from './UserSettings'; +// UserSettings moved to NavBar import ConfirmDialog from './ConfirmDialog'; const ServerSettings = () => { @@ -243,24 +243,48 @@ const ServerSettings = () => { )} - + {/* UserSettings moved to NavBar */} setCommandsExpanded(prev => !prev)}> }> Commands + + + {!isBotInServer && Invite the bot to enable commands.} - - Ping Command - - - - + + {commandsList.map(cmd => ( + + + {cmd.name} + {cmd.description} + + + {['help', 'manage-commands'].includes(cmd.name) ? ( + } + label="Locked" + /> + ) : ( + { + const newVal = e.target.checked; + // optimistic update + setCommandsList(prev => prev.map(c => c.name === cmd.name ? { ...c, enabled: newVal } : c)); + try { + await axios.post(`http://localhost:3002/api/servers/${guildId}/commands/${cmd.name}/toggle`, { enabled: newVal }); + } catch (err) { + // revert on error + setCommandsList(prev => prev.map(c => c.name === cmd.name ? { ...c, enabled: cmd.enabled } : c)); + } + }} disabled={!isBotInServer} label={cmd.enabled ? 'Enabled' : 'Disabled'} />} + /> + )} + + + ))}