Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Guest application formik context #630 #640

Merged
merged 38 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
9a28fe7
feat: context wrapper skeleton and route
JpadillaCoding Oct 26, 2023
f1487f8
feat: initial values of questions
JpadillaCoding Oct 26, 2023
8dc0959
feat: button layout made to respond depending on the form page
JpadillaCoding Nov 4, 2023
e52d7f2
refrac: made buttons individual components
JpadillaCoding Nov 8, 2023
b008fe1
refrac: buttons needed navigation moved inside the component
JpadillaCoding Nov 9, 2023
750d666
feat: initial yup validation needs for guest application
JpadillaCoding Nov 11, 2023
fca7a63
style: nav buttons updated to have proper colors
JpadillaCoding Nov 11, 2023
c79646f
feat: implemented progress bar tracker
JpadillaCoding Nov 11, 2023
c06df92
style: color matching progress bar and buttons
JpadillaCoding Nov 12, 2023
04a0e86
style: guest context container styling
JpadillaCoding Nov 12, 2023
0a79be4
resolving conflicts
JpadillaCoding Nov 12, 2023
2abec29
refrac: made schema into an array to fit validation based on step
JpadillaCoding Nov 12, 2023
25f0a25
feat: error messages added to schema validation along with better dat…
JpadillaCoding Nov 12, 2023
8c27707
feat: added prop to navigate user to intended page based on next and …
JpadillaCoding Nov 12, 2023
e19d5b1
bug: setup stepper state and variables in context for usage throughou…
JpadillaCoding Nov 13, 2023
25a3529
bug: attempting different approach on buttons to make them more dynamic
JpadillaCoding Nov 14, 2023
0e0cb4e
feat: navButtons now one file
JpadillaCoding Nov 14, 2023
9e56b0d
feat: updated Date validation to meet format requirements
JpadillaCoding Nov 18, 2023
8e43d5d
feat: added a check to make sure the current step is validated
JpadillaCoding Nov 18, 2023
583f0d4
bug to work on: layout styling for context
JpadillaCoding Nov 29, 2023
27f79c4
style: buttons stay at teh bottom of screen
JpadillaCoding Dec 1, 2023
269aa27
Merge branch 'main' of github.com:hackforla/HomeUniteUs into GuestApp…
JpadillaCoding Dec 1, 2023
76205ca
reselved merge conflict with package-lock. Accepted incoming changes.
JpadillaCoding Dec 16, 2023
2a9e504
refrac: moved button logic to parent component
JpadillaCoding Jan 12, 2024
3fc4547
tested changing functions to parent component with mock form
JpadillaCoding Jan 14, 2024
a9056f2
Merge branch 'main' of github.com:hackforla/HomeUniteUs into GuestApp…
JpadillaCoding Jan 14, 2024
90867a8
bug: getting GH actions checks failures. reinstalled all dependecies …
JpadillaCoding Jan 14, 2024
05e191e
Revert "tested changing functions to parent component with mock form"
JpadillaCoding Jan 14, 2024
ae21280
deleted form testing files and fixed bug causing context to not load
JpadillaCoding Jan 14, 2024
70d96e1
reverted package-lock before changes
JpadillaCoding Jan 14, 2024
e1a9489
ran npm install for updating package-lock
JpadillaCoding Jan 14, 2024
df39a24
copied lock file from main
JpadillaCoding Jan 14, 2024
7dfacf1
deleted lock file added to root
JpadillaCoding Jan 14, 2024
a245e70
added date-fns to package-lock
JpadillaCoding Jan 14, 2024
9d085e4
copied main and manually added date-fns and ran npm ci
JpadillaCoding Jan 14, 2024
a61c62a
Merge branch 'main' of github.com:hackforla/HomeUniteUs into GuestApp…
JpadillaCoding Jan 18, 2024
193e293
Merge branch 'main' of github.com:hackforla/HomeUniteUs into GuestApp…
JpadillaCoding Feb 5, 2024
bbcadfa
refrac: Variable name change and optimized tracker by reducing unnece…
JpadillaCoding Feb 5, 2024
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
26 changes: 25 additions & 1 deletion app/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 app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@mui/material": "^5.8.6",
"@mui/x-data-grid": "^6.15.0",
"@reduxjs/toolkit": "^1.8.3",
"date-fns": "^2.30.0",
"formik": "^2.2.9",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
37 changes: 37 additions & 0 deletions app/src/components/common/GuestApplicationButtons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {Button, Stack} from '@mui/material';

