init Admin frontend

This commit is contained in:
Eddi3_As 2025-03-14 11:43:01 -04:00
parent 112062c0b2
commit 16ec234ed8
5 changed files with 149 additions and 12 deletions

View file

@ -29,6 +29,7 @@ import OAuthCallback from './pages/AuthManager/callback/AuthCallback';
const App: React.FC = () => { const App: React.FC = () => {
const [isAuthenticated, setIsAuthenticated] = useState(ApiService.isLoggedIn()); const [isAuthenticated, setIsAuthenticated] = useState(ApiService.isLoggedIn());
const [isTeacherAuthenticated, setIsTeacherAuthenticated] = useState(ApiService.isLoggedInTeacher()); const [isTeacherAuthenticated, setIsTeacherAuthenticated] = useState(ApiService.isLoggedInTeacher());
const [isAdmin, setIsAdmin] = useState(false);
const [isRoomRequireAuthentication, setRoomsRequireAuth] = useState(null); const [isRoomRequireAuthentication, setRoomsRequireAuth] = useState(null);
const location = useLocation(); const location = useLocation();
@ -37,6 +38,7 @@ const App: React.FC = () => {
const checkLoginStatus = () => { const checkLoginStatus = () => {
setIsAuthenticated(ApiService.isLoggedIn()); setIsAuthenticated(ApiService.isLoggedIn());
setIsTeacherAuthenticated(ApiService.isLoggedInTeacher()); setIsTeacherAuthenticated(ApiService.isLoggedInTeacher());
//setIsAdmin(ApiService.isAdmin());
}; };
const fetchAuthenticatedRooms = async () => { const fetchAuthenticatedRooms = async () => {
@ -56,7 +58,7 @@ const App: React.FC = () => {
return ( return (
<div className="content"> <div className="content">
<Header isLoggedIn={isAuthenticated} handleLogout={handleLogout} /> <Header isLoggedIn={isAuthenticated} isAdmin={true} handleLogout={handleLogout} />
<div className="app"> <div className="app">
<main> <main>
<Routes> <Routes>

View file

@ -0,0 +1,57 @@
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import AdminDrawer from '../../../components/AdminDrawer/AdminDrawer';
import '@testing-library/jest-dom';
describe('AdminDrawer Component', () => {
test('renders the Admin button', () => {
render(<AdminDrawer />);
// Check if the "Admin" button is in the document
const button = screen.getByRole('button', { name: /admin/i });
expect(button).toBeInTheDocument();
});
test('opens the drawer when the button is clicked', () => {
render(<AdminDrawer />);
// Click the "Admin" button
const button = screen.getByRole('button', { name: /admin/i });
fireEvent.click(button);
// Check if the drawer is open (it should be a right-side drawer, so check for list items)
const statsItem = screen.getByText(/Stats/i);
expect(statsItem).toBeInTheDocument();
});
//TODO modify this test as no redirect as of yet
/*
test('closes the drawer when an item is clicked', () => {
render(<AdminDrawer />);
// Open the drawer by clicking the "Admin" button
const button = screen.getByRole('button', { name: /admin/i });
fireEvent.click(button);
// Click on a menu item (Stats, Images, or Users)
const statsItem = screen.getByText(/Stats/i);
expect(statsItem).toBeInTheDocument();
fireEvent.click(statsItem);
// Ensure that the drawer is closed after clicking an item
const statsItemAgain = screen.queryByText(/Stats/i);
expect(statsItemAgain).not.toBeInTheDocument();
});
*/
test('menu items render correctly', () => {
render(<AdminDrawer />);
// Open the drawer
const button = screen.getByRole('button', { name: /admin/i });
fireEvent.click(button);
// Check if all the menu items are rendered
expect(screen.getByText(/Stats/i)).toBeInTheDocument();
expect(screen.getByText(/Images/i)).toBeInTheDocument();
expect(screen.getByText(/Users/i)).toBeInTheDocument();
});
});

View file

@ -0,0 +1,64 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import Drawer from '@mui/material/Drawer';
import Button from '@mui/material/Button';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import BarChartIcon from '@mui/icons-material/BarChart';
import ImageIcon from '@mui/icons-material/Image';
import PeopleIcon from '@mui/icons-material/People';
const styles = {
drawerBg: 'rgba(82, 113, 255, 0.85)',
drawerTxtColor: 'white',
btnBg: 'rgba(82, 113, 255, 1)',
btnHover: 'rgba(65, 105, 225, 0.7)',
height: '100%'
};
export default function AdminDrawer() {
const [open, setOpen] = React.useState(false);
const toggleDrawer = (isOpen: boolean) => () => {
setOpen(isOpen);
};
const menuItems = [
{ text: 'Stats', icon: <BarChartIcon /> },
{ text: 'Images', icon: <ImageIcon /> },
{ text: 'Users', icon: <PeopleIcon /> },
];
const list = (
<Box sx={{ width: 250, backgroundColor: styles.drawerBg, height: styles.height, color: styles.drawerTxtColor }} role="presentation" onClick={toggleDrawer(false)}>
<List>
{menuItems.map(({ text, icon }) => (
<ListItem key={text} disablePadding>
<ListItemButton>
<ListItemIcon sx={{ color: styles.drawerTxtColor }}>{icon}</ListItemIcon>
<ListItemText primary={text} />
</ListItemButton>
</ListItem>
))}
</List>
</Box>
);
return (
<div>
<Button
variant="contained"
sx={{ backgroundColor: styles.btnBg, color: 'white', '&:hover': { backgroundColor: styles.btnHover } }}
onClick={toggleDrawer(true)}
>
Admin
</Button>
<Drawer anchor="right" open={open} onClose={toggleDrawer(false)}>
{list}
</Drawer>
</div>
);
}

View file

@ -2,13 +2,15 @@ import { Link, useNavigate } from 'react-router-dom';
import * as React from 'react'; import * as React from 'react';
import './header.css'; import './header.css';
import { Button } from '@mui/material'; import { Button } from '@mui/material';
import AdminDrawer from '../AdminDrawer/AdminDrawer';
interface HeaderProps { interface HeaderProps {
isLoggedIn: boolean; isLoggedIn: boolean;
isAdmin: boolean;
handleLogout: () => void; handleLogout: () => void;
} }
const Header: React.FC<HeaderProps> = ({ isLoggedIn, handleLogout }) => { const Header: React.FC<HeaderProps> = ({ isLoggedIn, isAdmin, handleLogout }) => {
const navigate = useNavigate(); const navigate = useNavigate();
return ( return (
@ -21,18 +23,24 @@ const Header: React.FC<HeaderProps> = ({ isLoggedIn, handleLogout }) => {
/> />
{isLoggedIn && ( {isLoggedIn && (
<Button <div className="button-group">
variant="outlined"
color="primary" { isAdmin && <AdminDrawer /> }
onClick={() => {
handleLogout(); <Button
navigate('/'); variant="outlined"
}} color="primary"
> onClick={() => {
Logout handleLogout();
</Button> navigate('/');
}}
>
Logout
</Button>
</div>
)} )}
{!isLoggedIn && ( {!isLoggedIn && (
<div className="auth-selection-btn"> <div className="auth-selection-btn">
<Link to="/login"> <Link to="/login">

View file

@ -11,4 +11,10 @@
.header img { .header img {
cursor: pointer; cursor: pointer;
}
.button-group {
display: flex;
flex-wrap: wrap;
gap: 10px;
} }