auth with api
This commit is contained in:
38
src/app.tsx
38
src/app.tsx
@@ -1,21 +1,39 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import React, {useEffect} from 'react';
|
||||
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import { Dashboard } from './dashboard';
|
||||
|
||||
import { getConfigValue } from "@brojs/cli";
|
||||
import {ToastContainer} from "react-toastify";
|
||||
import 'react-toastify/dist/ReactToastify.css';
|
||||
|
||||
|
||||
import './index.css'
|
||||
|
||||
const BASE_API_URL = getConfigValue("enterfront.api");
|
||||
|
||||
// fetch(`${BASE_API_URL}/books/list`)
|
||||
import {displayMessage} from "./backend/notifications/notifications.js";
|
||||
import {MessageType} from "./backend/notifications/message";
|
||||
|
||||
const App = () => {
|
||||
useEffect(() => {
|
||||
document.title = 'Enterfront';
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const msg = localStorage.getItem('message');
|
||||
|
||||
if (!msg) return;
|
||||
|
||||
displayMessage(msg, MessageType.SUCCESS);
|
||||
localStorage.removeItem('message');
|
||||
}, []);
|
||||
|
||||
return(
|
||||
<BrowserRouter>
|
||||
<Dashboard />
|
||||
</BrowserRouter>
|
||||
<div>
|
||||
<BrowserRouter>
|
||||
<Dashboard />
|
||||
</BrowserRouter>
|
||||
|
||||
<ToastContainer/>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
45
src/backend/api.js
Normal file
45
src/backend/api.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import {getConfigValue} from "@brojs/cli";
|
||||
|
||||
export const BASE_API_URL = "http://localhost:8099" + getConfigValue("enterfront.api");
|
||||
|
||||
// fetch(`${BASE_API_URL}/books/list`)
|
||||
|
||||
export async function post(path, body) {
|
||||
const res = await fetch(`${BASE_API_URL}${path}`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
|
||||
if (res.status === 200) {
|
||||
const data = await res.json();
|
||||
console.log("Received post:", data);
|
||||
|
||||
return {ok: true, data: data};
|
||||
} else {
|
||||
const errorData = await res.json();
|
||||
console.log("Error during post:", errorData.message);
|
||||
|
||||
return {ok: false, data: errorData};
|
||||
}
|
||||
}
|
||||
|
||||
export async function get(path){
|
||||
const res = await fetch(`${BASE_API_URL}${path}`, {
|
||||
method: "GET"
|
||||
});
|
||||
|
||||
if (res.status === 200) {
|
||||
const data = await res.json();
|
||||
console.log("Received get:", data);
|
||||
|
||||
return {ok: true, data: data};
|
||||
} else {
|
||||
const errorData = await res.json();
|
||||
console.log("Error during get:", errorData.message);
|
||||
|
||||
return {ok: false, data: errorData};
|
||||
}
|
||||
}
|
||||
6
src/backend/notifications/message.tsx
Normal file
6
src/backend/notifications/message.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
export enum MessageType {
|
||||
ERROR,
|
||||
SUCCESS,
|
||||
INFO,
|
||||
WARN
|
||||
}
|
||||
28
src/backend/notifications/notifications.js
Normal file
28
src/backend/notifications/notifications.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import {toast} from "react-toastify";
|
||||
import {MessageType} from "./message.tsx";
|
||||
|
||||
export const displayMessage = (message, type) => {
|
||||
switch (type) {
|
||||
default:
|
||||
case MessageType.ERROR:
|
||||
toast.error(message, {
|
||||
position: 'bottom-right',
|
||||
});
|
||||
break;
|
||||
case MessageType.INFO:
|
||||
toast.info(message, {
|
||||
position: 'bottom-right',
|
||||
});
|
||||
break;
|
||||
case MessageType.SUCCESS:
|
||||
toast.success(message, {
|
||||
position: 'bottom-right',
|
||||
});
|
||||
break;
|
||||
case MessageType.WARN:
|
||||
toast.warn(message, {
|
||||
position: 'bottom-right',
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,13 @@ import ActionButton from "./ActionButton.jsx";
|
||||
const AccountButtons = (props) => {
|
||||
return (
|
||||
<div className="account-buttons">
|
||||
<ActionButton title={"Exit"} action={props.exitHandler}/>
|
||||
<ActionButton title={"Change Name"} action={props.changeNameHandler}/>
|
||||
<ActionButton title={"Change Pass"} action={props.changePassHandler}/>
|
||||
|
||||
{props.registered ? (
|
||||
<>
|
||||
<ActionButton title={"Exit"} action={props.exitHandler}/>
|
||||
<ActionButton title={"Change Name"} action={props.changeNameHandler}/>
|
||||
<ActionButton title={"Change Pass"} action={props.changePassHandler}/>
|
||||
</>
|
||||
) : null}
|
||||
<a className="MyButton mclaren-regular" href={URLs.home.url}>Back</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
18
src/components/account/HelloItem.jsx
Normal file
18
src/components/account/HelloItem.jsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import React from 'react';
|
||||
|
||||
const HelloItem = (props) => {
|
||||
return (
|
||||
<div className="hello-item-class">
|
||||
{!!props.nickname ? (
|
||||
<>
|
||||
<h1 className="mclaren-regular">Hello, {props.nickname}!</h1>
|
||||
<p className="mclaren-regular">Your ID: {props.id}</p>
|
||||
</>
|
||||
) : (
|
||||
<p className="mclaren-regular">You don't have account :(</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default HelloItem;
|
||||
@@ -3,6 +3,8 @@
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.account-buttons a {
|
||||
@@ -20,10 +22,33 @@
|
||||
color: black;
|
||||
}
|
||||
|
||||
.hello-item-class {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.hello-item-class h1 {
|
||||
font-size: 4vw;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.hello-item-class p {
|
||||
font-size: 1.5vw;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
.account-buttons a {
|
||||
font-size: 2.5vh;
|
||||
width: 60vw;
|
||||
margin-top: 3vh;
|
||||
}
|
||||
|
||||
.hello-item-class h1 {
|
||||
font-size: 5vh;
|
||||
}
|
||||
|
||||
.hello-item-class p {
|
||||
font-size: 2vh;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,53 @@
|
||||
import React from "react";
|
||||
import React, {useEffect, useState} from "react";
|
||||
import AccountButtons from "../components/account/AccountButtons.jsx";
|
||||
import userIcon from "../../images/user.svg";
|
||||
import {get} from "../backend/api";
|
||||
import {displayMessage} from "../backend/notifications/notifications";
|
||||
import {MessageType} from "../backend/notifications/message";
|
||||
import HelloItem from "../components/account/HelloItem.jsx";
|
||||
|
||||
const Account = () => {
|
||||
const exitHandler = () => {}
|
||||
const changeNameHandler = () => {}
|
||||
const changePassHandler = () => {}
|
||||
const exitHandler = () => {
|
||||
localStorage.removeItem("username");
|
||||
localStorage.removeItem("token");
|
||||
|
||||
localStorage.setItem("message", "Exited successfully!");
|
||||
window.location.href = "/";
|
||||
}
|
||||
const changeNameHandler = () => {}
|
||||
const changePassHandler = () => {}
|
||||
|
||||
const [nickname, setNickname] = useState("");
|
||||
const [id, setId] = useState("");
|
||||
|
||||
async function getUser() {
|
||||
const username = localStorage.getItem("username");
|
||||
if (!username) {
|
||||
displayMessage("You're not logged in!", MessageType.WARN);
|
||||
return;
|
||||
}
|
||||
|
||||
const {ok, data} = await get('/auth/' + username);
|
||||
if (!ok) {
|
||||
displayMessage("Some error with auth", MessageType.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
setNickname(data.user.nickname);
|
||||
setId(username);
|
||||
}
|
||||
|
||||
useEffect(() => {getUser().then()}, [])
|
||||
|
||||
return (
|
||||
<div className="account-items">
|
||||
<img src={userIcon} alt="user" />
|
||||
<HelloItem nickname={nickname} id={id} />
|
||||
<AccountButtons
|
||||
exitHandler={exitHandler}
|
||||
changeNameHandler={changeNameHandler}
|
||||
changePassHandler={changePassHandler}
|
||||
registered={!!nickname}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -3,12 +3,41 @@ import InputField from "../components/reg/InputField.jsx";
|
||||
import LoginButtons from "../components/reg/LoginButtons.jsx";
|
||||
import LoginTitle from "../components/reg/loginTitle.jsx";
|
||||
|
||||
import {MessageType} from "../backend/notifications/message.tsx";
|
||||
import {displayMessage} from "../backend/notifications/notifications.js";
|
||||
import {post} from "../backend/api.js";
|
||||
|
||||
const SignIn = () => {
|
||||
const [name, setName] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
|
||||
const submit = (e) => {
|
||||
console.log('Sign In!')
|
||||
const [nameErrorsCounter, setNameErrorsCounter] = useState(0);
|
||||
|
||||
async function submit() {
|
||||
console.log('Sign In!')
|
||||
|
||||
const {ok, data} = await post('/auth/login', {name: name, password: password});
|
||||
|
||||
if (!ok) {
|
||||
displayMessage(data.message, MessageType.ERROR);
|
||||
|
||||
if (nameErrorsCounter >= 1) {
|
||||
displayMessage("Note that you need to enter your ID name", MessageType.INFO);
|
||||
setNameErrorsCounter(0);
|
||||
} else {
|
||||
setNameErrorsCounter(nameErrorsCounter + 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.setItem('token', data.token);
|
||||
localStorage.setItem('username', name);
|
||||
|
||||
setNameErrorsCounter(0);
|
||||
|
||||
localStorage.setItem('message', 'Successfully logged in!');
|
||||
window.location.href = "/";
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -2,20 +2,59 @@ import React, {useState} from 'react';
|
||||
import InputField from "../components/reg/InputField.jsx";
|
||||
import LoginButtons from "../components/reg/LoginButtons.jsx";
|
||||
import LoginTitle from "../components/reg/loginTitle.jsx";
|
||||
import {post} from "../backend/api";
|
||||
import {displayMessage} from "../backend/notifications/notifications";
|
||||
import {MessageType} from "../backend/notifications/message";
|
||||
|
||||
|
||||
const SignUp = () => {
|
||||
const [name, setName] = useState("");
|
||||
const [nickname, setNickname] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [repeatPassword, setRepeatPassword] = useState("");
|
||||
|
||||
const submit = (e) => {
|
||||
console.log('Sign Up!')
|
||||
async function login(name, password) {
|
||||
const {ok, data} = await post('/auth/login', {name: name, password: password});
|
||||
return {loginStatus: ok, loginData: data};
|
||||
}
|
||||
|
||||
async function submit () {
|
||||
console.log('Sign Up!');
|
||||
|
||||
if (password !== repeatPassword) {
|
||||
displayMessage("Passwords don't match", MessageType.WARN);
|
||||
return;
|
||||
}
|
||||
|
||||
const {ok, data} = await post('/auth/reg',
|
||||
{name: name, password: password, nickname: nickname});
|
||||
|
||||
if (!ok) {
|
||||
displayMessage(data.message, MessageType.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
const { loginStatus, loginData } = await login(name, password);
|
||||
|
||||
console.log(loginStatus, loginData)
|
||||
|
||||
if (!loginStatus) {
|
||||
displayMessage(loginData.message, MessageType.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.setItem('token', loginData.token);
|
||||
localStorage.setItem('username', name);
|
||||
|
||||
localStorage.setItem('message', 'Successfully signed up!');
|
||||
window.location.href = "/";
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="LoginList">
|
||||
<LoginTitle/>
|
||||
<InputField title="Name" setValue={setName} value={name}/>
|
||||
<InputField title="Nickname (for others)" setValue={setNickname} value={nickname}/>
|
||||
<InputField title="Password" setValue={setPassword} value={password}/>
|
||||
<InputField title="Repeat Password" setValue={setRepeatPassword} value={repeatPassword}/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user