Main project structure #3

Closed
Beesquit wants to merge 17 commits from dev into main
26 changed files with 4057 additions and 0 deletions
Showing only changes of commit d23546d6e0 - Show all commits

View File

@ -1,9 +1,16 @@
import { BrowserRouter as Router, Routes, Route, Navigate, Outlet, useLocation } from 'react-router-dom'; import { BrowserRouter as Router, Routes, Route, Navigate, Outlet, useLocation } from 'react-router-dom';
import {useContext } from "react"; import {useContext, useEffect, useState } from "react";
import AuthContext, { AuthProvider } from "./auth/auth-provider"
import ping from "./auth/ping";
import Login from "./pages/login/login" import Login from "./pages/login/login"
import Register from "./pages/register/register" import Register from "./pages/register/register"
import Home from "./pages/home/home" import Home from "./pages/home/home"
import AuthContext, { AuthProvider } from "./auth/auth-provider" import Dashboard from "./pages/dashboard/dashboard"
import Settings from "./pages/settings/settings"
import useAuth from './auth/auth';
function App() { function App() {
@ -16,7 +23,11 @@ function App() {
<Route element={<PrivateRoute />}> <Route element={<PrivateRoute />}>
<Route path='/' element={<Home />} /> <Route path='/' element={<Home />} />
<Route path='/dashboard' element={<Dashboard />} />
<Route path='/settings' element={<Settings />} />
</Route> </Route>
<Route path="*" element={<div>404</div>} />
</Routes> </Routes>
</Router> </Router>
</AuthProvider> </AuthProvider>
@ -25,14 +36,34 @@ function App() {
const PrivateRoute = () => { const PrivateRoute = () => {
const { isAuthenticated } = useContext(AuthContext); const { token } = useAuth();
const location = useLocation(); const location = useLocation();
const [checked, setChecked] = useState(false);
const [isValid, setIsValid] = useState(false);
useEffect(() => {
const checkAuth = async () => {
if (!token) {
setIsValid(false);
setChecked(true);
return;
}
const result = await ping(token);
console.log(result)
setIsValid(result);
setChecked(true);
};
checkAuth();
}, [token]);
if (!checked) {
return <div>Checking server availability...</div>;
}
return ( return (
isAuthenticated === true ? isValid
<Outlet /> ? <Outlet />
: : <Navigate to="/login" state={{ from: location }} replace />
<Navigate to="/login" state={{ from: location }} replace />
); );
} }

View File

@ -9,7 +9,7 @@ type AuthContextType = {
const AuthContext = createContext<AuthContextType>({ const AuthContext = createContext<AuthContextType>({
token: null, token: null,
setToken: () => { }, setToken: () => {},
}); });
@ -20,15 +20,19 @@ export const AuthProvider = ({ children }: { children: JSX.Element }) => {
const savedToken = localStorage.getItem("token"); const savedToken = localStorage.getItem("token");
if (savedToken) { if (savedToken) {
setTokenState(savedToken); setTokenState(savedToken);
console.log("meow")
} }
console.log(savedToken)
}, []); }, []);
const setToken = (newToken: string | null) => { const setToken = (newToken: string | null) => {
setTokenState(newToken); setTokenState(newToken);
if (newToken) { if (newToken) {
localStorage.setItem("token", newToken); localStorage.setItem("token", newToken);
console.log("saved")
} else { } else {
localStorage.removeItem("token"); localStorage.removeItem("token");
console.log("removed")
} }
}; };

View File

@ -3,9 +3,7 @@ import AuthContext from "./auth-provider"
function useAuth() { function useAuth() {
return ( return useContext(AuthContext);
useContext(AuthContext)
);
} }
export default useAuth; export default useAuth;

View File

@ -1,12 +1,15 @@
import { useNavigate } from "react-router-dom";
import useAuth from "./auth"; import useAuth from "./auth";
const logout = () => {
// eslint-disable-next-line react-hooks/rules-of-hooks const useLogout = () => {
const { setToken: setAuth } = useAuth(); const { setToken } = useAuth();
const navigate = useNavigate();
return () => { return () => {
setAuth(false); setToken(null);
navigate("/login");
}; };
} }
export default logout; export default useLogout;

View File

@ -1,16 +1,10 @@
const ping = () => { const ping = async (token: string | null): Promise<boolean> => {
// TODO: request to API // TODO: request to API
return () => { return new Promise((resolve) => {
return true; setTimeout(() => {
}; resolve(!!token);
} }, 300);
});
// const ping = async (token: string): Promise<boolean> => { };
// return new Promise((resolve) => {
// setTimeout(() => {
// resolve(!!token);
// }, 300);
// });
// };
export default ping; export default ping;

View File

@ -0,0 +1,9 @@
const Dashboard = () => {
return (
<div>
<h2>Dashboard</h2>
</div>
)
}
export default Dashboard;

View File

@ -1,11 +1,23 @@
import { useNavigate } from "react-router-dom";
import useAuth from "../../auth/auth";
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import logout from "../../auth/logout" import useLogout from "../../auth/logout"
const Home = () => { const Home = () => {
const { setToken } = useAuth();
const navigate = useNavigate();
const handleLogout = () => {
setToken(null);
navigate("/login");
};
return ( return (
<div> <div>
<h2>Home</h2> <h2>Home</h2>
<button onClick={logout()}> <button onClick={handleLogout}>
Logout Logout
</button> </button>
<nav> <nav>

View File

@ -2,24 +2,26 @@ import { useState } from "react";
import { useNavigate, useLocation } from "react-router-dom"; import { useNavigate, useLocation } from "react-router-dom";
import useAuth from "../../auth/auth"; import useAuth from "../../auth/auth";
const Login = () => { const Login = () => {
const { setToken: setAuth } = useAuth(); const { setToken } = useAuth();
const [username, setUsername] = useState(""); const [username, setUsername] = useState("");
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const from = location.state?.from?.pathname || "/home"; const from = location.state?.from?.pathname || "/";
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
// TODO: request to API // TODO: request to API
if (username === "admin" && password === "1234") { if (username === "admin" && password === "1234") {
setAuth(true); const token = "todo.jwt.token";
setToken(token);
navigate(from, { replace: true }); navigate(from, { replace: true });
} else { } else {
alert("Неверный логин или пароль"); alert("Wrong login or password");
} }
}; };

View File

@ -0,0 +1,9 @@
const Settings = () => {
return (
<div>
<h2>Settings</h2>
</div>
)
}
export default Settings;