CreateStudentModal
Wed Sep 07 2022 07:44:16 GMT+0000 (Coordinated Universal Time)
Saved by @alexSIera1234 #react.js
import React, { useEffect, useState, useMemo, useContext } from 'react';
import styled from 'styled-components/macro';
import * as yup from 'yup';
import { yupResolver } from '@hookform/resolvers/yup';
import { useForm, Controller, SubmitHandler } from 'react-hook-form';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import { useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
import FormInput from 'components/FormInput';
import CustomCheckbox from 'components/CustomCheckbox';
import { getUser } from 'redux/reducers/user';
import CustomModalContext from 'contexts/CustomModalContext';
import { useActions } from 'hooks/useActions';
import LearningPackageBody from 'pages/Signup/SelectLearningPackages/LearningPackageBody';
import instance from 'api/axiosInstance';
import { getFormattedSuggestYear } from 'utils/url';
import { formatDateForRegistration } from 'utils/Date';
export interface IStudentAccountForm {
firstName: string;
lastName: string;
userName: string;
password: string;
dateOfBirth?: Date;
email: string;
isStudentFourYear?: boolean;
grateStudent?: string;
}
type Props = {
isModal?: boolean;
};
const grateStudentArr = [
{
value: '3',
title: 'Year 3',
},
{
value: '4',
title: 'Year 4',
},
{
value: '5',
title: 'Year 5',
},
{
value: '6',
title: 'Year 6',
},
];
const schema = yup.object({
firstName: yup.string().required('First Name is a required field'),
lastName: yup.string().required('Last Name is a required field'),
userName: yup.string().required('User Name is a required field'),
password: yup.string().required('Password is a required field'),
dateOfBirth: yup.string().nullable().required('Date of Birth is a required field'),
email: yup.string().email(),
isStudentFourYear: yup.boolean(),
grateStudent: yup.string(),
});
const CreateStudentModal: React.FC<Props> = ({ isModal }) => {
const { setStudentAccount } = useActions();
const customModalContext = useContext(CustomModalContext);
const { hideModal, setActiveView } = customModalContext;
const history = useHistory();
const dispatch = useDispatch();
const currentUser = useSelector(getUser);
const studentWhenAppClosed = JSON.parse(localStorage.getItem('studentAccount') || '{}');
const memoizedIsCurUserIdEqualsStudentId = useMemo(
() => currentUser.userId === studentWhenAppClosed?.parentId,
// eslint-disable-next-line react-hooks/exhaustive-deps
[currentUser, studentWhenAppClosed],
);
const [studentYear, setStudentYear] = useState('');
const {
register,
formState: { errors },
control,
handleSubmit,
watch,
setValue,
} = useForm<IStudentAccountForm>({
defaultValues: {
firstName: Boolean(studentWhenAppClosed?.firstName) ? studentWhenAppClosed.firstName : '',
lastName: Boolean(studentWhenAppClosed?.lastName) ? studentWhenAppClosed.lastName : '',
userName: Boolean(studentWhenAppClosed?.userName) ? studentWhenAppClosed.userName : '',
password: Boolean(studentWhenAppClosed?.password) ? studentWhenAppClosed.password : '',
email: Boolean(studentWhenAppClosed?.email) ? studentWhenAppClosed.email : '',
isStudentFourYear: studentWhenAppClosed?.isStudentFourYear ? studentWhenAppClosed.isStudentFourYear : true,
grateStudent: Boolean(studentWhenAppClosed?.grateStudent) ? studentWhenAppClosed.grateStudent : '',
},
resolver: yupResolver(schema),
});
const newDate = watch('dateOfBirth');
const isStudentFourYear = watch('isStudentFourYear');
const grateStudentValue = watch('grateStudent');
const onSubmit: SubmitHandler<IStudentAccountForm> = async (data) => {
dispatch(
setStudentAccount({
firstName: data.firstName,
lastName: data.lastName,
userName: data.userName,
password: data.password,
dateOfBirth: data.dateOfBirth!,
email: data.email,
isStudentFourYear: data.isStudentFourYear,
grateStudent: data.grateStudent,
}),
);
!isModal && history.push('/select-learning-packages');
localStorage.setItem(
'studentAccount',
JSON.stringify({ ...data, dateOfBirth: data.dateOfBirth!, parentId: currentUser.userId }),
);
};
const createStudentAccount: SubmitHandler<IStudentAccountForm> = async (data) => {
setActiveView({
component: LearningPackageBody,
props: {
student: data,
isModal,
},
});
};
const getDate = async () => {
try {
const selectedDate = newDate;
const formattedDateValue = formatDateForRegistration(selectedDate);
const payload = {
date: formattedDateValue,
};
if (formattedDateValue === 'Invalid Date') {
return;
}
const response = await instance.post(getFormattedSuggestYear, payload);
if (response !== null) {
setStudentYear(response.data.year);
if (!isStudentFourYear) {
setValue('isStudentFourYear', false);
} else if (String(response.data.year) === grateStudentValue) {
setValue('isStudentFourYear', true);
} else {
setValue('grateStudent', String(response.data.year));
}
}
return response;
} catch (e) {
console.log(e);
}
};
useEffect(() => {
getDate();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [grateStudentValue, newDate, isStudentFourYear]);
useMemo(() => {
if (!memoizedIsCurUserIdEqualsStudentId) {
localStorage.removeItem('studentAccount');
}
}, [memoizedIsCurUserIdEqualsStudentId]);
return (
<StyledContainer isModal={isModal}>
{!isModal ? <h3 className="create-student-account__title">Create Student Account</h3> : null}
<form
className="create-student-account__form"
onSubmit={isModal ? handleSubmit(createStudentAccount) : handleSubmit(onSubmit)}
>
<div className="create-student-account__form-fields-wrapper">
<StyledFormInput
label="First Name"
name="firstName"
error={errors.firstName}
register={register}
placeholder="Enter a first name"
inputType="text"
/>
<StyledFormInput
label="Last Name"
name="lastName"
error={errors.lastName}
register={register}
placeholder="Enter a last name"
inputType="text"
/>
<StyledFormInput
label="User Name"
name="userName"
error={errors.userName}
register={register}
placeholder="Enter a user name"
inputType="text"
/>
<StyledFormInput
label="Password"
name="password"
error={errors.password}
register={register}
placeholder="Enter a password"
inputType="password"
/>
<Controller
name="dateOfBirth"
control={control}
defaultValue={
Boolean(studentWhenAppClosed?.dateOfBirth)
? (new Date(studentWhenAppClosed?.dateOfBirth) as unknown as Date)
: (new Date() as unknown as Date)
}
render={({ field: { onChange, value } }) => (
<div className="create-student-account__date-wrapper">
<label htmlFor="date" className="create-student-account__label">
Date of Birth
</label>
<StyledDatePicker
id="date"
onChange={onChange}
selected={value}
value={value as unknown as string}
placeholderText="Enter a date of birthday"
onKeyDown={(e) => {
e.preventDefault();
}}
dateFormat="MM/dd/yyyy"
dateFormatCalendar="MM/dd/yyyy"
/>
<p className="create-student-account__error">{errors?.dateOfBirth?.message}</p>
</div>
)}
/>
<StyledFormInput
label="Email Address (optional):"
name="email"
error={errors.email}
register={register}
placeholder="Enter a email"
inputType="text"
/>
<div className="create-student-account__checkbox-form-wrapper">
<p className="create-student-account__checkbox-title">Is this student in year {studentYear}?</p>
<Controller
render={({ field: { onChange, value } }) => (
<StyledCustomCheckbox
title="Yes"
name="Yes"
register={register}
onChange={() => onChange(true)}
checked={value}
/>
)}
name="isStudentFourYear"
control={control}
/>
<Controller
render={({ field: { onChange, value } }) => (
<StyledCustomCheckbox
title="No"
name="No"
register={register}
onChange={() => onChange(false)}
checked={!value}
/>
)}
name="isStudentFourYear"
control={control}
/>
</div>
<div className="create-student-account__checkbox-form-wrapper">
<p className="create-student-account__checkbox-title">What grate is the student? </p>
{grateStudentArr.map((item, index) => (
<Controller
key={index}
render={({ field: { onChange, value } }) => (
<StyledCustomCheckbox
title={item.title}
register={register}
name={item.title}
onChange={() => onChange(item.value)}
disabled={isStudentFourYear}
checked={value === item.value}
/>
)}
name="grateStudent"
control={control}
/>
))}
</div>
</div>
{!isModal ? (
<button className="create-student-account__form-button-next" type="submit">
Next
</button>
) : (
<div className="create-student-account__buttons-wrapper">
<button className="create-student-account__close-button" type="button" onClick={hideModal}>
Close
</button>
<button className="create-student-account__form-button-next" type="submit">
Add Student
</button>
</div>
)}
</form>
</StyledContainer>
);
};
const StyledContainer = styled.div<Props>`
width: ${(props) => (props.isModal ? '901px' : '1016px')};
margin: 0 auto;
background: white;
border-radius: ${(props) => (props.isModal ? 0 : '25px')};
padding: ${(props) => (props.isModal ? 0 : '42px 68px 58px')};
border-top: ${(props) => (props.isModal ? '1px solid #ececec' : 'none')};
padding-top: ${(props) => (props.isModal ? '32px' : 'none')};
font-family: ${({ theme }) => theme.font.fontFamily.popins};
.create-student-account {
&__title {
font-size: 30px;
line-height: 39px;
letter-spacing: 0.43px;
color: #20114d;
margin: 0;
padding-bottom: 25px;
font-weight: 600;
border-bottom: 1px solid #ececec;
margin-bottom: 18px;
}
&__form {
display: flex;
flex-direction: column;
align-items: center;
justify-content: start;
}
&__form-fields-wrapper {
width: 100%;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(3, max-content);
column-gap: 28px;
row-gap: 10px;
margin-bottom: 51px;
}
&__checkbox-form-wrapper {
display: grid;
grid-template-columns: min-content repeat(2, 0.1fr);
column-gap: 45px;
grid-column: 1 / 3;
:last-of-type {
grid-template-columns: min-content repeat(4, 0.1fr);
}
}
&__checkbox-title {
font-family: ${({ theme }) => theme.font.fontFamily.popins};
font-weight: 600;
font-size: 16px;
line-height: 18px;
letter-spacing: 0.2px;
width: 221px;
color: #20114d;
}
&__form-button-next {
padding: 11px 30px;
width: fit-content;
color: white;
background: #32e790;
text-align: center;
font-weight: 600;
font-size: 14px;
line-height: 18px;
letter-spacing: 0.2px;
border-radius: 27px;
border: 2px solid #32e790;
align-self: end;
cursor: pointer;
font-family: ${({ theme }) => theme.font.fontFamily.popins};
:last-of-type {
padding: 9px 34px;
}
}
&__date-wrapper {
display: flex;
flex-direction: column;
justify-content: start;
}
&__label {
margin: 0 0 10px 0;
margin-bottom: 10px;
font-size: 14px;
color: #20114d;
font-weight: 400;
}
&__error {
font-size: 9px;
color: red;
margin-top: 5px;
text-transform: capitalize;
}
&__buttons-wrapper {
display: flex;
flex-direction: row;
align-items: space-between;
justify-content: space-between;
width: 100%;
}
&__close-button {
padding: 9px 34px;
width: 157px;
color: rgba(245, 80, 83, 1);
background: white;
text-align: center;
font-weight: 600;
font-size: 14px;
line-height: 18px;
letter-spacing: 0.2px;
border-radius: 27px;
border: 2px solid rgba(245, 80, 83, 1);
align-self: end;
cursor: pointer;
}
}
`;
const StyledCustomCheckbox = styled(CustomCheckbox)`
width: 90px;
label {
font-family: ${({ theme }) => theme.font.fontFamily.popins};
font-weight: ${({ theme }) => theme.font.fontWeight.medium};
font-size: 16px;
line-height: 18px;
letter-spacing: 0.2px;
color: #20114d;
}
.custom-checkbox + label {
position: relative;
}
.custom-checkbox + label::before {
width: 23px;
height: 23px;
border-radius: 50%;
width: 1.5em;
height: 1.5em;
}
.custom-checkbox:checked + label::before {
background-color: #41e85b;
background-image: none;
}
.custom-checkbox:checked + label::after {
content: '';
width: 14px;
height: 14px;
position: absolute;
border-radius: 50%;
left: 5px;
background-color: #41e85b;
border: 2px solid white;
}
`;
const StyledDatePicker = styled(DatePicker)`
border: 1px solid #dad1c9;
border-radius: 13px;
padding: 11px 15px 11px 15px;
outline: none;
width: 100%;
font-weight: 600;
font-size: 16px;
line-height: 18px;
letter-spacing: 0.2px;
font-family: ${({ theme }) => theme.font.fontFamily.popins};
::placeholder {
color: rgba(32, 17, 77, 0.5);
font-family: ${({ theme }) => theme.font.fontFamily.popins};
}
`;
const StyledFormInput = styled(FormInput)`
font-weight: 600;
font-size: 16px;
line-height: 18px;
letter-spacing: 0.2px;
color: rgb(166, 160, 184);
font-family: ${({ theme }) => theme.font.fontFamily.popins};
::after {
color: #20114d;
}
`;
export default CreateStudentModal;



Comments