DashboardLayout

This commit is contained in:
Mikan
2025-06-02 18:11:15 +03:00
parent ab10918dc4
commit 054cb63d71
5 changed files with 70 additions and 43 deletions

View File

@@ -29,7 +29,7 @@ export function useDataPage<T>(application:string, endpoint: string, params:{[ke
}) })
} }
}, },
[data, application, endpoint, needLoad] [data, application, endpoint, needLoad, params]
) )
// function changePage(pageUrl: string|undefined) { // function changePage(pageUrl: string|undefined) {
@@ -92,7 +92,7 @@ export function useData<T>(application:string, endpoint: string, id: string|numb
} }
interface CachedData<T>{ interface CachedData<T>{
get(id: string | number, needLoad: boolean): T|undefined|null get(id: string | number, needLoad?: boolean): T|undefined|null
} }
export function useCachedData<T>(application: string, endpoint: string): CachedData<T> { export function useCachedData<T>(application: string, endpoint: string): CachedData<T> {

View File

@@ -1,29 +1,46 @@
import {useUser} from "../utils/users/UseUser.ts"; import { useUser } from "../utils/users/UseUser.ts"; // Хук для получения информации о пользователе
import {Outlet, useNavigate} from "react-router-dom"; import { Outlet, Link, useNavigate } from "react-router-dom"; // Композиция для маршрутизации
import React, {useEffect} from "react"; import React, { useEffect } from "react";
import {UserContextType} from "../types/users.ts";
export function DashboardLayout() { export function DashboardLayout() {
const { user } = useUser(); const { user, logout } = useUser() as UserContextType; // Получаем данные о пользователе
const navigate = useNavigate(); const navigate = useNavigate(); // Получаем функцию для навигации
// Проверяем, есть ли пользователь, если нет, редиректим на страницу логина
useEffect(() => { useEffect(() => {
if (!user) { if (!user) {
navigate("/login/") navigate("/login/");
} }
}, [navigate, user]); }, [navigate, user]);
if (!user){ if (!user) {
return null; return null; // Если пользователь не найден, ничего не отображаем
} }
// Определяем класс для активной ссылки
const isActive = (path: string) => window.location.pathname.includes(path)? 'selected' : 'unselected';
return ( return (
<> <div className="dashboard-layout">
<div className="header"> <div className="sidebar">
<h1 className="logo">Pro-Fi</h1> <h1 className="logo">Pro-Fi</h1>
<p className="role">{user.roleTitle || "Роль не опознана"}</p> {/* Отображаем текущую роль пользователя */}
<nav className="navigation">
<Link to="/dashboard/staff" className={isActive('/dashboard/staff')}>Штат</Link>
<Link to="/dashboard/schools" className={isActive('/dashboard/schools')}>Школы</Link>
<Link to="/dashboard/events" className={isActive('/dashboard/events')}>Мероприятия</Link>
<Link to="/dashboard/students" className={isActive('/dashboard/students')}>Студенты</Link>
<Link to="/dashboard/reports" className={isActive('/dashboard/reports')}>Отчеты</Link>
<Link to="/dashboard/partners" className={isActive('/dashboard/partners')}>Партнеры</Link>
<Link to="/admin" className={isActive('/admin')}>Админ-панель</Link>
<button onClick={logout} className="logout">Выйти</button>
</nav>
</div> </div>
<div className="content"> <div className="content">
<Outlet /> <Outlet />
</div> </div>
</> </div>
); );
} }

View File

@@ -23,12 +23,18 @@ export function LoginPage() {
const handleSubmit = async (e: React.FormEvent) => { const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
if (login && loginInput && password) { if (login && loginInput && password) {
let success = false;
try { try {
await login({ login: loginInput, password }); success = await login({ login: loginInput, password });
setError(null); setError(null);
if (!success){
setError('Ошибка входа');
}
} catch { } catch {
setError('Ошибка входа'); setError('Ошибка входа');
} }
} }
}; };

View File

@@ -2,7 +2,7 @@ import {UniqueItem} from "./common.ts";
export type UserContextType = { export type UserContextType = {
user: Account | undefined; user: Account | undefined;
login: (credentials: TokenObtainPair) => Promise<void>; login: (credentials: TokenObtainPair) => Promise<boolean>;
logout: () => void; logout: () => void;
}; };
@@ -14,13 +14,11 @@ export interface ContactData{
email?:string; email?:string;
} }
interface Role extends UniqueItem{
title: string;
}
export interface Account extends UniqueItem, ContactData{ export interface Account extends UniqueItem, ContactData{
login: string; login: string;
role?: Role; role?: number;
roleTitle?: string;
is_staff: boolean; is_staff: boolean;
is_active: boolean; is_active: boolean;

View File

@@ -31,7 +31,6 @@ export function UserProvider({ children }: { children: ReactNode }) {
}, [tokens]); }, [tokens]);
useEffect(() => { useEffect(() => {
console.log(user)
if (user) { if (user) {
localStorage.setItem('user', JSON.stringify(user)); localStorage.setItem('user', JSON.stringify(user));
} else { } else {
@@ -48,21 +47,27 @@ export function UserProvider({ children }: { children: ReactNode }) {
response = await getFetch(`/users/auth/users/${(response.body as Account).id}/`); response = await getFetch(`/users/auth/users/${(response.body as Account).id}/`);
if (response.success){ if (!response.success){
return response.body as Account
}
// if (response?.success && response.body) {
// return response.body as Account; // Возвращаем данные о пользователе
// }
return undefined; return undefined;
}
const account = response.body as Account ;
if (account.role){
response = await getFetch(`/users/roles/${account.role}/`);
if (response.success){
account.roleTitle = (response.body as {name:string}).name;
}
}
return account;
}; };
const handleLogin = async (credentials: TokenObtainPair) => { const handleLogin = async (credentials: TokenObtainPair) => {
const tokens = await apiLogin(credentials); const tokens = await apiLogin(credentials);
if (tokens) { if (tokens) {
setTokens(tokens); setTokens(tokens);
return true;
} }
return false;
}; };
const handleLogout = () => { const handleLogout = () => {
@@ -70,7 +75,10 @@ export function UserProvider({ children }: { children: ReactNode }) {
setTokens(undefined); setTokens(undefined);
}; };
const validateToken = async () => {
useEffect(() => {
async function validateToken() {
if (tokens?.access) { if (tokens?.access) {
const isValid = await verifyToken({ token: tokens.access }); const isValid = await verifyToken({ token: tokens.access });
if (!isValid && tokens.refresh) { if (!isValid && tokens.refresh) {
@@ -84,11 +92,9 @@ export function UserProvider({ children }: { children: ReactNode }) {
handleLogout(); handleLogout();
} }
} }
}; }
useEffect(() => {
validateToken().then(); validateToken().then();
}, []); }, [tokens]);
return ( return (
<UserContext.Provider value={{ user, login: handleLogin, logout: handleLogout }}> <UserContext.Provider value={{ user, login: handleLogin, logout: handleLogout }}>