I did a thing
- Fixed random things. - Added a footer. - Changed menu styling to be more pleasing. - Made menu turn into hamburger dropdown menu so this dashboard is somewhat okay to use on mobile. - Made a log out menu button for the mobile people. - Made the entire layout work on mobile. - Fixed the shit I broke along the way. It's 2:30am now, time for bed.
This commit is contained in:
parent
d9a9ecafbb
commit
2dfb996cde
@ -8,6 +8,7 @@
|
|||||||
"react-router": "^6.4.3",
|
"react-router": "^6.4.3",
|
||||||
"react-router-dom": "^6.4.3",
|
"react-router-dom": "^6.4.3",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
|
"react-top-loading-bar": "^2.3.1",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -55,7 +55,7 @@ function App() {
|
|||||||
</div>
|
</div>
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
<div className='main-content'>
|
<div className={`main-content ${user ? "" : "login"}`}>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<Routes>
|
<Routes>
|
||||||
|
|
||||||
@ -87,7 +87,10 @@ function App() {
|
|||||||
|
|
||||||
</Routes>
|
</Routes>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
|
|
||||||
|
<div className={`footer ${user ? "" : "login"}`}>
|
||||||
|
<p className='m-0'>Made with ❤️ by <a href="https://corgi.wtf" target="_blank" rel="noreferrer">Navy.gif</a> | CSS by <a href="https://d3vision.dev" target="_blank" rel="noreferrer">D3vision</a></p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
@ -2,6 +2,9 @@ import React from 'react';
|
|||||||
import '../css/components/Sidebar.css';
|
import '../css/components/Sidebar.css';
|
||||||
import NavLink from '../structures/NavLink';
|
import NavLink from '../structures/NavLink';
|
||||||
import logoImg from '../img/logo.png';
|
import logoImg from '../img/logo.png';
|
||||||
|
import { useNavigate } from "react-router";
|
||||||
|
import { useLoginContext } from "../structures/UserContext";
|
||||||
|
import { clearSession, post } from "../util/Util";
|
||||||
|
|
||||||
const Sidebar = ({children}) => {
|
const Sidebar = ({children}) => {
|
||||||
|
|
||||||
@ -15,9 +18,32 @@ const expandMenu = (event) => {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.target.parentElement.classList.toggle("open");
|
event.target.parentElement.classList.toggle("open");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const expandMobileMenu = (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.target.parentElement.parentElement.classList.toggle("show-menu");
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeMobileMenu = (event) => {
|
||||||
|
if(event.target.classList.contains("sidebar-menu-item-carrot")) return;
|
||||||
|
event.target.getRootNode().querySelector(".sidebar").classList.remove("show-menu");
|
||||||
|
};
|
||||||
|
|
||||||
// Nav menu
|
// Nav menu
|
||||||
const SidebarMenu = ({menuItems = [], children}) => {
|
const SidebarMenu = ({menuItems = [], children}) => {
|
||||||
|
const [user, updateUser] = useLoginContext();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
if (!user) return;
|
||||||
|
|
||||||
|
const logOut = async () => {
|
||||||
|
const response = await post('/api/logout');
|
||||||
|
if (response.status === 200) {
|
||||||
|
clearSession();
|
||||||
|
updateUser();
|
||||||
|
navigate('/login');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const elements = [];
|
const elements = [];
|
||||||
for (const menuItem of menuItems) {
|
for (const menuItem of menuItems) {
|
||||||
@ -26,10 +52,10 @@ const SidebarMenu = ({menuItems = [], children}) => {
|
|||||||
let subElements = null;
|
let subElements = null;
|
||||||
if (subItems.length) subElements = subItems.map(({ label, to, relative = true }) => {
|
if (subItems.length) subElements = subItems.map(({ label, to, relative = true }) => {
|
||||||
if(relative) to = `${menuItem.to}${to}`;
|
if(relative) to = `${menuItem.to}${to}`;
|
||||||
return <NavLink className='sidebar-menu-item sidebar-menu-child-item' activeClassName='active' to={to} key={label}>{label}</NavLink>;
|
return <NavLink className='sidebar-menu-item sidebar-menu-child-item' onClick={closeMobileMenu} activeClassName='active' to={to} key={label}>{label}</NavLink>;
|
||||||
});
|
});
|
||||||
elements.push(<div key={label} className='parent-menu'>
|
elements.push(<div key={label} className='parent-menu'>
|
||||||
<NavLink className={`sidebar-menu-item ${subElements?.length ? 'has-children' : ''}`} activeClassName='active' {...rest} key={label}>
|
<NavLink className={`sidebar-menu-item ${subElements?.length ? 'has-children' : ''}`} onClick={closeMobileMenu} activeClassName='active' {...rest} key={label}>
|
||||||
{label}{subElements && <i className="sidebar-menu-item-carrot" onClick={expandMenu}></i>}
|
{label}{subElements && <i className="sidebar-menu-item-carrot" onClick={expandMenu}></i>}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
{subElements && <div className='sidebar-menu-child-wrapper'>
|
{subElements && <div className='sidebar-menu-child-wrapper'>
|
||||||
@ -39,11 +65,14 @@ const SidebarMenu = ({menuItems = [], children}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return <div className='sidebar-menu'>
|
return <div className='sidebar-menu'>
|
||||||
|
<span className='hamburger' onClick={expandMobileMenu}></span>
|
||||||
<img className="sidebar-logo" src={logoImg}/>
|
<img className="sidebar-logo" src={logoImg}/>
|
||||||
<hr/>
|
|
||||||
{elements}
|
{elements}
|
||||||
|
|
||||||
{children}
|
{children}
|
||||||
|
<div className="parent-menu log-out-menu-item">
|
||||||
|
<a className="sidebar-menu-item" onClick={logOut} href="#">Log Out</a>
|
||||||
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -22,12 +22,27 @@ header {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: var(--background-secondary);
|
background-color: var(--background-secondary);
|
||||||
|
padding-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page{
|
.page{
|
||||||
padding: 0 15px 0 245px;
|
padding: 0 15px 0 245px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.footer{
|
||||||
|
padding: 15px 15px 15px 245px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px){
|
||||||
|
.footer{
|
||||||
|
padding: 15px;
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ld{
|
.ld{
|
||||||
min-height: 140px;
|
min-height: 140px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -3,22 +3,29 @@
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
width: 230px;
|
width: 230px;
|
||||||
padding: 1rem 0;
|
padding: 1rem 0;
|
||||||
|
z-index: 1000;
|
||||||
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-menu {
|
.sidebar-menu {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
.sidebar-menu .parent-menu:first-of-type{
|
||||||
|
border-top: 1px solid #232323;
|
||||||
|
}
|
||||||
|
|
||||||
.parent-menu{
|
.parent-menu{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
border-bottom: 1px solid #232323;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-logo{
|
.sidebar-logo{
|
||||||
margin: auto;
|
margin: auto;
|
||||||
margin-top: 1rem;
|
margin-top: 2.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 3.5rem;
|
||||||
max-width: 170px;
|
max-height: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-menu-item-carrot{
|
.sidebar-menu-item-carrot{
|
||||||
@ -33,15 +40,16 @@
|
|||||||
}
|
}
|
||||||
.sidebar-menu-item.has-children.open .sidebar-menu-item-carrot{
|
.sidebar-menu-item.has-children.open .sidebar-menu-item-carrot{
|
||||||
transform: rotate(-90deg);
|
transform: rotate(-90deg);
|
||||||
transition: transform ease-in-out 0.15s;
|
transition: transform ease-in-out 0.2s;
|
||||||
}
|
}
|
||||||
.sidebar-menu-item.has-children.active .sidebar-menu-item-carrot{
|
.sidebar-menu-item.has-children.active .sidebar-menu-item-carrot{
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
.sidebar-menu-item.has-children.open + .sidebar-menu-child-wrapper{
|
.sidebar-menu-item.has-children.open + .sidebar-menu-child-wrapper{
|
||||||
height: 100%;
|
height: 100%;
|
||||||
opacity: 1;
|
/* opacity: 1; */
|
||||||
transition: max-height 0.5s ease-in-out, opacity 0.25s ease-in-out;
|
/* transition: max-height 0.5s ease-in-out, opacity 0.25s ease-in-out; */
|
||||||
|
transition: max-height ease-in-out 0.25s;
|
||||||
max-height: 600px;
|
max-height: 600px;
|
||||||
}
|
}
|
||||||
.sidebar-menu-item.sidebar-menu-item.has-children{
|
.sidebar-menu-item.sidebar-menu-item.has-children{
|
||||||
@ -58,8 +66,9 @@
|
|||||||
z-index: 0;
|
z-index: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
max-height: 0;
|
max-height: 0;
|
||||||
opacity: 0;
|
/* opacity: 0; */
|
||||||
transition: max-height 0.25s ease-in-out, opacity 0.25s ease-in-out;
|
/* transition: max-height 0.25s ease-in-out, opacity 0.25s ease-in-out; */
|
||||||
|
transition: max-height ease-in-out 0.25s;
|
||||||
}
|
}
|
||||||
.sidebar hr{
|
.sidebar hr{
|
||||||
margin-left: 2rem;
|
margin-left: 2rem;
|
||||||
@ -67,7 +76,7 @@
|
|||||||
}
|
}
|
||||||
.sidebar-menu-item {
|
.sidebar-menu-item {
|
||||||
margin: 0px 0px 0px -20px;
|
margin: 0px 0px 0px -20px;
|
||||||
padding: 14px 0px 14px calc(35px + 2rem);
|
padding: 15px 0px 15px calc(35px + 2rem);
|
||||||
background-color: var(--dark-blue);
|
background-color: var(--dark-blue);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@ -102,4 +111,60 @@
|
|||||||
padding-left: 35px !important;
|
padding-left: 35px !important;
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
.hamburger{
|
||||||
|
display: none;
|
||||||
|
visibility: hidden;
|
||||||
|
position: absolute;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='48px' height='48px' viewBox='0 0 48 48'%3E%3Ctitle%3E70 Basic icons by Xicons.co%3C/title%3E%3Cpath d='M41,14H7a2,2,0,0,1,0-4H41A2,2,0,0,1,41,14Z' fill='%23f5f5f5'/%3E%3Cpath d='M41,26H7a2,2,0,0,1,0-4H41A2,2,0,0,1,41,26Z' fill='%23f5f5f5'/%3E%3Cpath d='M41,38H7a2,2,0,0,1,0-4H41A2,2,0,0,1,41,38Z' fill='%23f5f5f5'/%3E%3C/svg%3E");
|
||||||
|
background-position: center;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
right: 30px;
|
||||||
|
margin-top: calc(0.75rem + 12px);
|
||||||
|
margin-bottom: calc(1.75rem + 12px);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.hamburger:hover{
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
.log-out-menu-item{
|
||||||
|
display: none;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 768px){
|
||||||
|
.page{
|
||||||
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
.sidebar{
|
||||||
|
width: 100%;
|
||||||
|
max-height: 95px;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: max-height ease-in-out 0.25s;
|
||||||
|
}
|
||||||
|
.sidebar.show-menu{
|
||||||
|
max-height: 100vh;
|
||||||
|
transition: max-height ease-in-out 0.25s;
|
||||||
|
}
|
||||||
|
.sidebar-logo{
|
||||||
|
max-height: 60px;
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
margin-bottom: 1.75rem;
|
||||||
|
margin-left: 30px;
|
||||||
|
max-width: 82vw;
|
||||||
|
}
|
||||||
|
.hamburger{
|
||||||
|
display: block;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
.main-content{
|
||||||
|
margin-top: 95px;
|
||||||
|
}
|
||||||
|
header{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.log-out-menu-item{
|
||||||
|
display: flex;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
}
|
}
|
@ -34,7 +34,9 @@ a:hover:not(.button){
|
|||||||
opacity: 1 !important;
|
opacity: 1 !important;
|
||||||
color: #C4C4C4;
|
color: #C4C4C4;
|
||||||
}
|
}
|
||||||
|
a:hover{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
details[open] summary ~ * {
|
details[open] summary ~ * {
|
||||||
animation: sweep .15s ease-in-out;
|
animation: sweep .15s ease-in-out;
|
||||||
}
|
}
|
||||||
|
@ -25,4 +25,14 @@ input{
|
|||||||
.registerText{
|
.registerText{
|
||||||
line-height: 1.6em;
|
line-height: 1.6em;
|
||||||
padding: 18px 10px 4px 10px;
|
padding: 18px 10px 4px 10px;
|
||||||
|
}
|
||||||
|
.footer.login{
|
||||||
|
padding: 15px !important;
|
||||||
|
position: absolute;
|
||||||
|
margin: auto;
|
||||||
|
width: 100%;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.main-content.login{
|
||||||
|
margin-top: 0;
|
||||||
}
|
}
|
@ -35,7 +35,7 @@ const Profile = () => {
|
|||||||
|
|
||||||
return <div className="row">
|
return <div className="row">
|
||||||
|
|
||||||
<div className="col-6">
|
<div className="col-6-lg col-12">
|
||||||
|
|
||||||
<h3>Profile</h3>
|
<h3>Profile</h3>
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ const Profile = () => {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-6">
|
<div className="col-6-lg col-12">
|
||||||
<h3>Settings</h3>
|
<h3>Settings</h3>
|
||||||
|
|
||||||
<p><b>ID:</b> {user.id}</p>
|
<p><b>ID:</b> {user.id}</p>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState, useRef } from "react";
|
||||||
import { Route, Routes, useNavigate } from "react-router";
|
import { Route, Routes, useNavigate } from "react-router";
|
||||||
import '../css/pages/Login.css';
|
import '../css/pages/Login.css';
|
||||||
import logoImg from '../img/logo.png';
|
import logoImg from '../img/logo.png';
|
||||||
import { useLoginContext } from "../structures/UserContext";
|
import { useLoginContext } from "../structures/UserContext";
|
||||||
|
import LoadingBar from 'react-top-loading-bar';
|
||||||
import { fetchUser, post } from "../util/Util";
|
import { fetchUser, post } from "../util/Util";
|
||||||
|
|
||||||
const loginMethods = [
|
const loginMethods = [
|
||||||
@ -18,9 +19,10 @@ const CredentialFields = () => {
|
|||||||
const [, setUser] = useLoginContext();
|
const [, setUser] = useLoginContext();
|
||||||
const [fail, setFail] = useState(false);
|
const [fail, setFail] = useState(false);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const ref = useRef(null);
|
||||||
|
|
||||||
const loginClick = async (event) => {
|
const loginClick = async (event) => {
|
||||||
|
ref.current.continuousStart();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const username = document.getElementById('username').value;
|
const username = document.getElementById('username').value;
|
||||||
const password = document.getElementById('password').value;
|
const password = document.getElementById('password').value;
|
||||||
@ -29,20 +31,23 @@ const CredentialFields = () => {
|
|||||||
const result = await post('/api/login', { username, password });
|
const result = await post('/api/login', { username, password });
|
||||||
|
|
||||||
if (![200, 302].includes(result.status)) {
|
if (![200, 302].includes(result.status)) {
|
||||||
|
ref.current.complete();
|
||||||
setFail(true);
|
setFail(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.data?.twoFactor) {
|
if (!result.data?.twoFactor) {
|
||||||
setUser(await fetchUser());
|
setUser(await fetchUser());
|
||||||
|
ref.current.complete();
|
||||||
return navigate('/home');
|
return navigate('/home');
|
||||||
}
|
}
|
||||||
|
ref.current.complete();
|
||||||
return navigate('verify');
|
return navigate('verify');
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
|
<LoadingBar color='#2685ff' ref={ref} />
|
||||||
<div className="is-center">
|
<div className="is-center">
|
||||||
<img className="logoImg mb-4" src={logoImg}></img>
|
<img className="logoImg mb-4" src={logoImg}></img>
|
||||||
</div>
|
</div>
|
||||||
@ -85,24 +90,34 @@ const TwoFactor = () => {
|
|||||||
const [fail, setFail] = useState(false);
|
const [fail, setFail] = useState(false);
|
||||||
const [, setUser] = useLoginContext();
|
const [, setUser] = useLoginContext();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const ref = useRef(null);
|
||||||
|
|
||||||
const twoFactorClick = async () => {
|
const twoFactorClick = async () => {
|
||||||
const code = document.getElementById('2faCode').value;
|
const code = document.getElementById('2faCode').value;
|
||||||
if (!code) return;
|
if (!code) return;
|
||||||
|
ref.current.continuousStart();
|
||||||
const result = await post('/api/login/verify', { code });
|
const result = await post('/api/login/verify', { code });
|
||||||
if (result.status === 200) {
|
if (result.status === 200) {
|
||||||
setUser(await fetchUser());
|
setUser(await fetchUser());
|
||||||
|
ref.current.complete();
|
||||||
return navigate('/home');
|
return navigate('/home');
|
||||||
}
|
}
|
||||||
|
ref.current.complete();
|
||||||
setFail(true);
|
setFail(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
return <div className="card mb-3 is-center dir-column">
|
return <div>
|
||||||
{fail ? <p>Invalid code</p> : null}
|
<LoadingBar color='#2685ff' ref={ref} />
|
||||||
<h2>Verification code</h2>
|
<div className="is-center">
|
||||||
<input autoComplete='off' placeholder='Code' required id='2faCode' type='password' />
|
<img className="logoImg mb-4" src={logoImg}></img>
|
||||||
<button onClick={twoFactorClick}>Enter</button>
|
</div>
|
||||||
|
|
||||||
|
<div className="card mb-3 is-center dir-column">
|
||||||
|
<h2>Verification Code</h2>
|
||||||
|
{fail ? <p className="mt-0">Invalid code</p> : null}
|
||||||
|
<input autoComplete='off' placeholder='Your 2FA code...' required id='2faCode' type='password' />
|
||||||
|
<button className="button primary m-3" onClick={twoFactorClick}>Enter</button>
|
||||||
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,32 +1,41 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState, useRef } from "react";
|
||||||
import { useNavigate, useSearchParams } from "react-router-dom";
|
import { useNavigate, useSearchParams } from "react-router-dom";
|
||||||
import { post } from "../util/Util";
|
import { post } from "../util/Util";
|
||||||
import '../css/pages/Register.css';
|
import '../css/pages/Register.css';
|
||||||
import logoImg from '../img/logo.png';
|
import logoImg from '../img/logo.png';
|
||||||
|
import LoadingBar from 'react-top-loading-bar';
|
||||||
|
|
||||||
const Register = () => {
|
const Register = () => {
|
||||||
|
|
||||||
const [error, setError] = useState();
|
const [error, setError] = useState();
|
||||||
const [params] = useSearchParams();
|
const [params] = useSearchParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const ref = useRef(null);
|
||||||
|
|
||||||
document.body.classList.add('bg-triangles');
|
document.body.classList.add('bg-triangles');
|
||||||
const code = params.get('code');
|
const code = params.get('code');
|
||||||
|
|
||||||
const submit = async (event) => {
|
const submit = async (event) => {
|
||||||
|
ref.current.continuousStart();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const username = document.getElementById('username').value;
|
const username = document.getElementById('username').value;
|
||||||
const password = document.getElementById('password').value;
|
const password = document.getElementById('password').value;
|
||||||
if (!username.length || !password.length) return;
|
if (!username.length || !password.length) {
|
||||||
|
ref.current.complete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const response = await post('/api/register', { username, password, code });
|
const response = await post('/api/register', { username, password, code });
|
||||||
if (response.status !== 200) return setError(response.message);
|
if (response.status !== 200) {
|
||||||
|
ref.current.complete();
|
||||||
|
return setError(response.message);
|
||||||
|
}
|
||||||
|
ref.current.complete();
|
||||||
navigate('/login');
|
navigate('/login');
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return <div className="row is-center is-full-screen is-marginless">
|
return <div className="row is-center is-full-screen is-marginless">
|
||||||
|
<LoadingBar color='#2685ff' ref={ref} />
|
||||||
<div className='registerWrapper col-6 col-6-md col-3-lg'>
|
<div className='registerWrapper col-6 col-6-md col-3-lg'>
|
||||||
<div>
|
<div>
|
||||||
<div className="is-center">
|
<div className="is-center">
|
||||||
|
@ -7496,6 +7496,11 @@ react-scripts@5.0.1:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "^2.3.2"
|
fsevents "^2.3.2"
|
||||||
|
|
||||||
|
react-top-loading-bar@^2.3.1:
|
||||||
|
version "2.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-top-loading-bar/-/react-top-loading-bar-2.3.1.tgz#d727eb6aaa412eae52a990e5de9f33e9136ac714"
|
||||||
|
integrity sha512-rQk2Nm+TOBrM1C4E3e6KwT65iXyRSgBHjCkr2FNja1S51WaPulRA5nKj/xazuQ3x89wDDdGsrqkqy0RBIfd0xg==
|
||||||
|
|
||||||
react@^18.2.0:
|
react@^18.2.0:
|
||||||
version "18.2.0"
|
version "18.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
||||||
|
Loading…
Reference in New Issue
Block a user