This commit is contained in:
2025-09-03 17:43:44 +03:00
parent a918b831a7
commit 28ffe00464
7 changed files with 126 additions and 253 deletions

View File

@ -1,4 +1,4 @@
import { BrowserRouter as Router, Routes, Route, Navigate, Outlet, useLocation } from 'react-router-dom'; import { BrowserRouter as Router, Routes, Route, Outlet, useLocation, useNavigate } from 'react-router-dom';
import {useEffect, useState } from "react"; import {useEffect, useState } from "react";
import { ToastContainer } from "react-toastify"; import { ToastContainer } from "react-toastify";
@ -20,49 +20,14 @@ import Settings from "./pages/settings/settings"
import useAuth from './auth/auth'; import useAuth from './auth/auth';
function App() {
const theme = themeFromSourceColor(argbFromHex("ffddaf"));
const systemDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
applyTheme(theme, { target: document.body, dark: systemDark });
return (
<AuthProvider>
<>
<ToastContainer
position="top-right"
autoClose={2000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick={false}
rtl={false}
theme={"light"}
// transition={Bounce}
/>
<Router>
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route element={<PrivateRoute />}>
<Route path='/' element={<Home />} />
<Route path='/dashboard' element={<Dashboard />} />
<Route path='/settings' element={<Settings />} />
</Route>
<Route path="*" element={<div>404</div>} />
</Routes>
</Router>
</>
</AuthProvider>
);
}
const PrivateRoute = () => { const PrivateRoute = () => {
const { token, loading } = useAuth(); const { token, loading } = useAuth();
const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const [checked, setChecked] = useState(false); const [checked, setChecked] = useState(false);
const [isValid, setIsValid] = useState(false); const [isValid, setIsValid] = useState(false);
useEffect(() => { useEffect(() => {
const checkAuth = async () => { const checkAuth = async () => {
if (!token) { if (!token) {
@ -83,10 +48,48 @@ const PrivateRoute = () => {
return <div>Checking server availability...</div>; return <div>Checking server availability...</div>;
} }
if (!isValid) {
navigate(`/login?to=${location.pathname}`);
}
else {
return <Outlet />
}
}
function App() {
const theme = themeFromSourceColor(argbFromHex("ffddaf"));
const systemDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
applyTheme(theme, { target: document.body, dark: systemDark });
return ( return (
isValid <AuthProvider>
? <Outlet /> <>
: <Navigate to="/login" state={{ from: location }} replace /> <ToastContainer
position="top-right"
autoClose={2000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick={false}
rtl={false}
theme={systemDark ? "light" : "dark"}
// transition={Bounce}
/>
<Router>
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route element={<PrivateRoute />}>
<Route path='/' element={<Home />} />
<Route path='/dashboard' element={<Dashboard />} />
<Route path='/settings' element={<Settings />} />
</Route>
<Route path="*" element={<div>404</div>} />
</Routes>
</Router>
</>
</AuthProvider>
); );
} }

View File

@ -5,7 +5,6 @@
} }
.form-field input { .form-field input {
width: 100%;
padding: 12px; padding: 12px;
border: 2px solid #ddd; border: 2px solid #ddd;
border-radius: 8px; border-radius: 8px;

View File

@ -20,5 +20,10 @@
} }
body { body {
display: flex; margin: 0;
padding: 0;
width: 100vw;
max-width: 100%;
height: 100vh;
max-height: 100%;
} }

View File

@ -1,16 +1,34 @@
.login-div { .login {
display: flex; display: flex;
height: 100%; width: 100vw;
justify-content: flex-end; height: 100vh;
align-items: center; max-width:100%;
border: 1px solid green; justify-content: space-between;
} }
.login-right-div { .login-right {
display: flex; display: flex;
height: 100%; height: 100%;
justify-content: flex-end;
align-items: center;
flex-direction: column; flex-direction: column;
border: 1px solid blue; justify-content: center;
margin-left: auto;
margin-right: 5vw;
margin-left: 5vw;
}
.login-left {
overflow: hidden;
display: flex;
background-color: black;
height: 100%;
justify-content: center;
margin-right: auto;
}
.login-block {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
} }

View File

@ -41,52 +41,55 @@ const Login = () => {
}; };
return ( return (
<div className="login-right-div"> <div className="login">
<h2 <div className="login-left">
style={{ <video className='videoTag' autoPlay loop muted>
display: "flex" <source src={"./test.mp4"} type='video/mp4' />
}} </video>
> </div>
Login <div className="login-right">
</h2> <div className="login-block">
<form onSubmit={handleSubmit} <h2>
style={{ Login
flexDirection: "column", </h2>
display: "flex", <form onSubmit={handleSubmit}
gap: "10px", style={{
alignItems: "center", flexDirection: "column",
}} display: "flex",
noValidate gap: "10px",
> alignItems: "center",
<FormField }}
type="text" noValidate
placeholder="Username" >
value={username} <FormField
onChange={(e) => setUsername(e.target.value)} type="text"
required placeholder="Username"
showError={usernameEmpty} value={username}
errorMessage="Please enter your username" onChange={(e) => setUsername(e.target.value)}
className="test1" required
/> showError={usernameEmpty}
<FormField errorMessage="Please enter your username"
type="password" />
placeholder="Password" <FormField
value={password} type="password"
onChange={(e) => setPassword(e.target.value)} placeholder="Password"
required value={password}
showError={passwordEmpty} onChange={(e) => setPassword(e.target.value)}
errorMessage="Please enter your password" required
className="test2" showError={passwordEmpty}
/> errorMessage="Please enter your password"
<button type="submit" />
style={{ <button type="submit"
display: "flex", style={{
marginTop: "10px" display: "flex",
}} marginTop: "10px"
> }}
Login >
</button> Login
</form> </button>
</form>
</div>
</div>
</div> </div>
); );
}; };

View File

@ -1,66 +0,0 @@
div {
margin: auto;
text-align:center;
}
input {
margin: auto;
text-align: center;
}
button {
/* margin: auto; */
background-color: var(--background_dark);
color: var(--text_dark);
border: 2px solid black;
border-color: var(--buttons-main-color);
padding: 16px 32px;
text-align: center;
text-decoration: none;
font-size: 16px;
cursor: pointer;
border-radius: 12px;
transition-duration: 0.4s;
}
button:hover {
background-color: var(--buttons-main-color);
color: var(--text_dark);
}
button:active {
background-color: var(--buttons-press-color);
color: var(--text_dark);
}
button span {
cursor: pointer;
display: inline-block;
position: relative;
transition: 0.5s;
}
button span:after {
/* content: '\00bb'; */
content: '\2317';
position: absolute;
opacity: 0;
top: 0;
right: -20px;
transition: 0.5s;
}
button:hover span {
padding-right: 25px;
}
button:hover span:after {
opacity: 1;
right: 0;
}
.bold-text {
font-weight: bold;
}

View File

@ -1,89 +0,0 @@
import React from "react"
import './login.css'
import { useLocation, useNavigate } from 'react-router-dom';
const Login = () => {
state = {
username: "",
password: "",
}
const { setAuth } = useContext(AuthContext); // используем контекст для получения значений isAuthenticated и setAuth
const navigate = useNavigate(); // используем хук useNavigate для навигации по маршрутам
const location = useLocation(); // используем хук useLocation для получения текущего маршрута
// получаем маршрут, на который нужно перенаправить пользователя после авторизации
const from = location.state?.from?.pathname || '/';
validateString = (text:string) => {
return text ? text : false
}
return (
<div>
<div>
<input
type="text"
name="username"
placeholder="Username"
onChange={(e) => this.setState({username: e.target.value})}
onBlur={(e) => this.setState({username: e.target.value})}
/>
</div>
<div>
<input
type="text"
name="password"
placeholder="Password"
onChange={(e) => this.setState({password: e.target.value})}
onBlur={(e) => this.setState({password: e.target.value})}
color="#FF0000"
/>
</div>
<div className="bold-text">
Your username is: {this.state.username}
</div>
<div>
{
(() => {
const r: string | boolean = this.validateString(this.state.username);
if (r) {
return r
}
return "invalid";
})()
}
</div>
<div className="bold-text">
Your password is: {this.state.password}
</div>
<div>
{
(() => {
const r: string | boolean = this.validateString(this.state.password);
if (r) {
return r
}
return "invalid";
})()
}
</div>
<button
onClick={() =>
this.validateString(this.state.username)
&&
this.validateString(this.state.password)
? false
: alert("Please enter not blank username and password")
}
>
<span>
Login
</span>
</button>
</div>
)
}
export default Login;