Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
0635645
Set the endOfLine parameter for prettier to auto
Skutlis Feb 26, 2025
5d64ac8
Merge pull request #2 from boolean-uk/fixPrettier
sanderrasmussen Feb 26, 2025
8e64d18
added password input validation in register from
sanderrasmussen Feb 26, 2025
aab5f5a
added standard pattern to form
sanderrasmussen Feb 26, 2025
4c6b63d
Testing some features
Skutlis Feb 26, 2025
17a4906
Merge branch 'test' into UI-registration-validation
Skutlis Feb 26, 2025
794aa75
Changed from regex to the same validation as the backend. The error m…
Skutlis Feb 26, 2025
eccb001
changed the email field in the register page to a text field, so that…
Skutlis Feb 27, 2025
e17b8b2
Merge pull request #8 from boolean-uk/UI-registration-validation
Skutlis Feb 27, 2025
b0b1124
Add ui for step 2 and 3 in create profile
martvu Feb 27, 2025
89f9edd
added form and css
Feb 27, 2025
b75ecbb
User’s first name and last name is required on register account.
sanderrasmussen Feb 27, 2025
f7b3a3b
Merge pull request #11 from boolean-uk/10-ui---add-create-profile-ste…
martvu Feb 27, 2025
46fb02e
update
Feb 27, 2025
e925bbe
Merge branch 'main' into UI-Create-profile
sanderrasmussen Feb 27, 2025
9d86535
completed merge with main
sanderrasmussen Feb 27, 2025
63e8aab
merged in uploadPhoto
sanderrasmussen Feb 27, 2025
7cfe5a9
merged in uploadPhoto
sanderrasmussen Feb 27, 2025
0b47ef1
removed q file, and added missing profile fields
sanderrasmussen Feb 27, 2025
b8f1bc3
readded missing profile fields
sanderrasmussen Feb 27, 2025
d369954
Merge pull request #12 from boolean-uk/UI-Create-profile
sanderrasmussen Feb 27, 2025
146f222
EditProfile and ViewProfile
Feb 27, 2025
f144e1b
Created tokenservice and profilebutton
Skutlis Feb 27, 2025
52c8f4a
Merge branch '5-ui---view-profile' into 5--UI-tokenService-and-button
Skutlis Feb 27, 2025
a87033e
not working profilebutton
Feb 27, 2025
6815371
Changed the profilebutton
Skutlis Feb 27, 2025
f970bce
change
Feb 27, 2025
7a200d5
merge
Feb 27, 2025
3c298d6
buttons working + nav route
Feb 27, 2025
3b7e21a
implemented tsome changed
Skutlis Feb 28, 2025
0b73d24
fix routing for edit with/without permission
Feb 28, 2025
d58c74c
Did some updates
Skutlis Feb 28, 2025
acdde50
Profile and edit profile now works
Skutlis Feb 28, 2025
45eca8d
merged main into this branch and resolved conflicts
Skutlis Feb 28, 2025
ab3fd8b
Merge pull request #16 from boolean-uk/5-ui---view-profile
josteinlaa Feb 28, 2025
e0e0b99
Added a hotfix to the login such that it now routes correctly, and us…
Skutlis Feb 28, 2025
b81e155
Merge branch 'main' into login-hot-fix
Skutlis Feb 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .env.example

This file was deleted.