export const NavButtons = ({
erikguntner marked this conversation as resolved.
Show resolved Hide resolved
next,
prev,
saveAndExit,
}: {
next: () => void;
prev: () => void;
saveAndExit: () => void;
}) => {
return (
<Stack gap={2}>
<Button fullWidth size="medium" variant="contained" onClick={next}>
Continue
</Button>
<Button
fullWidth
size="medium"
variant="outlined"
onClick={prev}
sx={{color: 'black', border: 2, borderColor: 'primary.main'}}
>
Back
</Button>
<Button
fullWidth
size="medium"
onClick={saveAndExit}
variant="text"
sx={{color: 'black'}}
>
Save and Exit
</Button>
</Stack>
);
};
134 changes: 134 additions & 0 deletions app/src/components/common/GuestApplicationContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import {Box, Stack} from '@mui/material';
import {Formik} from 'formik';
import {useEffect, useState} from 'react';
import {Outlet} from 'react-router-dom';
import ProgressBar from './ProgressBar';
import {GuestApplicationSchema} from '../../utils/GuestApplicationSchema';
import {NavButtons} from './GuestApplicationButtons';
import {useNavigate} from 'react-router-dom';

export interface formInputValues {
fullName: string;
dateOfBirth: string;
gender: string;
email: string;
phoneNumber: string;
contactPrefrence: string;
nameOfGuest: Array<string>;
typeOfPet: Array<string>;
currentlyEmployed: string;
employmentSearch: string;
employmentDescription: string;
educationEnrollment: string;
educationEnrollmentSearch: string;
educationProgramName: string;
multilingual: string;
spokenLanguages: string;
cigarettesUse: string;
alcoholUse: string;
otherSubstanceUse: string;
mentalIllness: string;
programGoals: string;
hostRelationshipGoal: string;
potentialChallenges: string;
}
export const stepToRouteMapping: {[key: number]: string} = {
1: '',
};
export const initialValues = {
fullName: '',
dateOfBirth: '',
gender: '',
email: '',
phoneNumber: '',
contactPrefrence: '',
nameOfGuest: [''],
typeOfPet: [''],
currentlyEmployed: '',
employmentSearch: '',
employmentDescription: '',
educationEnrollment: '',
educationEnrollmentSearch: '',
educationProgramName: '',
multilingual: '',
spokenLanguages: '',
cigarettesUse: '',
alcoholUse: '',
otherSubstanceUse: '',
mentalIllness: '',
programGoals: '',
hostRelationshipGoal: '',
potentialChallenges: '',
};

export const GuestApplicationContext = () => {
const TOTALPAGES = 10; /*Once all forms are made and added to "stepToRouteMapping", make this number change based on "stepToRouteMapping"*/
erikguntner marked this conversation as resolved.
Show resolved Hide resolved
const storedStep = localStorage.getItem('currentStep');
const initialStep = storedStep ? parseInt(storedStep, 10) : 1;
erikguntner marked this conversation as resolved.
Show resolved Hide resolved
const [step, setStep] = useState<number>(initialStep);
erikguntner marked this conversation as resolved.
Show resolved Hide resolved
const progressBarValue = (step / TOTALPAGES) * 100;
const navigate = useNavigate();

useEffect(() => {
navigate(stepToRouteMapping[step]);
}, []);
useEffect(() => {
localStorage.setItem('currentStep', step.toString());
}, [step]);
function saveData() {
//add logic to save current data
console.log('data saving features not implemented');
}
function nextStep() {
saveData();
const newStep = step + 1;
if (stepToRouteMapping[newStep] !== undefined) {
setStep(newStep);
navigate(stepToRouteMapping[newStep]);
} else {
alert('Form not complete!');
}
}
function prevStep() {
const newStep = step - 1;
if (step > 1) {
setStep(newStep);
navigate(stepToRouteMapping[newStep]);
} else {
navigate('/guest');
}
}
function saveAndExit() {
saveData();
navigate('/guest');
}

return (
<Formik
initialValues={initialValues}
onSubmit={() => console.log('Parent wrapper submit')}
validationSchema={GuestApplicationSchema[step - 1]}
>
<Box padding={2} gap={0} height={'95vh'}>
<Stack>
<ProgressBar progressBarValue={progressBarValue} />
</Stack>
<Stack
marginTop={2}
overflow={'scroll'}
minHeight={'72%'}
maxHeight={'72%'}
>
<Outlet />
</Stack>
<Stack>
<NavButtons
next={nextStep}
prev={prevStep}
saveAndExit={saveAndExit}
/>
</Stack>
</Box>
</Formik>
);
};
29 changes: 29 additions & 0 deletions app/src/components/common/ProgressBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {styled} from '@mui/material/styles';
import Box from '@mui/material/Box';
import LinearProgress, {
linearProgressClasses,
} from '@mui/material/LinearProgress';

