mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
init Admin frontend
This commit is contained in:
parent
112062c0b2
commit
16ec234ed8
5 changed files with 149 additions and 12 deletions
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
64
client/src/components/AdminDrawer/AdminDrawer.tsx
Normal file
64
client/src/components/AdminDrawer/AdminDrawer.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -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,6 +23,10 @@ const Header: React.FC<HeaderProps> = ({ isLoggedIn, handleLogout }) => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{isLoggedIn && (
|
{isLoggedIn && (
|
||||||
|
<div className="button-group">
|
||||||
|
|
||||||
|
{ isAdmin && <AdminDrawer /> }
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
|
@ -31,8 +37,10 @@ const Header: React.FC<HeaderProps> = ({ isLoggedIn, handleLogout }) => {
|
||||||
>
|
>
|
||||||
Logout
|
Logout
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
{!isLoggedIn && (
|
{!isLoggedIn && (
|
||||||
<div className="auth-selection-btn">
|
<div className="auth-selection-btn">
|
||||||
<Link to="/login">
|
<Link to="/login">
|
||||||
|
|
|
||||||
|
|
@ -12,3 +12,9 @@
|
||||||
.header img {
|
.header img {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue