Adds register page.
This commit is contained in:
@@ -5,6 +5,7 @@ import Login from './components/Login';
|
||||
import Gamenights from './components/Gamenights';
|
||||
import Gamenight from './components/Gamenight';
|
||||
import AdminPanel from './components/AdminPanel';
|
||||
import Register from './components/Register';
|
||||
|
||||
import { get_gamenights, get_games, unpack_api_result, login } from './api/Api';
|
||||
|
||||
@@ -21,20 +22,21 @@ function App() {
|
||||
const handleLogin = (input) => {
|
||||
unpack_api_result(login(input), setFlashData)
|
||||
.then(result => {
|
||||
setUser(result.user);
|
||||
localStorage.setItem(localStorageUserKey, JSON.stringify(result.user));
|
||||
})
|
||||
.then(() => setAppState('LoggedIn'))
|
||||
if(result !== undefined) {
|
||||
setUser(result.user);
|
||||
localStorage.setItem(localStorageUserKey, JSON.stringify(result.user));
|
||||
setAppState('LoggedIn')
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if(activeGamenightId !== null) {
|
||||
setAppState('GamenightDetails');
|
||||
} else {
|
||||
setAppState('LoggedIn')
|
||||
setAppState(user === null ? 'LoggedOut' : 'LoggedIn')
|
||||
}
|
||||
|
||||
}, [activeGamenightId])
|
||||
}, [activeGamenightId, user])
|
||||
|
||||
const onLogout = () => {
|
||||
setUser(null);
|
||||
@@ -50,8 +52,16 @@ function App() {
|
||||
setAppState('UserPage')
|
||||
}
|
||||
|
||||
const onRegister = () => {
|
||||
setAppState('RegisterPage')
|
||||
}
|
||||
|
||||
const onReset = () => {
|
||||
setAppState('LoggedIn')
|
||||
setAppState(user === null ? 'LoggedOut' : 'LoggedIn')
|
||||
}
|
||||
|
||||
const onRegistered = (user) => {
|
||||
setUser(user);
|
||||
}
|
||||
|
||||
const setFlash = (data) => {
|
||||
@@ -59,20 +69,28 @@ function App() {
|
||||
};
|
||||
|
||||
const refetchGamenights = () => {
|
||||
setUser({...user});
|
||||
unpack_api_result(get_gamenights(user.jwt), setFlashData)
|
||||
.then(result => {
|
||||
if (result !== undefined) {
|
||||
setGamenights(result.gamenights);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (appState === 'LoggedIn') {
|
||||
unpack_api_result(get_gamenights(user.jwt), setFlashData)
|
||||
.then(result => setGamenights(result.gamenights));
|
||||
refetchGamenights()
|
||||
}
|
||||
}, [appState])
|
||||
|
||||
useEffect(() => {
|
||||
if (appState === 'LoggedIn') {
|
||||
unpack_api_result(get_games(user.jwt), setFlashData)
|
||||
.then(result => setGames(result.games));
|
||||
.then(result => {
|
||||
if (result !== undefined) {
|
||||
setGames(result.games)
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [appState])
|
||||
|
||||
@@ -82,12 +100,22 @@ function App() {
|
||||
|
||||
let mainview;
|
||||
if(appState === 'LoggedOut') {
|
||||
return (
|
||||
mainview = (
|
||||
<div className="App">
|
||||
<Login onChange={handleLogin}/>
|
||||
</div>
|
||||
);
|
||||
} else if(appState === 'GamenightDetails') {
|
||||
} else if(appState === 'RegisterPage') {
|
||||
mainview = (
|
||||
<Register
|
||||
onRegistered={onRegistered}
|
||||
setFlash={setFlash}/>
|
||||
);
|
||||
} else if(appState === 'UserPage') {
|
||||
mainview = (
|
||||
<span>UserPage</span>
|
||||
)
|
||||
}else if(appState === 'GamenightDetails') {
|
||||
mainview = (
|
||||
<Gamenight
|
||||
gamenightId={activeGamenightId}
|
||||
@@ -117,6 +145,7 @@ function App() {
|
||||
<MenuBar
|
||||
user={user}
|
||||
onUser={onUser}
|
||||
onRegister={onRegister}
|
||||
onAdmin={onAdmin}
|
||||
onLogout={onLogout}
|
||||
onReset={onReset}/>
|
||||
|
||||
@@ -2,21 +2,18 @@
|
||||
import fetchResource from './FetchResource'
|
||||
|
||||
export function unpack_api_result(promise, onError) {
|
||||
promise.then(result => {
|
||||
return promise.then(result => {
|
||||
if(result.result !== 'Ok') {
|
||||
onError({
|
||||
type: 'Error',
|
||||
message: result.message
|
||||
});
|
||||
throw new Error(result.message);
|
||||
}
|
||||
return result;
|
||||
})
|
||||
.catch(error => {
|
||||
onError({
|
||||
onError({
|
||||
type: 'Error',
|
||||
message: `${error.status} ${error.message}`
|
||||
message: `${error.status === null ?? error.status} ${error.message}`
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
});
|
||||
}
|
||||
|
||||
export function get_gamenights(token) {
|
||||
@@ -116,4 +113,14 @@ export function delete_registration_token(token, registration_token_id) {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function register(registration_token, input) {
|
||||
return fetchResource(`api/register/${registration_token}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(input)
|
||||
});
|
||||
}
|
||||
@@ -47,11 +47,13 @@ function AddGameNight(props) {
|
||||
|
||||
unpack_api_result(post_gamenight(input, props.user.jwt), props.setFlash)
|
||||
.then(result => {
|
||||
setExpanded(false);
|
||||
setGameName("");
|
||||
setDate(null);
|
||||
if(result !== undefined) {
|
||||
setExpanded(false);
|
||||
setGameName("");
|
||||
setDate(null);
|
||||
}
|
||||
})
|
||||
.then(() => props.refetchGamenights())
|
||||
.then(() => props.refetchGamenights());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -38,14 +38,22 @@ function AdminPanel(props) {
|
||||
const refetchTokens = () => {
|
||||
if(props.user !== null) {
|
||||
unpack_api_result(get_registration_tokens(props.user.jwt), props.setFlash)
|
||||
.then(result => setRegistrationTokens(result.registration_tokens));
|
||||
}
|
||||
.then(result => {
|
||||
if(result !== undefined) {
|
||||
setRegistrationTokens(result.registration_tokens);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const deleteToken = (id) => {
|
||||
if(props.user !== null) {
|
||||
unpack_api_result(delete_registration_token(props.user.jwt, id), props.setFlash)
|
||||
.then(() => refetchTokens())
|
||||
.then(result => {
|
||||
if(result !== undefined) {
|
||||
refetchTokens();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +65,11 @@ function AdminPanel(props) {
|
||||
|
||||
if(props.user !== null) {
|
||||
unpack_api_result(add_registration_token(props.user.jwt, input), props.setFlash)
|
||||
.then(() => refetchTokens())
|
||||
.then(result => {
|
||||
if(result !== undefined) {
|
||||
refetchTokens();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +104,7 @@ function AdminPanel(props) {
|
||||
<div className="Add-GameNight">
|
||||
<form autoComplete="off" onSubmit={e => { e.preventDefault(); }}>
|
||||
<DateTimePicker
|
||||
label="Gamenight date and time"
|
||||
label="Token expires at"
|
||||
variant="standard"
|
||||
value={expires}
|
||||
onChange={setExpires}
|
||||
@@ -153,8 +165,8 @@ function AdminPanel(props) {
|
||||
e.stopPropagation();
|
||||
deleteToken(row.id)
|
||||
}}>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
|
||||
@@ -19,7 +19,11 @@ function Gamenight(props) {
|
||||
const fetchGamenight = () => {
|
||||
if (props.user !== null) {
|
||||
unpack_api_result(get_gamenight(props.gamenightId, props.user.jwt), props.setFlash)
|
||||
.then(result => setGamenight(result.gamenight));
|
||||
.then(result => {
|
||||
if(result !== undefined) {
|
||||
setGamenight(result.gamenight);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +55,11 @@ function Gamenight(props) {
|
||||
};
|
||||
|
||||
unpack_api_result(patch_gamenight(gamenight.id, input, props.user.jwt), props.setFlash)
|
||||
.then(() => fetchGamenight());
|
||||
.then(result => {
|
||||
if(result !== undefined) {
|
||||
fetchGamenight();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const Leave = () => {
|
||||
@@ -60,7 +68,11 @@ function Gamenight(props) {
|
||||
};
|
||||
|
||||
unpack_api_result(patch_gamenight(gamenight.id, input, props.user.jwt), props.setFlash)
|
||||
.then(() => fetchGamenight());
|
||||
.then(result => {
|
||||
if(result !== undefined) {
|
||||
fetchGamenight();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let join_or_leave_button;
|
||||
|
||||
@@ -18,7 +18,12 @@ function Gamenights(props) {
|
||||
if (props.user !== null) {
|
||||
const input = { game_id: game_id };
|
||||
unpack_api_result(delete_gamenight(input, props.user.jwt), props.setFlash)
|
||||
.then(() => props.refetchGamenights());
|
||||
.then(result => {
|
||||
if(result !== undefined) {
|
||||
console.log("hello?");
|
||||
props.refetchGamenights();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,19 +8,13 @@ import MenuIcon from '@mui/icons-material/Menu';
|
||||
|
||||
function MenuBar(props) {
|
||||
|
||||
let adminPanelButton = null;
|
||||
if (props.user?.role === 'Admin') {
|
||||
adminPanelButton = (
|
||||
<Button
|
||||
color="inherit"
|
||||
onClick={props.onAdmin}>
|
||||
AdminPanel
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
let userButton = null;
|
||||
if (props.user != null) {
|
||||
let logoutButton = null;
|
||||
let adminPanelButton = null;
|
||||
let registerButton = null;
|
||||
if (props.user !== null) {
|
||||
userButton = (
|
||||
<Button
|
||||
color="inherit"
|
||||
@@ -28,6 +22,30 @@ function MenuBar(props) {
|
||||
{props.user.username}
|
||||
</Button>
|
||||
);
|
||||
logoutButton = (
|
||||
<Button
|
||||
color="inherit"
|
||||
onClick={props.onLogout}>
|
||||
Logout
|
||||
</Button>
|
||||
);
|
||||
if (props.user.role === 'Admin') {
|
||||
adminPanelButton = (
|
||||
<Button
|
||||
color="inherit"
|
||||
onClick={props.onAdmin}>
|
||||
AdminPanel
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
} else {
|
||||
registerButton = (
|
||||
<Button
|
||||
color="inherit"
|
||||
onClick={props.onRegister}>
|
||||
Register
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -50,12 +68,9 @@ function MenuBar(props) {
|
||||
Gamenight!
|
||||
</Typography>
|
||||
{userButton !== null && userButton}
|
||||
{registerButton !== null && registerButton}
|
||||
{adminPanelButton !== null && adminPanelButton}
|
||||
<Button
|
||||
color="inherit"
|
||||
onClick={props.onLogout}>
|
||||
Logout
|
||||
</Button>
|
||||
{logoutButton !== null && logoutButton}
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
);
|
||||
|
||||
98
frontend/src/components/Register.jsx
Normal file
98
frontend/src/components/Register.jsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import {useState} from 'react';
|
||||
import FormControl from '@mui/material/FormControl';
|
||||
import Input from '@mui/material/Input';
|
||||
import FormHelperText from '@mui/material/FormHelperText';
|
||||
import Button from '@mui/material/Button';
|
||||
|
||||
import {register, unpack_api_result} from '../api/Api';
|
||||
|
||||
function Register(props) {
|
||||
const [registrationToken, setRegistrationToken] = useState("");
|
||||
const [username, setUsername] = useState("");
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [passwordRepeat, setPasswordRepeat] = useState("");
|
||||
|
||||
const onRegister = () => {
|
||||
let input = {
|
||||
username,
|
||||
email,
|
||||
password,
|
||||
password_repeat: passwordRepeat
|
||||
}
|
||||
|
||||
unpack_api_result(register(registrationToken, input), props.setFlash)
|
||||
.then(result => {
|
||||
if(result !== undefined) {
|
||||
props.onRegistered(result.user);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<FormControl>
|
||||
<Input
|
||||
id="registration_token"
|
||||
aria-describedby="registration_token-helper-text"
|
||||
value={registrationToken}
|
||||
onChange={(e) => {setRegistrationToken(e.target.value)}} />
|
||||
<FormHelperText
|
||||
id="registration_token-helper-text">
|
||||
Registration token given by a gamenight admin
|
||||
</FormHelperText>
|
||||
|
||||
<Input
|
||||
id="username"
|
||||
aria-describedby="email-helper-text"
|
||||
value={username}
|
||||
onChange={(e) => {setUsername(e.target.value)}} />
|
||||
<FormHelperText
|
||||
id="username-helper-text">
|
||||
Username to display everywhere
|
||||
</FormHelperText>
|
||||
|
||||
<Input
|
||||
id="email"
|
||||
aria-describedby="email-helper-text"
|
||||
value={email}
|
||||
onChange={(e) => {setEmail(e.target.value)}} />
|
||||
<FormHelperText
|
||||
id="email-helper-text">
|
||||
E-mail used for notifications and password resets
|
||||
</FormHelperText>
|
||||
|
||||
<Input
|
||||
id="password"
|
||||
type="password"
|
||||
aria-describedby="password-helper-text"
|
||||
value={password}
|
||||
onChange={(e) => {setPassword(e.target.value)}} />
|
||||
<FormHelperText
|
||||
id="password-helper-text">
|
||||
Password atleast 10 characters long
|
||||
</FormHelperText>
|
||||
|
||||
<Input
|
||||
id="password_repeat"
|
||||
type="password"
|
||||
aria-describedby="password_repeat-helper-text"
|
||||
value={passwordRepeat}
|
||||
onChange={(e) => {setPasswordRepeat(e.target.value)}} />
|
||||
<FormHelperText
|
||||
id="password_repeat-helper-text">
|
||||
Confirm your password
|
||||
</FormHelperText>
|
||||
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="success"
|
||||
onClick={onRegister}>
|
||||
Register
|
||||
</Button>
|
||||
|
||||
</FormControl>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
export default Register;
|
||||
Reference in New Issue
Block a user