Add registration page.

pull/31/head
Sander Vocke 5 years ago
parent 2029b58466
commit 04a025f850
  1. 5
      client/src/components/MainWindow.tsx
  2. 13
      client/src/components/windows/Windows.tsx
  3. 50
      client/src/components/windows/login/LoginWindow.tsx
  4. 131
      client/src/components/windows/register/RegisterWindow.tsx
  5. 5
      client/src/components/windows/song/SongWindow.tsx
  6. 20
      client/src/lib/useAuth.tsx

@ -12,6 +12,7 @@ import ManageTagsWindow from './windows/manage_tags/ManageTagsWindow';
import { BrowserRouter, Switch, Route, useParams, Redirect } from 'react-router-dom';
import LoginWindow from './windows/login/LoginWindow';
import { useAuth } from '../lib/useAuth';
import RegisterWindow from './windows/register/RegisterWindow';
var _ = require('lodash');
const darkTheme = createMuiTheme({
@ -54,6 +55,10 @@ export default function MainWindow(props: any) {
<AppBar selectedTab={null} />
<LoginWindow />
</Route>
<Route path="/register">
<AppBar selectedTab={null} />
<RegisterWindow />
</Route>
<PrivateRoute path="/query">
<AppBar selectedTab={AppBarTab.Query} />
<QueryWindow />

@ -12,6 +12,8 @@ import AlbumWindow, { AlbumWindowReducer } from './album/AlbumWindow';
import TagWindow, { TagWindowReducer } from './tag/TagWindow';
import { songGetters } from '../../lib/songGetters';
import ManageTagsWindow, { ManageTagsWindowReducer } from './manage_tags/ManageTagsWindow';
import { RegisterWindowReducer } from './register/RegisterWindow';
import { LoginWindowReducer } from './login/LoginWindow';
export enum WindowType {
Query = "Query",
@ -21,6 +23,7 @@ export enum WindowType {
Song = "Song",
ManageTags = "ManageTags",
Login = "Login",
Register = "Register",
}
export interface WindowState { }
@ -32,6 +35,8 @@ export const newWindowReducer = {
[WindowType.Song]: SongWindowReducer,
[WindowType.Tag]: TagWindowReducer,
[WindowType.ManageTags]: ManageTagsWindowReducer,
[WindowType.Login]: LoginWindowReducer,
[WindowType.Register]: RegisterWindowReducer,
}
export const newWindowState = {
@ -82,5 +87,11 @@ export const newWindowState = {
alert: null,
pendingChanges: [],
}
}
},
[WindowType.Login]: () => {
return {}
},
[WindowType.Register]: () => {
return {}
},
}

@ -1,25 +1,49 @@
import React, { useState } from 'react';
import React, { useState, useReducer } from 'react';
import { WindowState } from "../Windows";
import { Box, Paper, Typography, TextField, Button } from "@material-ui/core";
import { useHistory, useLocation } from 'react-router';
import { useAuth, Auth } from '../../../lib/useAuth';
export interface LoginWindowState extends WindowState { }
export enum LoginWindowStateActions { }
export function LoginWindowReducer(state: LoginWindowState, action: any) { }
export interface LoginWindowState extends WindowState {
email: string,
password: string,
}
export enum LoginWindowStateActions {
SetEmail = "SetEmail",
SetPassword = "SetPassword",
}
export function LoginWindowReducer(state: LoginWindowState, action: any) {
switch (action.type) {
case LoginWindowStateActions.SetEmail:
return { ...state, email: action.value }
case LoginWindowStateActions.SetPassword:
return { ...state, password: action.value }
default:
throw new Error("Unimplemented LoginWindow state update.")
}
}
export default function LoginWindow(props: {}) {
const [state, dispatch] = useReducer(LoginWindowReducer, {
email: "",
password: "",
});
return <LoginWindowControlled state={state} dispatch={dispatch} />
}
export function LoginWindowControlled(props: {
state: LoginWindowState,
dispatch: (action: any) => void,
}) {
let history: any = useHistory();
let location: any = useLocation();
let auth: Auth = useAuth();
let { from } = location.state || { from: { pathname: "/" } };
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>("");
const onSubmit = (event: any) => {
event.preventDefault();
auth.signin(email, password)
auth.signin(props.state.email, props.state.password)
.then(() => {
history.replace(from);
})
@ -43,7 +67,10 @@ export default function LoginWindow(props: {}) {
label="Email"
name="email"
autoFocus
onInput={(e: any) => setEmail(e.target.value)}
onInput={(e: any) => props.dispatch({
type: LoginWindowStateActions.SetEmail,
value: e.target.value
})}
/>
<TextField
variant="outlined"
@ -54,7 +81,10 @@ export default function LoginWindow(props: {}) {
label="Password"
name="password"
type="password"
onInput={(e: any) => setPassword(e.target.value)}
onInput={(e: any) => props.dispatch({
type: LoginWindowStateActions.SetPassword,
value: e.target.value
})}
/>
<Button
type="submit"

@ -0,0 +1,131 @@
import React, { useState, useReducer } from 'react';
import { WindowState } from "../Windows";
import { Box, Paper, Typography, TextField, Button } from "@material-ui/core";
import { useHistory, useLocation } from 'react-router';
import { useAuth, Auth } from '../../../lib/useAuth';
import Alert from '@material-ui/lab/Alert';
import { Link } from 'react-router-dom';
export enum RegistrationStatus {
NoneSubmitted = 0,
Successful,
Unsuccessful,
}
export interface RegisterWindowState extends WindowState {
email: string,
password: string,
status: RegistrationStatus,
}
export enum RegisterWindowStateActions {
SetEmail = "SetEmail",
SetPassword = "SetPassword",
SetStatus = "SetStatus",
}
export function RegisterWindowReducer(state: RegisterWindowState, action: any) {
switch (action.type) {
case RegisterWindowStateActions.SetEmail:
return { ...state, email: action.value }
case RegisterWindowStateActions.SetPassword:
return { ...state, password: action.value }
case RegisterWindowStateActions.SetStatus:
return { ...state, status: action.value }
default:
throw new Error("Unimplemented RegisterWindow state update.")
}
}
export default function RegisterWindow(props: {}) {
const [state, dispatch] = useReducer(RegisterWindowReducer, {
email: "",
password: "",
status: RegistrationStatus.NoneSubmitted,
});
return <RegisterWindowControlled state={state} dispatch={dispatch} />
}
export function RegisterWindowControlled(props: {
state: RegisterWindowState,
dispatch: (action: any) => void,
}) {
let history: any = useHistory();
let location: any = useLocation();
let auth: Auth = useAuth();
let { from } = location.state || { from: { pathname: "/" } };
const onSubmit = (event: any) => {
event.preventDefault();
auth.signup(props.state.email, props.state.password)
.then(() => {
console.log("succes!")
props.dispatch({
type: RegisterWindowStateActions.SetStatus,
value: RegistrationStatus.Successful,
})
}).catch((e: any) => {
console.log("Fail!")
props.dispatch({
type: RegisterWindowStateActions.SetStatus,
value: RegistrationStatus.Unsuccessful,
})
})
}
return <Box width="100%" justifyContent="center" display="flex" flexWrap="wrap">
<Box
m={1}
mt={4}
>
<Paper>
<Box p={3}>
<Typography variant="h5">Sign up</Typography>
<form noValidate onSubmit={onSubmit}>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email"
name="email"
autoFocus
onInput={(e: any) => props.dispatch({
type: RegisterWindowStateActions.SetEmail,
value: e.target.value
})}
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="password"
label="Password"
name="password"
type="password"
onInput={(e: any) => props.dispatch({
type: RegisterWindowStateActions.SetPassword,
value: e.target.value
})}
/>
{props.state.status === RegistrationStatus.Successful && <Alert severity="success">
Registration successful! Please {<Link to="/login">sign in</Link>} to continue.
</Alert>
}
{props.state.status === RegistrationStatus.Unsuccessful && <Alert severity="error">
Registration failed - please check your inputs and try again.
</Alert>
}
{props.state.status !== RegistrationStatus.Successful && <Button
type="submit"
fullWidth
variant="outlined"
color="primary"
>Sign up</Button>}
</form>
</Box>
</Paper>
</Box>
</Box>
}

@ -44,11 +44,6 @@ export function SongWindowReducer(state: SongWindowState, action: any) {
}
}
export interface IProps {
state: SongWindowState,
dispatch: (action: any) => void,
}
export async function getSongMetadata(id: number) {
return (await querySongs({
query: {

@ -15,7 +15,7 @@ export interface Auth {
user: AuthUser | null,
signout: () => void,
signin: (email: string, password: string) => Promise<AuthUser>,
signup: (email: string, password: string) => void,
signup: (email: string, password: string) => Promise<void>,
};
const authContext = createContext<Auth>({
@ -49,14 +49,14 @@ function useProvideAuth() {
const response = await fetch(url, { method: "POST" });
const json = await response.json();
if(!("userId" in json)) {
if (!("userId" in json)) {
throw new Error("No UserID received from login.");
}
const user = {
id: json.userId,
email: email,
icon: <PersonIcon/>,
icon: <PersonIcon />,
}
setUser(user);
return user;
@ -73,13 +73,11 @@ function useProvideAuth() {
password: password,
})
};
return (async () => {
const response = await fetch((process.env.REACT_APP_BACKEND || "") + serverApi.RegisterUserEndpoint, requestOpts)
if(!response.ok) {
throw new Error("Failed to register user.")
}
})();
const response = await fetch((process.env.REACT_APP_BACKEND || "") + serverApi.RegisterUserEndpoint, requestOpts)
if (!response.ok) {
throw new Error("Failed to register user.")
}
})();
};
@ -87,7 +85,7 @@ function useProvideAuth() {
return (async () => {
const url = (process.env.REACT_APP_BACKEND || "") + serverApi.LogoutEndpoint;
const response = await fetch(url, { method: "POST" });
if(!response.ok) {
if (!response.ok) {
throw new Error("Failed to log out.");
}
setUser(null);

Loading…
Cancel
Save