Skip to content

Commit

Permalink
Add oauth on login
Browse files Browse the repository at this point in the history
  • Loading branch information
stefan-petrov1 committed Apr 21, 2024
1 parent d63672d commit a62d08e
Show file tree
Hide file tree
Showing 8 changed files with 304 additions and 14 deletions.
2 changes: 1 addition & 1 deletion client/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

<!-- Template Stylesheet -->
<link href="/css/style.css" rel="stylesheet">
<title>React App</title>
<title>EventEntry</title>

</head>

Expand Down
5 changes: 5 additions & 0 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Admin from './pages/admin/Admin';
import AdminTableDefault from './pages/admin/admin-tables/AdminTableDefault';
import AdminTableSkills from './pages/admin/admin-tables/AdminTableSkills';
import AdminTableUsers from './pages/admin/admin-tables/AdminTableUsers';
import FinishRegister from './pages/auth/finish-register/FinishRegister';
import Login from './pages/auth/login/Login';
import Logout from './pages/auth/logout/Logout';
import Register from './pages/auth/register/Register';
Expand Down Expand Up @@ -56,6 +57,10 @@ function App() {
element={
<ProtectedRoute role={RoleEnum.USER} onlyAuth={true} />
}>
<Route
path={PageEnum.FinishRegister}
element={<FinishRegister />}
/>
<Route path={PageEnum.Chat} element={<Chat />} />
<Route path={PageEnum.Logout} element={<Logout />} />
<Route path={PageEnum.Profile} element={<Profile />} />
Expand Down
15 changes: 10 additions & 5 deletions client/src/components/navbar/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,17 @@ function LoggedNav(props: {
}) {
return (
<>
{!props.hasFinishedOAuth2 && (
<NavItem to={PageEnum.FinishRegister} text="Finish Register" />
)}
<NavItem to={PageEnum.Logout} text="Log out" />
<NavItem
to={PageEnum.Profile.replace(':userId', props.userId.toString())}
text="Profile"
img={profileUserIcon}
/>
{props.hasFinishedOAuth2 && (
<NavItem
to={PageEnum.Profile.replace(':userId', props.userId.toString())}
text="Profile"
img={profileUserIcon}
/>
)}
</>
);
}
Expand Down
274 changes: 274 additions & 0 deletions client/src/pages/auth/finish-register/FinishRegister.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
import { useCallback } from 'react';
import { SubmitHandler, useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import { MultiValue } from 'react-select';
import { CachePolicies, useFetch } from 'use-http';
import FormErrorWrapper from '../../../components/form-error-wrapper/FormErrorWrapper';
import FormInput from '../../../components/form-input/FormInput';
import SkillsSelect, {
SkillOption,
} from '../../../components/skills-select/SkillsSelect';
import { OAuthPaths, skillsPaths } from '../../../config/api';
import { useAuthContext } from '../../../contexts/AuthContext';
import { useErrorContext } from '../../../contexts/ErrorContext';
import useValidators from '../../../hooks/useValidator';
import { IAuthResponse, ISkill, PageEnum, RoleEnum } from '../../../types';
import '../styles/Register.scss';

type Inputs = {
'First Name': string;
'Last Name': string;
'Current Workplace': string;
Education: string;
Experience: string;
Address: string;
WICHW: string;
skillsHave: MultiValue<SkillOption>;
skillsNeed: MultiValue<SkillOption>;
role: RoleEnum;
};

function FinishRegister() {
const navigate = useNavigate();
const { user, loginUser } = useAuthContext();
const { auth } = useValidators();
const { addError } = useErrorContext();

const {
handleSubmit,
control,
register,
reset,
watch,
setError,
clearErrors,
setValue,
formState: { errors },
} = useForm<Inputs>({
defaultValues: {
'First Name': user.firstname || '',
'Last Name': '',
'Current Workplace': '',
Education: '',
Experience: '',
Address: '',
WICHW: '',
skillsHave: [],
skillsNeed: [],
role: RoleEnum.USER,
},
mode: 'onChange',
});

const formValues = watch();

const { data: skills } = useFetch<ISkill[]>(
skillsPaths.getAll,
{
cachePolicy: CachePolicies.CACHE_AND_NETWORK,
},
[]
);

const { put, response, loading } = useFetch<IAuthResponse>(
OAuthPaths.completeOAuth
);

const onSubmit: SubmitHandler<Inputs> = async (data) => {
const body = {
firstname: data['First Name'].trim(),
lastname: data['Last Name'].trim(),
currentWorkPlace: data['Current Workplace'].trim(),
education: data.Education.trim(),
workExperience: data.Experience.trim(),
address: data.Address.trim(),
whatCanHelpWith: data.WICHW.trim(),
skills: data.skillsHave.map((x) =>
skills?.find((y) => y.id === Number(x.value))
),
lookingForSkills: data.skillsNeed.map((x) =>
skills?.find((y) => y.id === Number(x.value))
),
role: data.role,
};

const res = await put(body);

if (response.ok) {
reset();
loginUser(res);
navigate(PageEnum.Home);
}
};

const skillsAsSelectOptions =
skills?.map((x) => ({
value: x.id.toString(),
label: x.name,
})) || [];

const onSkillsHaveChange = useCallback(
(val: MultiValue<SkillOption>) => {
setValue('skillsHave', val, {
shouldValidate: true,
shouldDirty: true,
shouldTouch: true,
});
},
[setValue]
);

const onSkillsNeedChange = useCallback(
(val: MultiValue<SkillOption>) => {
setValue('skillsNeed', val, {
shouldValidate: true,
shouldDirty: true,
shouldTouch: true,
});
},
[setValue]
);

return (
<div className="row">
<div className="col-sm-9 col-md-7 col-lg-5 mx-auto">
<div className="card border-0 shadow rounded-3 my-5">
<div className="card-body p-4 p-sm-5">
<h5 className="card-title text-center mb-5 fw-light fs-5">
Finish Register
</h5>
<form onSubmit={handleSubmit(onSubmit)}>
<FormInput
control={control}
type="text"
inputClasses="form-control"
name="First Name"
placeholder="John"
labelText="First Name*"
rules={auth.FIRST_NAME_VALIDATIONS}
/>

<FormInput
control={control}
type="text"
inputClasses="form-control"
name="Last Name"
placeholder="Johnson"
labelText="Last Name*"
rules={auth.LAST_NAME_VALIDATIONS}
/>

<FormInput
control={control}
type="text"
inputClasses="form-control"
name="Address"
placeholder="LudogorieSoft, Targovishte 7700, Bulgaria"
labelText="Address*"
rules={auth.ADDRESS_VALIDATIONS}
/>

<FormInput
control={control}
type="text"
inputClasses="form-control"
name="Education"
placeholder="1 SU 'st. Sedmochislenici'"
labelText="Education*"
rules={auth.EDUCATION_VALIDATIONS}
/>

<FormErrorWrapper message={errors.Experience?.message}>
<div className="form-floating">
<textarea
className="form-control"
placeholder="Leave a comment here"
id="floatingTextarea2"
style={{ height: '100px' }}
{...register('Experience', {
...auth.EXPERIENCE_VALIDATIONS,
})}></textarea>
<label htmlFor="floatingTextarea2">Experience*</label>
</div>
</FormErrorWrapper>

<FormErrorWrapper message={errors.WICHW?.message}>
<div className="form-floating">
<textarea
className="form-control"
placeholder="Leave a comment here"
id="floatingTextarea2"
style={{ height: '100px' }}
{...register('WICHW', {
...auth.WICHW_VALIDATIONS,
})}></textarea>
<label htmlFor="floatingTextarea2">
What I can help with*
</label>
</div>
</FormErrorWrapper>

<FormInput
control={control}
type="text"
inputClasses="form-control"
name="Current Workplace"
placeholder="LudogorieSoft, Targovishte 7700, Bulgaria"
labelText="Workplace"
/>

<FormErrorWrapper message={undefined}>
<SkillsSelect
options={skillsAsSelectOptions}
placeholder={'Select what skills you HAVE...'}
onChange={onSkillsHaveChange}
/>
</FormErrorWrapper>
<FormErrorWrapper message={undefined}>
<SkillsSelect
options={skillsAsSelectOptions}
placeholder={'Select what skills you NEED...'}
onChange={onSkillsNeedChange}
/>
</FormErrorWrapper>

<FormErrorWrapper message={undefined}>
<div className="d-flex justify-content-between align-items-center">
<div className="d-flex justify-content-center align-items-center gap-2">
<input
{...register('role')}
type="radio"
className="form-check-input m-0"
value={RoleEnum.USER}
/>
<p className="m-0">User</p>
</div>
<div className="d-flex justify-content-center align-items-center gap-2">
<p className="m-0">Organisation</p>
<input
{...register('role')}
type="radio"
className="form-check-input m-0"
value={RoleEnum.ORGANISATION}
/>
</div>
</div>
</FormErrorWrapper>

<div className="d-grid">
<button
disabled={loading}
className="btn btn-primary btn-login text-uppercase fw-bold"
type="submit">
Finish Register
</button>
</div>
</form>
</div>
</div>
</div>
</div>
);
}

export default FinishRegister;
2 changes: 1 addition & 1 deletion client/src/pages/auth/register/Register.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { authPaths, skillsPaths } from '../../../config/api';
import { useErrorContext } from '../../../contexts/ErrorContext';
import useValidators from '../../../hooks/useValidator';
import { AlertTypeEnum, IAuthResponse, ISkill, RoleEnum } from '../../../types';
import './Register.scss';
import '../styles/Register.scss';

type Inputs = {
'First Name': string;
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions client/src/types/enums/PageEnum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ export enum PageEnum {
Profile = '/profile/:userId',
Admin = '/admin',
Chat = '/chat/:userId',
FinishRegister = '/finish-register',
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,21 +123,23 @@ public User processOAuthUser(CustomOAuth2User oAuth2User) {

if (user == null) {
// Default names after the user registers with OAUth2 and before they fill some other necessary information
final String NAME_PLACEHOLDER = "CHANGE_NAME";
final String ADDRESS_PLACEHOLDER = "CHANGE_ADDRESS";

String username = oAuth2User.getName().toLowerCase()
.replaceAll("[^a-zA-Z0-9]", "");
final String EDUCATION_PLACEHOLDER = "CHANGE_EDUCATION";
final String WORK_EXPERIENCE_PLACEHOLDER = "CHANGE_EXPERIENCE_CHANGE";
final String WCHW_PLACEHOLDER = "CHANGE_WHAT_CAN_HELP_WITH";

RegisterRequest registerRequest = new RegisterRequest();

// TODO: Add missing setters!!
registerRequest.setEmail(oAuth2User.getEmail());
registerRequest.setProvider(oAuth2User.getProvider());
registerRequest.setFirstname(NAME_PLACEHOLDER);
registerRequest.setLastname(NAME_PLACEHOLDER);
registerRequest.setFirstname(oAuth2User.getName());
registerRequest.setLastname("");
registerRequest.setRole(Role.USER);
registerRequest.setAddress(ADDRESS_PLACEHOLDER);
registerRequest.setEducation(EDUCATION_PLACEHOLDER);
registerRequest.setWorkExperience(WORK_EXPERIENCE_PLACEHOLDER);
registerRequest.setWhatCanHelpWith(WCHW_PLACEHOLDER);

user = userRepository.save(buildUser(registerRequest));
}
Expand All @@ -151,10 +153,13 @@ public User updateOAuth2UserWithFullData(CompleteOAuthRequest request, Long user
user.setFirstname(request.getFirstname());
user.setLastname(request.getLastname());
user.setAddress(request.getAddress());
user.setRole(request.getRole());
user.setEducation(request.getEducation());
user.setCurrentWorkPlace(request.getCurrentWorkPlace());
user.setWorkExperience(request.getWorkExperience());
user.setWhatCanHelpWith(request.getWhatCanHelpWith());
user.setRole(request.getRole());
user.setSkills(request.getSkills());
user.setLookingForSkills(request.getLookingForSkills());
user.setAdditionalInfoRequired(false);

return userRepository.save(user);
Expand Down

0 comments on commit a62d08e

Please sign in to comment.