const BorderLinearProgress = styled(LinearProgress)(({theme}) => ({
height: 10,
borderRadius: 5,
[`&.${linearProgressClasses.colorPrimary}`]: {
backgroundColor: theme.palette.grey[300],
},
[`& .${linearProgressClasses.bar}`]: {
borderRadius: 5,
backgroundColor: theme.palette.primary,
},
}));

export default function ProgressBar({
progressBarValue,
}: {
progressBarValue: number;
}) {
return (
<Box sx={{flexGrow: 1}}>
<BorderLinearProgress variant="determinate" value={progressBarValue} />
</Box>
);
}
1 change: 1 addition & 0 deletions app/src/components/layout/GuestDashboardLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const navItems = [
},
{title: 'My Contacts', icon: <ContactsOutlined />, href: '/guest/contacts'},
{title: 'Settings', icon: <SettingsOutlined />, href: '/guest/settings'},
{title: 'Application', icon: <TaskOutlined />, href: '/guest/application'},
];

export const GuestDashboardLayout = () => {
Expand Down
5 changes: 5 additions & 0 deletions app/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
CoordinatorDashboardLayout,
GuestDashboardLayout,
} from './components/layout';
import {GuestApplicationContext} from './components/common/GuestApplicationContext';

function HuuApp() {
const [session] = useSessionMutation();
Expand Down Expand Up @@ -94,6 +95,10 @@ function HuuApp() {
<Route path="contacts" element={<GuestContacts />} />
<Route path="tasks" element={<GuestTasks />} />
<Route path="settings" element={<GuestSettings />} />
<Route
path="application"
element={<GuestApplicationContext />}
></Route>
</Route>
<Route
path="/coordinator"
Expand Down
89 changes: 89 additions & 0 deletions app/src/utils/GuestApplicationSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import {parse, isDate} from 'date-fns';
import {array, date, object, string} from 'yup';

export const GuestApplicationSchema = [
//validation is based on step
object({
fullName: string().required('Name is required'),
dateOfBirth: date()
.transform(parseDateString)
.typeError('Please use correct format')
.required('Date of Birth is required')
.min(new Date('01/01/1900'), 'Set a valid date')
.max(new Date(), 'Date cannot be in the future'),
gender: string().required('Select an option'),
}),
object({
email: string().email('Invalid email format').required('Email is required'),
phoneNumber: string()
.required()
.matches(
/^((\\+[1-9]{1,4}[ \\-]*)|(\\([0-9]{2,3}\\)[ \\-]*)|([0-9]{2,4})[ \\-]*)*?[0-9]{3,4}?[ \\-]*[0-9]{3,4}?$/,
'Phone number is not valid.',
)
.required('Phone number is required'),
contactPrefrence: string().required('Select an option'),
}),
object({
nameOfGuestArray: array().of(
object({
nameOfGuest: string().required('Name is Required'),
}),
),
typeOfPetArray: array().of(
object({
typeOfPet: string().required('Pet Type is Required'),
}),
),
}),
object({
currentlyEmployed: string().required('Select an option'),
employmentSearch: string().when('currentlyEmployed', {
is: (currentlyEmployed: string) => currentlyEmployed === 'No',
then: string().required('Field is required'),
}),
employmentDescription: string().when('currentlyEmployed', {
is: (currentlyEmployed: string) => currentlyEmployed === 'Yes',
then: string().required('Field is required'),
}),
}),
object({
educationEnrollment: string().required('Select an option'),
educationEnrollmentSearch: string().when('educationEnrollment', {
is: (educationEnrollment: string) => educationEnrollment === 'No',
then: string().required('Field is required'),
}),
educationProgramName: string().when('educationEnrollment', {
is: (educationEnrollment: string) => educationEnrollment === 'Yes',
then: string().required('Field is required'),
}),
}),
object({
multilingual: string().required('Select an option'),
spokenLanguages: string().when('multilingual', {
is: (multilingual: string) => multilingual === 'Yes',
then: string().required('Field is required'),
}),
}),
object({
cigarettesUse: string().required('Select an option'),
alcoholUse: string().required('Select an option'),
otherSubstanceUse: string().required('Select an option'),
}),
object({
mentalIllness: string().required('Select an option'),
}),
object({
programGoals: string().required('Field is required'),
hostRelationshipGoal: string().required('Field is required'),
potentialChallenges: string().required('Field is required'),
}),
];

function parseDateString(value: string, originalValue: string) {
const parsedDate = isDate(originalValue)
? originalValue
: parse(originalValue, 'MM/dd/yyyy', new Date());

return parsedDate;
}