2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
"singleQuote": true,
"trailingComma": "none",
"jsxBracketSameLine": false,
"endOfLine": "lf"
"endOfLine": "auto"
}
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"react-modal": "^3.16.1",
"react-router-dom": "^6.8.0",
"react-scripts": "5.0.1",
"validator": "^13.12.0",
"web-vitals": "^3.1.1"
},
"scripts": {
Expand Down
4 changes: 4 additions & 0 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@
.ReactModal__Html--open {
overflow: hidden;
}

.profile-button-group > section {
padding-left: 400px;
}
21 changes: 20 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import Verification from './pages/verification';
import { AuthProvider, ProtectedRoute } from './context/auth';
import { ModalProvider } from './context/modal';
import Welcome from './pages/welcome';

import ViewProfile from './pages/profileView';
import EditProfile from './pages/profileEdit';
const App = () => {
return (
<>
Expand All @@ -28,6 +29,24 @@ const App = () => {
</ProtectedRoute>
}
/>
<Route
path="profile/:id"
element={
<ProtectedRoute>
<ViewProfile></ViewProfile>
</ProtectedRoute>
}
/>

<Route
path="profile/:id/edit"
element={
<ProtectedRoute>
<EditProfile></EditProfile>
</ProtectedRoute>
}
/>

<Route
path="welcome"
element={
Expand Down
31 changes: 29 additions & 2 deletions src/components/form/textInput/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import { useState } from 'react';

const TextInput = ({ value, onChange, name, label, icon, type = 'text' }) => {
const TextInput = ({
value,
onChange,
errorResponse = '',
name,
label,
icon,
require = false,
type = 'text',
readOnly = false
}) => {
const [input, setInput] = useState('');
const [showpassword, setShowpassword] = useState(false);
// form is valid if has a text value or field is optional
// const [isValid, setIsValid] = useState(!!value || !require);
if (type === 'password') {
return (
<div className="inputwrapper">
Expand All @@ -11,21 +23,33 @@ const TextInput = ({ value, onChange, name, label, icon, type = 'text' }) => {
type={type}
name={name}
value={value}
required={require}
readOnly={readOnly}
onChange={(e) => {
onChange(e);
setInput(e.target.value);
}}
/>
{showpassword && <input type="text" name={name} value={input} className="passwordreveal" />}
{showpassword && (
<input
type="text"
name={name}
value={input}
className="passwordreveal"
readOnly={readOnly}
/>
)}
<button
className={`showpasswordbutton formbutton ${showpassword === true && '__faded'}`}
onClick={(e) => {
e.preventDefault();
setShowpassword(!showpassword);
}}
type="button"
>
<EyeLogo />
</button>
{errorResponse && <span className="input-invalid">{errorResponse}</span>}
</div>
);
} else {
Expand All @@ -36,10 +60,13 @@ const TextInput = ({ value, onChange, name, label, icon, type = 'text' }) => {
type={type}
name={name}
value={value}
required={require}
readOnly={readOnly}
onChange={onChange}
className={icon && 'input-has-icon'}
/>
{icon && <span className="input-icon">{icon}</span>}
{errorResponse && <span className="input-invalid">{errorResponse}</span>}
</div>
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/navigation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import HomeIcon from '../../assets/icons/homeIcon';
import ProfileIcon from '../../assets/icons/profileIcon';
import useAuth from '../../hooks/useAuth';
import './style.css';
import { getId } from '../../service/tokenService';

const Navigation = () => {
const { token } = useAuth();
Expand All @@ -22,7 +23,7 @@ const Navigation = () => {
</NavLink>
</li>
<li>
<NavLink to="/">
<NavLink to={`/profile/${getId()}`}>
<ProfileIcon />
<p>Profile</p>
</NavLink>
Expand Down
177 changes: 177 additions & 0 deletions src/components/profile/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import './profile.css';
import { useContext } from 'react';
import Form from '../form';
import TextInput from '../form/textInput';

const Profile = ({ readOnly, UserContext }) => {
if (!UserContext) {
throw new Error('UserContext is required');
}

const context = useContext(UserContext);
const { user, updatedUser, onChange, submit } = context;
const initials = user ? `${user.firstName[0]}${user.lastName[0]}` : '';

if (!user) {
return <div>Loading...</div>;
}

return (
<div className="profile-container">
<h1>{readOnly ? 'View Profile' : 'Edit Profile'}</h1>
<div className="profile-edit-section">
<div className="profile-header">
<div className="profile-icon">
<p>{initials}</p>
</div>
<label className="profile-name">
<p className="profile-name-header">{`${user.firstName} ${user.lastName}`}</p>
<p>{user.role === 'STUDENT' ? 'Student' : 'Teacher'}</p>
</label>
</div>

<div className="profile-body">
<section>
<Form className="profile-body-forms" onSubmit={submit}>
<section>
<h3>Basic Info</h3>
<div className="profile-smaller-icon">
<p>{initials}</p>
</div>
<TextInput
value={updatedUser ? updatedUser.firstName || user.firstName : user.firstName}
onChange={onChange}
name="firstName"
label="First Name"
readOnly={readOnly}
require={true}
/>
<TextInput
value={updatedUser ? updatedUser.lastName || user.lastName : user.lastName}
onChange={onChange}
name="lastName"
label="Last Name"
readOnly={readOnly}
require={true}
/>
<TextInput
value={
updatedUser
? updatedUser.username || user.email.split('@')[0]
: user.email.split('@')[0]
}
onChange={onChange}
name="username"
label="Username"
readOnly={readOnly}
require={true}
/>
<TextInput
value={updatedUser ? updatedUser.githubUrl || user.githubUrl : user.githubUrl}
onChange={onChange}
name="githubUrl"
label="GitHub Username"
readOnly={readOnly}
require={true}
/>
</section>

<section>
<h3>{user.role === 'STUDENT' ? 'Training Info' : 'Professional Info'}</h3>
<TextInput
value={updatedUser ? updatedUser.role || user.role : user.role}
onChange={onChange}
name="role"
label="Role"
readOnly={readOnly}
require={true}
/>
<TextInput
value={updatedUser ? updatedUser.specialism || 'N/A' : 'N/A'}
onChange={onChange}
name="specialism"
label="Specialism"
readOnly={readOnly}
require={true}
/>
{user.role === 'STUDENT' ? (
<>
<TextInput
value={updatedUser ? updatedUser.cohortStartDate || 'N/A' : 'N/A'}
onChange={onChange}
name="cohortStartDate"
label="Cohort Start Date"
readOnly={readOnly}
require={true}
/>
<TextInput
value={updatedUser ? updatedUser.cohortEndDate : 'N/A'}
onChange={onChange}
name="cohortEndDate"
label="Cohort End Date"
readOnly={readOnly}
require={true}
/>
</>
) : (
<TextInput
value={updatedUser ? updatedUser.jobTitle || 'N/A' : 'N/A'}
onChange={onChange}
name="jobTitle"
label="Job Title"
readOnly={readOnly}
require={true}
/>
)}
</section>
<section>
<h3>Contact Info</h3>
<TextInput
value={updatedUser ? updatedUser.email || user.email : user.email}
onChange={onChange}
name="email"
label="Email"
readOnly={readOnly}
require={true}
/>
<TextInput
value={updatedUser ? updatedUser.mobile || 'N/A' : 'N/A'}
onChange={onChange}
name="mobile"
label="Mobile"
readOnly={readOnly}
require={true}
/>
<TextInput
value={updatedUser ? updatedUser.password || '********' : '********'}
onChange={onChange}
name="password"
label="Password"
readOnly={readOnly}
require={true}
/>
</section>
<section>
<h3>Bio</h3>
<textarea
value={
updatedUser
? updatedUser.biography || user.biography || ''
: user.biography || ''
}
onChange={onChange}
name="biography"
label="Biography"
readOnly={readOnly}
required={true}
/>
</section>
</Form>
</section>
</div>
</div>
</div>
);
};

export default Profile;
Loading