Skip to content

Commit c51c415

Browse files
committed
Implement dashboard
* Implement reactExtensions service - module containing one method, setFormElement - Function composition method for easily setting states with event handlers * Implement ChangePassword component * Implement FullName component * Implement Email component * Implement inlineFormElements CSS module * Add above components to dashboard * Update copyright to 2021
1 parent b65f1bc commit c51c415

9 files changed

Lines changed: 182 additions & 36 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import FormField from "../FormField/formField";
2+
import { useState } from "react";
3+
import changePassword from "../Register/register.module.css";
4+
import { setFormElement } from "../reactExtensions";
5+
6+
export default function ChangePassword(props) {
7+
const [currentPassword, setCurrentPassword] = useState("");
8+
const [newPassword, setNewPassword] = useState("");
9+
const [confirmNewPassword, setConfirmNewPassword] = useState("");
10+
11+
return (
12+
<form className={changePassword.form}>
13+
<FormField
14+
labelContent="Current Password"
15+
label="currpass"
16+
format="password"
17+
required
18+
value={currentPassword}
19+
onChange={setFormElement(setCurrentPassword)}
20+
/>
21+
<FormField
22+
labelContent="New Password"
23+
label="newpass"
24+
format="password"
25+
required
26+
value={newPassword}
27+
onChange={setFormElement(setNewPassword)}
28+
/>
29+
<FormField
30+
labelContent="Confirm New Password"
31+
label="confnewpass"
32+
format="password"
33+
required
34+
value={confirmNewPassword}
35+
onChange={setFormElement(setConfirmNewPassword)}
36+
/>
37+
38+
<button type="submit" className={changePassword.card}>
39+
Change my Password
40+
</button>
41+
</form>
42+
);
43+
}

src/Dashboard/dashboard.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
export default function Dashboard() {
2-
return (
3-
<article>
4-
<h1>Borum Sphere Dashboard</h1>
5-
<h2>Full Name</h2>
1+
import ChangePassword from "../ChangePassword/changePassword";
2+
import FullName from "../InlineFormElements/FullName/fullName";
3+
import Email from "../InlineFormElements/Email/email";
4+
import dashboard from "./dashboard.module.css";
65

7-
8-
9-
</article>
10-
);
11-
}
6+
export default function Dashboard() {
7+
return (
8+
<article>
9+
<h1>Borum Sphere Dashboard</h1>
10+
<FullName />
11+
<Email />
12+
<ChangePassword />
13+
<button className={dashboard.signOut}>Sign out of all accounts</button>
14+
</article>
15+
);
16+
}

src/Dashboard/dashboard.module.css

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.signOut {
2+
font-size: 2em;
3+
margin-bottom: 1em;
4+
background: white;
5+
border: 1px solid blue;
6+
padding: 1em;
7+
border-radius: 25px;
8+
}
9+
10+
.signOut:hover {
11+
color: red;
12+
cursor: pointer;
13+
border: 1px solid red;
14+
}

src/FormField/formField.js

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
import formField from "./formField.module.css";
22

33
export default function FormField({
4-
autofocus = false,
5-
label,
6-
format = "text",
7-
required = false,
8-
value = "",
9-
onChange = () => {},
4+
autofocus = false,
5+
label,
6+
labelContent = () =>
7+
label[0].toUpperCase() + label.substring(1).toLowerCase(),
8+
format = "text",
9+
required = false,
10+
value = "",
11+
onChange = () => {},
1012
}) {
11-
return (
12-
<fieldset>
13-
<legend>
14-
<label htmlFor={label}>
15-
{label[0].toUpperCase() + label.substring(1).toLowerCase()}
16-
</label>
17-
</legend>
18-
<input
19-
className={formField.field}
20-
required={required}
21-
autoFocus={autofocus}
22-
type={format}
23-
id={label}
24-
name={label}
25-
value={value}
26-
onChange={onChange}
27-
/>
28-
</fieldset>
29-
);
13+
return (
14+
<fieldset>
15+
<legend>
16+
<label htmlFor={label}>{labelContent}</label>
17+
</legend>
18+
<input
19+
className={formField.field}
20+
required={required}
21+
autoFocus={autofocus}
22+
type={format}
23+
id={label}
24+
name={label}
25+
value={value}
26+
onChange={onChange}
27+
/>
28+
</fieldset>
29+
);
3030
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { useState } from "react";
2+
import { setFormElement } from "../../reactExtensions";
3+
import inlineFormElements from "../inlineFormElements.module.css";
4+
5+
export default function Email(props) {
6+
const [email, setEmail] = useState(sessionStorage.getItem("email"));
7+
8+
const onEmailSaveClick = e => {
9+
fetch("https://api.bforborum.com/api/login", {
10+
method: "PUT",
11+
body: `email=${email}`,
12+
});
13+
};
14+
15+
return (
16+
<div className={inlineFormElements.inlineFormElement}>
17+
<label>Email</label>
18+
<p contentEditable="true" onChange={setFormElement(setEmail)}>{email}</p>
19+
<button onClick={onEmailSaveClick}>Save</button>
20+
</div>
21+
);
22+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import inlineFormElements from "../inlineFormElements.module.css";
2+
3+
export default function FullName(props) {
4+
const firstName = sessionStorage.getItem("firstName") ?? "";
5+
const lastName = sessionStorage.getItem("lastName") ?? "";
6+
const fullName = firstName + " " + lastName;
7+
8+
const saveNewName = () => {
9+
fetch("https://api.bforborum.com/api/login", {
10+
method: "PUT",
11+
headers: {
12+
authorization: `Basic ${sessionStorage.getItem("apiKey")}`,
13+
"content-type": "application/x-www-form-urlencoded",
14+
},
15+
body: `firstName=${firstName}&lastName=${lastName}`,
16+
})
17+
.then(response => response.json())
18+
.then(response => {
19+
if (
20+
response.statusCode < 200 ||
21+
response.statusCode >= 300 ||
22+
!response.ok
23+
) {
24+
alert(
25+
"Your first name and last name could not be updated because of a system error"
26+
);
27+
}
28+
});
29+
};
30+
31+
return (
32+
<div className={inlineFormElements.inlineFormElement}>
33+
<label>Full Name</label>
34+
<h2 contentEditable="true" suppressContentEditableWarning="true">{fullName}</h2>
35+
<button onClick={saveNewName}>Save</button>
36+
</div>
37+
);
38+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.inlineFormElement {
2+
display: flex;
3+
align-items: center;
4+
}
5+
6+
.inlineFormElement label {
7+
width: 100px;
8+
text-align: left;
9+
}
10+
11+
.inlineFormElement [contentEditable="true"] {
12+
width: 500px;
13+
}
14+
15+
.inlineFormElement button {
16+
background: none;
17+
border: none;
18+
color: rgb(0, 255, 13);
19+
}

src/Layout/layout.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export default function Layout(props) {
1515
Powered by{" "}
1616
<img src="/vercel.svg" alt="Vercel Logo" className={layout.logo} />
1717
</a>
18-
<p>&copy; 2020 Borum Tech</p>
18+
<p>&copy; 2021 Borum Tech</p>
1919
<ul className={layout.legalLinks}>
2020
{/* <li className={layout.privacyPolicy}>
2121
<Link href="/legal/PrivacyPolicy">

src/reactExtensions.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const setFormElement = setter => {
2+
return event => setter(event.currentTarget.value);
3+
};
4+
5+
export { setFormElement };

0 commit comments

Comments
 (0)