Skip to content
This repository was archived by the owner on Apr 5, 2024. It is now read-only.

Commit 560e3fa

Browse files
committed
Added Registration UI
1 parent c4331ad commit 560e3fa

File tree

9 files changed

+129
-2
lines changed

9 files changed

+129
-2
lines changed
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
https://www.apache.org/licenses/LICENSE-2.0.html

webapp_frontend/src/background/methods/strings.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,8 @@ function stringReplaceSubstringOneTimeFromBeginningAndEnd(string:string, substri
1313
return string;
1414
}
1515

16-
export {reverseString, stringReplaceSubstringOneTimeFromBeginningAndEnd}
16+
function deleteSpaces(string:string):string {
17+
return string.replace(/\s/,"")
18+
}
19+
20+
export {reverseString, stringReplaceSubstringOneTimeFromBeginningAndEnd, deleteSpaces}

webapp_frontend/src/components/Router/Router.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {Redirect, Route, Switch} from "react-router-dom";
33
import Health from "../pages/Health";
44
import Error404 from "../pages/errors/Error404";
55
import Login from "../basicElements/Login";
6+
import Registration from "../pages/Registration";
67

78
export default function Router(): ReactElement {
89

@@ -13,6 +14,7 @@ export default function Router(): ReactElement {
1314
<Route exact path={"/"}>
1415
<Redirect to={"/health"}/>
1516
</Route>
17+
<Route path={"/registration"} component={Registration} />
1618
<Route path={"*"} component={Error404}/>
1719
</Switch>
1820
)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React from "react";
2+
import {storiesOf} from "@storybook/react";
3+
import Registration from "./Registration";
4+
import {BrowserRouter} from "react-router-dom";
5+
import '../../style/custom.scss';
6+
7+
storiesOf("Registration", module)
8+
.add("default", () =>
9+
<BrowserRouter>
10+
<Registration/>
11+
</BrowserRouter>
12+
)
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import React, {ChangeEvent, FormEvent, ReactElement, useState} from "react";
2+
import {Container, Row, Col, Form, FormGroup, Button} from "react-bootstrap";
3+
import {deleteSpaces} from "../../background/methods/strings";
4+
import {notMinStrLength} from "../../background/methods/checkInput";
5+
import info_svg from "../../assets/images/icons/material.io/info-24px.svg";
6+
import check_svg from "../../assets/images/icons/material.io/check_circle-24px.svg";
7+
import error_svg from "../../assets/images/icons/material.io/error-24px.svg";
8+
9+
export default function Registration(): ReactElement {
10+
const MIN_PASSWORD_LENGTH = 8;
11+
12+
const [username, setUsername] = useState<string>("");
13+
const [password, setPassword] = useState<string>("");
14+
const [passwordConfirmation, setPasswordConfirmation] = useState<string>("");
15+
const [passwordInformationLength, setPasswordInformationLength] = useState<boolean>(false);
16+
const [passwordInformationLowercase, setPasswordInformationLowercase] = useState<boolean>(false);
17+
const [passwordInformationUppercase, setPasswordInformationUppercase] = useState<boolean>(false);
18+
const [passwordInformationNumber, setPasswordInformationNumber] = useState<boolean>(false);
19+
const [passwordsMatch, setPasswordsMatch] = useState<boolean>(false);
20+
const [errorMessage, setErrorMessage] = useState<string>("");
21+
22+
const handleSubmit = (event: FormEvent) => {
23+
event.preventDefault();
24+
25+
}
26+
27+
const handlePasswordChange = (event: ChangeEvent<HTMLInputElement>) => {
28+
event.preventDefault();
29+
let value = event.target.value;
30+
value = deleteSpaces(value);
31+
setPasswordInformationLength(!notMinStrLength(value, MIN_PASSWORD_LENGTH));
32+
setPasswordInformationLowercase(value.match(/[a-z]/) !== null);
33+
setPasswordInformationUppercase(value.match(/[A-Z]/) !== null);
34+
setPasswordInformationNumber(value.match(/\d/) !== null);
35+
setPassword(value)
36+
}
37+
38+
const handlePasswordConfirmationChange = (event: ChangeEvent<HTMLInputElement>) => {
39+
event.preventDefault();
40+
let value = event.target.value;
41+
value = deleteSpaces(value);
42+
setPasswordsMatch(password === value);
43+
setPasswordConfirmation(value);
44+
}
45+
46+
return (
47+
<Container>
48+
<Row>
49+
<Col md={{span: 6, offset: 3}}>
50+
<h1>Create new account</h1>
51+
<Form onSubmit={handleSubmit}>
52+
<FormGroup controlId="formBasicUsername">
53+
<Form.Label>Username</Form.Label>
54+
<Form.Control type={"name"} value={username}
55+
onChange={event => setUsername(event.target.value)}/>
56+
</FormGroup>
57+
<Form.Group controlId="formBasicPassword">
58+
<Form.Label>Password</Form.Label>
59+
<Form.Control type="password"
60+
placeholder="Must contain one number, uppercase & lowercase letter each"
61+
value={password}
62+
onChange={(event: ChangeEvent<HTMLInputElement>) => handlePasswordChange(event)}/>
63+
<div>
64+
<img alt={"status image password length"} src={passwordInformationLength ? check_svg : info_svg}/>
65+
<span className={"sr-only"}>{passwordInformationLength ? "Done: " : "Missing: "}</span>
66+
<span className={passwordInformationLength ? "text-success" : "text-muted"}>Passwords must be at least 8 characters.</span>
67+
</div>
68+
<div>
69+
<img alt={"status image password contains uppercase character"} src={passwordInformationUppercase ? check_svg : info_svg}/>
70+
<span className={"sr-only"}>{passwordInformationUppercase ? "Done: " : "Missing: "}</span>
71+
<span className={passwordInformationUppercase ? "text-success" : "text-muted"}>Passwords must be at least contain 1 uppercase character.</span>
72+
</div>
73+
<div>
74+
<img alt={"status image password contains lowercase character"} src={passwordInformationLowercase ? check_svg : info_svg}/>
75+
<span className={"sr-only"}>{passwordInformationLowercase ? "Done: " : "Missing: "}</span>
76+
<span className={passwordInformationLowercase ? "text-success" : "text-muted"}>Passwords must be at least contain 1 lowercase character.</span>
77+
</div>
78+
<div>
79+
<img alt={"status image password contains number"} src={passwordInformationNumber ? check_svg : info_svg}/>
80+
<span className={"sr-only"}>{passwordInformationNumber ? "Done: " : "Missing: "}</span>
81+
<span className={passwordInformationNumber ? "text-success" : "text-muted"}>Passwords must be at least contain 1 number.</span>
82+
</div>
83+
</Form.Group>
84+
<Form.Group controlId="formConfirmPassword">
85+
<Form.Label>Re-enter password</Form.Label>
86+
<Form.Control type="password"
87+
value={passwordConfirmation}
88+
onChange={(event: ChangeEvent<HTMLInputElement>) => handlePasswordConfirmationChange(event)}/>
89+
<div>
90+
<img alt={"status image passwords match"} src={!passwordConfirmation ? info_svg : passwordsMatch ? check_svg : error_svg}/>
91+
<span className={"sr-only"}>{passwordsMatch ? "Done: " : "Missing: "}</span>
92+
<span className={!passwordConfirmation ? "text-muted" : passwordsMatch ? "text-success" : "text-danger"}>Passwords must match.</span>
93+
</div>
94+
</Form.Group>
95+
<Button variant="primary" type="submit">
96+
Submit
97+
</Button>
98+
<p className="text-danger">{errorMessage}</p>
99+
</Form>
100+
</Col>
101+
</Row>
102+
</Container>
103+
)
104+
}

webapp_frontend/src/style/custom.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ $blue: #1a4965;
2121
@import "~bootstrap/scss/grid";
2222
@import "~bootstrap/scss/buttons";
2323
@import "~bootstrap/scss/tables";
24-
@import "~bootstrap/scss/utilities";
24+
@import "~bootstrap/scss/utilities";
25+
@import "~bootstrap/scss/forms";

0 commit comments

Comments
 (0)