From 641a0acae2d4e19cecd956d39bbb03ec53dea744 Mon Sep 17 00:00:00 2001 From: r1skz3ro Date: Mon, 15 Jul 2024 12:36:11 +0200 Subject: [PATCH] feat: refactor and id support --- .../people/add-new/layout.tsx | 5 +- .../add-new/main-ladder/[[...id]]/page.tsx | 3 + .../personal-details/[[...id]]/page.tsx | 3 + .../people/add-new/main-ladder/page.tsx | 3 - .../people/add-new/personal-details/page.tsx | 3 - .../modules/SideStepper/SideStepper.tsx | 14 ++- .../pages/MainLadder/MainLadder.hooks.ts | 38 -------- .../pages/MainLadder/MainLadder.interface.ts | 11 --- .../pages/MainLadder/MainLadder.tsx | 88 ------------------- .../PersonalDetails.interface.ts | 11 --- .../AddEmployeeForm.interface.ts | 17 ++++ .../AddEmployeeForm.tsx | 19 ++++ .../AddEmployeeFormProvider/index.ts | 3 + .../MainLadder/MainLadder.hooks.ts | 37 ++++++++ .../addEmployee/MainLadder/MainLadder.tsx | 86 ++++++++++++++++++ .../MainLadder/MainLadder.utils.tsx | 0 .../{ => addEmployee}/MainLadder/index.ts | 0 .../PersonalDetails/PersonalDetails.hooks.ts | 16 ++-- .../PersonalDetails/PersonalDetails.tsx | 17 ++-- .../PersonalDetails/index.ts | 0 20 files changed, 196 insertions(+), 178 deletions(-) rename frontend/src/app/(app)/{(peopleFlow) => (addEmployee)}/people/add-new/layout.tsx (68%) create mode 100644 frontend/src/app/(app)/(addEmployee)/people/add-new/main-ladder/[[...id]]/page.tsx create mode 100644 frontend/src/app/(app)/(addEmployee)/people/add-new/personal-details/[[...id]]/page.tsx delete mode 100644 frontend/src/app/(app)/(peopleFlow)/people/add-new/main-ladder/page.tsx delete mode 100644 frontend/src/app/(app)/(peopleFlow)/people/add-new/personal-details/page.tsx delete mode 100644 frontend/src/components/pages/MainLadder/MainLadder.hooks.ts delete mode 100644 frontend/src/components/pages/MainLadder/MainLadder.interface.ts delete mode 100644 frontend/src/components/pages/MainLadder/MainLadder.tsx delete mode 100644 frontend/src/components/pages/PersonalDetails/PersonalDetails.interface.ts create mode 100644 frontend/src/components/pages/addEmployee/AddEmployeeFormProvider/AddEmployeeForm.interface.ts create mode 100644 frontend/src/components/pages/addEmployee/AddEmployeeFormProvider/AddEmployeeForm.tsx create mode 100644 frontend/src/components/pages/addEmployee/AddEmployeeFormProvider/index.ts create mode 100644 frontend/src/components/pages/addEmployee/MainLadder/MainLadder.hooks.ts create mode 100644 frontend/src/components/pages/addEmployee/MainLadder/MainLadder.tsx rename frontend/src/components/pages/{ => addEmployee}/MainLadder/MainLadder.utils.tsx (100%) rename frontend/src/components/pages/{ => addEmployee}/MainLadder/index.ts (100%) rename frontend/src/components/pages/{ => addEmployee}/PersonalDetails/PersonalDetails.hooks.ts (64%) rename frontend/src/components/pages/{ => addEmployee}/PersonalDetails/PersonalDetails.tsx (78%) rename frontend/src/components/pages/{ => addEmployee}/PersonalDetails/index.ts (100%) diff --git a/frontend/src/app/(app)/(peopleFlow)/people/add-new/layout.tsx b/frontend/src/app/(app)/(addEmployee)/people/add-new/layout.tsx similarity index 68% rename from frontend/src/app/(app)/(peopleFlow)/people/add-new/layout.tsx rename to frontend/src/app/(app)/(addEmployee)/people/add-new/layout.tsx index c51e4e58..189c8645 100644 --- a/frontend/src/app/(app)/(peopleFlow)/people/add-new/layout.tsx +++ b/frontend/src/app/(app)/(addEmployee)/people/add-new/layout.tsx @@ -1,5 +1,6 @@ import { EmployeeSideStepper } from '@app/components/modules/EmployeeSideStepper'; import { WorkflowTopbar } from '@app/components/modules/WorkflowTopbar'; +import { AddEmployeeFormProvider } from '@app/components/pages/addEmployee/AddEmployeeFormProvider'; export default function PeopleLayout({ children }: Readonly<{ children: React.ReactNode }>) { return ( @@ -9,7 +10,9 @@ export default function PeopleLayout({ children }: Readonly<{ children: React.Re
-
{children}
+
+ {children} +
diff --git a/frontend/src/app/(app)/(addEmployee)/people/add-new/main-ladder/[[...id]]/page.tsx b/frontend/src/app/(app)/(addEmployee)/people/add-new/main-ladder/[[...id]]/page.tsx new file mode 100644 index 00000000..36903561 --- /dev/null +++ b/frontend/src/app/(app)/(addEmployee)/people/add-new/main-ladder/[[...id]]/page.tsx @@ -0,0 +1,3 @@ +import { MainLadder } from '@app/components/pages/addEmployee/MainLadder'; + +export default MainLadder; diff --git a/frontend/src/app/(app)/(addEmployee)/people/add-new/personal-details/[[...id]]/page.tsx b/frontend/src/app/(app)/(addEmployee)/people/add-new/personal-details/[[...id]]/page.tsx new file mode 100644 index 00000000..3953665e --- /dev/null +++ b/frontend/src/app/(app)/(addEmployee)/people/add-new/personal-details/[[...id]]/page.tsx @@ -0,0 +1,3 @@ +import { PersonalDetails } from '@app/components/pages/addEmployee/PersonalDetails'; + +export default PersonalDetails; diff --git a/frontend/src/app/(app)/(peopleFlow)/people/add-new/main-ladder/page.tsx b/frontend/src/app/(app)/(peopleFlow)/people/add-new/main-ladder/page.tsx deleted file mode 100644 index 0b96dbcd..00000000 --- a/frontend/src/app/(app)/(peopleFlow)/people/add-new/main-ladder/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { MainLadder } from '@app/components/pages/MainLadder'; - -export default MainLadder; diff --git a/frontend/src/app/(app)/(peopleFlow)/people/add-new/personal-details/page.tsx b/frontend/src/app/(app)/(peopleFlow)/people/add-new/personal-details/page.tsx deleted file mode 100644 index 41475a48..00000000 --- a/frontend/src/app/(app)/(peopleFlow)/people/add-new/personal-details/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { PersonalDetails } from '@app/components/pages/PersonalDetails/PersonalDetails'; - -export default PersonalDetails; diff --git a/frontend/src/components/modules/SideStepper/SideStepper.tsx b/frontend/src/components/modules/SideStepper/SideStepper.tsx index c0f446f7..da6ede53 100644 --- a/frontend/src/components/modules/SideStepper/SideStepper.tsx +++ b/frontend/src/components/modules/SideStepper/SideStepper.tsx @@ -3,16 +3,24 @@ import { SideStepperProps } from './SideStepper.interface'; import { Fragment } from 'react'; import { Typography } from '@app/components/common/Typography'; import { stepComponentsMap } from './SideStepper.utils'; +import { Button } from '@app/components/common/Button'; +import { useRouter } from 'next/navigation'; export const SideStepper = ({ steps }: SideStepperProps) => { + const router = useRouter(); return (
- {steps.map(({ label, state, active }, i) => { + {steps.map(({ label, state, active, href }, i) => { const last = i === steps.length - 1; return ( -
+
+ {!last && (
diff --git a/frontend/src/components/pages/MainLadder/MainLadder.hooks.ts b/frontend/src/components/pages/MainLadder/MainLadder.hooks.ts deleted file mode 100644 index 340720ed..00000000 --- a/frontend/src/components/pages/MainLadder/MainLadder.hooks.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { useFieldArray, useForm } from 'react-hook-form'; -import { MainLadderForm, MainLadderFormNames } from './MainLadder.interface'; -import { useEffect, useState } from 'react'; - -export const useMainLadder = () => { - const form = useForm({ - mode: 'onChange', - defaultValues: { - [MainLadderFormNames.ladder]: {}, - [MainLadderFormNames.technology]: [], - }, - }); - - const technologyFields = useFieldArray({ - name: MainLadderFormNames.technology, - control: form.control, - }); - - const [open, setOpen] = useState(true); - const [selectLadderValid, setSelectLadderValid] = useState(false); - - const handleSubmit = form.handleSubmit((data) => console.log('data', data)); - const values = form.watch(); - const ladderSelected = values?.[MainLadderFormNames.ladder]?.name?.length > 0; - - useEffect(() => { - const firstTechnology = values?.[MainLadderFormNames.technology]?.[0]; - const technologySelected = firstTechnology && firstTechnology.name?.length > 0; - - if (ladderSelected && technologySelected) { - setSelectLadderValid(true); - } else { - setSelectLadderValid(false); - } - }, [values, ladderSelected]); - - return { form, handleSubmit, technologyFields, open, setOpen, ladderSelected, selectLadderValid }; -}; diff --git a/frontend/src/components/pages/MainLadder/MainLadder.interface.ts b/frontend/src/components/pages/MainLadder/MainLadder.interface.ts deleted file mode 100644 index ef9640a7..00000000 --- a/frontend/src/components/pages/MainLadder/MainLadder.interface.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Option } from '@app/components/common/Combobox'; - -export const MainLadderFormNames = { - ladder: 'ladder', - technology: 'technology', -} as const; - -export interface MainLadderForm { - [MainLadderFormNames.ladder]: Option; - [MainLadderFormNames.technology]: Option[]; -} diff --git a/frontend/src/components/pages/MainLadder/MainLadder.tsx b/frontend/src/components/pages/MainLadder/MainLadder.tsx deleted file mode 100644 index f2514184..00000000 --- a/frontend/src/components/pages/MainLadder/MainLadder.tsx +++ /dev/null @@ -1,88 +0,0 @@ -'use client'; -import { Button } from '@app/components/common/Button'; -import { Combobox } from '@app/components/common/Combobox'; -import { FormProvider } from '@app/components/common/FormProvider'; -import { Typography } from '@app/components/common/Typography'; -import { stepComponentsMap } from '@app/components/modules/SideStepper'; -import { MainLadderForm, MainLadderFormNames } from './MainLadder.interface'; -import { useMainLadder } from './MainLadder.hooks'; -import { DeleteIcon } from '@app/static/icons/DeleteIcon'; -import { generateClassNames } from '@app/utils'; -import { ChevronUpIcon } from '@app/static/icons/ChevronUpIcon'; -import { Spacer, ladders, technologies } from './MainLadder.utils'; - -export const MainLadder = () => { - const { form, technologyFields, open, setOpen, ladderSelected, selectLadderValid } = useMainLadder(); - const values = form.watch(); - - return ( - form={form}> -
-
-
-
{stepComponentsMap.inProgress}
- 1. Select Ladder -
- -
- {open && ( -
-
- } - /> - {values?.[MainLadderFormNames.technology].map((tech, i) => { - return ( - - i !== 0 ? ( - - ) : ( - - ) - } - /> - ); - })} - {ladderSelected && ( - - )} -
-
- -
-
- )} -
- - ); -}; diff --git a/frontend/src/components/pages/PersonalDetails/PersonalDetails.interface.ts b/frontend/src/components/pages/PersonalDetails/PersonalDetails.interface.ts deleted file mode 100644 index 503ad06a..00000000 --- a/frontend/src/components/pages/PersonalDetails/PersonalDetails.interface.ts +++ /dev/null @@ -1,11 +0,0 @@ -export const PersonalDetailsFormNames = { - firstName: 'firstName', - lastName: 'lastName', - email: 'email', -} as const; - -export interface PersonalDetailsForm { - [PersonalDetailsFormNames.firstName]: string; - [PersonalDetailsFormNames.lastName]: string; - [PersonalDetailsFormNames.email]: string; -} diff --git a/frontend/src/components/pages/addEmployee/AddEmployeeFormProvider/AddEmployeeForm.interface.ts b/frontend/src/components/pages/addEmployee/AddEmployeeFormProvider/AddEmployeeForm.interface.ts new file mode 100644 index 00000000..7547ed39 --- /dev/null +++ b/frontend/src/components/pages/addEmployee/AddEmployeeFormProvider/AddEmployeeForm.interface.ts @@ -0,0 +1,17 @@ +import { Option } from '@app/components/common/Combobox'; + +export const addEmployeeFormNames = { + firstName: 'firstName', + lastName: 'lastName', + email: 'email', + ladder: 'ladder', + technology: 'technology', +} as const; + +export interface AddEmployeeForm { + [addEmployeeFormNames.firstName]: string; + [addEmployeeFormNames.lastName]: string; + [addEmployeeFormNames.email]: string; + [addEmployeeFormNames.ladder]: Option; + [addEmployeeFormNames.technology]: Option[]; +} diff --git a/frontend/src/components/pages/addEmployee/AddEmployeeFormProvider/AddEmployeeForm.tsx b/frontend/src/components/pages/addEmployee/AddEmployeeFormProvider/AddEmployeeForm.tsx new file mode 100644 index 00000000..8e654493 --- /dev/null +++ b/frontend/src/components/pages/addEmployee/AddEmployeeFormProvider/AddEmployeeForm.tsx @@ -0,0 +1,19 @@ +import { FC, PropsWithChildren } from 'react'; +import { useForm } from 'react-hook-form'; + +import { FormProvider } from '@app/components/common/FormProvider'; +import { AddEmployeeForm, addEmployeeFormNames } from './AddEmployeeForm.interface'; + +export const AddEmployeeFormProvider: FC = ({ children }) => { + const form = useForm({ + mode: 'onChange', + defaultValues: { + [addEmployeeFormNames.firstName]: '', + [addEmployeeFormNames.lastName]: '', + [addEmployeeFormNames.email]: '', + [addEmployeeFormNames.ladder]: {}, + [addEmployeeFormNames.technology]: [], + }, + }); + return form={form}>{children}; +}; diff --git a/frontend/src/components/pages/addEmployee/AddEmployeeFormProvider/index.ts b/frontend/src/components/pages/addEmployee/AddEmployeeFormProvider/index.ts new file mode 100644 index 00000000..7f7db7f2 --- /dev/null +++ b/frontend/src/components/pages/addEmployee/AddEmployeeFormProvider/index.ts @@ -0,0 +1,3 @@ +export { AddEmployeeFormProvider } from './AddEmployeeForm'; +export type { AddEmployeeForm } from './AddEmployeeForm.interface'; +export { addEmployeeFormNames } from './AddEmployeeForm.interface'; diff --git a/frontend/src/components/pages/addEmployee/MainLadder/MainLadder.hooks.ts b/frontend/src/components/pages/addEmployee/MainLadder/MainLadder.hooks.ts new file mode 100644 index 00000000..f22bbfcc --- /dev/null +++ b/frontend/src/components/pages/addEmployee/MainLadder/MainLadder.hooks.ts @@ -0,0 +1,37 @@ +import { useFieldArray, useFormContext } from 'react-hook-form'; +import { useEffect, useState } from 'react'; +import { AddEmployeeForm, addEmployeeFormNames } from '../AddEmployeeFormProvider'; +import { usePeopleStore } from '@app/store/people'; +import { routes } from '@app/constants'; + +export const useMainLadder = () => { + const form = useFormContext(); + const updateProgress = usePeopleStore((state) => state.updateProgress); + + const technologyFields = useFieldArray({ + name: addEmployeeFormNames.technology, + control: form.control, + }); + + const [open, setOpen] = useState(true); + const [formValid, setFormValid] = useState(false); + + const handleSubmit = form.handleSubmit((data) => console.log('data', data)); + const values = form.watch(); + const ladderSelected = values?.[addEmployeeFormNames.ladder]?.name?.length > 0; + const firstTechnology = values?.[addEmployeeFormNames.technology]?.[0]; + + useEffect(() => { + const technologySelected = firstTechnology && firstTechnology.name?.length > 0; + + setFormValid(ladderSelected && technologySelected); + }, [values, ladderSelected, firstTechnology]); + + // INFO: update progress in sidebar stepper + useEffect(() => { + if (formValid) updateProgress({ [routes.people.addNew.mainLadder]: 'completed' }); + else updateProgress({ [routes.people.addNew.mainLadder]: 'inProgress' }); + }, [formValid, updateProgress]); + + return { firstTechnology, form, handleSubmit, technologyFields, open, setOpen, ladderSelected, formValid }; +}; diff --git a/frontend/src/components/pages/addEmployee/MainLadder/MainLadder.tsx b/frontend/src/components/pages/addEmployee/MainLadder/MainLadder.tsx new file mode 100644 index 00000000..0a9a662f --- /dev/null +++ b/frontend/src/components/pages/addEmployee/MainLadder/MainLadder.tsx @@ -0,0 +1,86 @@ +'use client'; +import { Button } from '@app/components/common/Button'; +import { Combobox } from '@app/components/common/Combobox'; +import { Typography } from '@app/components/common/Typography'; +import { stepComponentsMap } from '@app/components/modules/SideStepper'; +import { useMainLadder } from './MainLadder.hooks'; +import { DeleteIcon } from '@app/static/icons/DeleteIcon'; +import { generateClassNames } from '@app/utils'; +import { ChevronUpIcon } from '@app/static/icons/ChevronUpIcon'; +import { Spacer, ladders, technologies } from './MainLadder.utils'; +import { addEmployeeFormNames } from '../AddEmployeeFormProvider'; + +export const MainLadder = () => { + const { form, technologyFields, open, setOpen, ladderSelected, formValid, firstTechnology } = useMainLadder(); + const values = form.watch(); + + return ( +
+
+
+
{formValid ? stepComponentsMap.completed : stepComponentsMap.inProgress}
+ 1. Select Ladder +
+ +
+ {open && ( +
+
+ } + /> + {values?.[addEmployeeFormNames.technology].map((tech, i) => { + return ( + + i !== 0 ? ( + + ) : ( + + ) + } + /> + ); + })} + {ladderSelected && ( + + )} +
+
+ +
+
+ )} +
+ ); +}; diff --git a/frontend/src/components/pages/MainLadder/MainLadder.utils.tsx b/frontend/src/components/pages/addEmployee/MainLadder/MainLadder.utils.tsx similarity index 100% rename from frontend/src/components/pages/MainLadder/MainLadder.utils.tsx rename to frontend/src/components/pages/addEmployee/MainLadder/MainLadder.utils.tsx diff --git a/frontend/src/components/pages/MainLadder/index.ts b/frontend/src/components/pages/addEmployee/MainLadder/index.ts similarity index 100% rename from frontend/src/components/pages/MainLadder/index.ts rename to frontend/src/components/pages/addEmployee/MainLadder/index.ts diff --git a/frontend/src/components/pages/PersonalDetails/PersonalDetails.hooks.ts b/frontend/src/components/pages/addEmployee/PersonalDetails/PersonalDetails.hooks.ts similarity index 64% rename from frontend/src/components/pages/PersonalDetails/PersonalDetails.hooks.ts rename to frontend/src/components/pages/addEmployee/PersonalDetails/PersonalDetails.hooks.ts index f7fcda6e..dc91569a 100644 --- a/frontend/src/components/pages/PersonalDetails/PersonalDetails.hooks.ts +++ b/frontend/src/components/pages/addEmployee/PersonalDetails/PersonalDetails.hooks.ts @@ -1,18 +1,12 @@ import { routes } from '@app/constants'; import { useEffect, useState } from 'react'; -import { useForm } from 'react-hook-form'; -import { PersonalDetailsForm, PersonalDetailsFormNames } from './PersonalDetails.interface'; +import { useFormContext } from 'react-hook-form'; + import { usePeopleStore } from '@app/store/people/store'; +import { AddEmployeeForm } from '../AddEmployeeFormProvider'; export const usePersonalDetails = () => { - const form = useForm({ - mode: 'onChange', - defaultValues: { - [PersonalDetailsFormNames.firstName]: '', - [PersonalDetailsFormNames.lastName]: '', - [PersonalDetailsFormNames.email]: '', - }, - }); + const form = useFormContext(); const { isDirty, isValid } = form.formState; const [formValid, setFormValid] = useState(false); const updateProgress = usePeopleStore((state) => state.updateProgress); @@ -27,5 +21,5 @@ export const usePersonalDetails = () => { else updateProgress({ [routes.people.addNew.personalDetails]: 'inProgress' }); }, [formValid, updateProgress]); - return { form, formValid }; + return { formValid }; }; diff --git a/frontend/src/components/pages/PersonalDetails/PersonalDetails.tsx b/frontend/src/components/pages/addEmployee/PersonalDetails/PersonalDetails.tsx similarity index 78% rename from frontend/src/components/pages/PersonalDetails/PersonalDetails.tsx rename to frontend/src/components/pages/addEmployee/PersonalDetails/PersonalDetails.tsx index dbbd85a6..7bf94d13 100644 --- a/frontend/src/components/pages/PersonalDetails/PersonalDetails.tsx +++ b/frontend/src/components/pages/addEmployee/PersonalDetails/PersonalDetails.tsx @@ -1,25 +1,24 @@ 'use client'; import { Button } from '@app/components/common/Button'; -import { FormProvider } from '@app/components/common/FormProvider'; import { Input } from '@app/components/common/Input'; import { Typography } from '@app/components/common/Typography'; -import { PersonalDetailsForm, PersonalDetailsFormNames } from './PersonalDetails.interface'; import { usePersonalDetails } from './PersonalDetails.hooks'; import { routes } from '@app/constants'; import { useRouter } from 'next/navigation'; +import { addEmployeeFormNames } from '../AddEmployeeFormProvider'; export const PersonalDetails = () => { - const { form, formValid } = usePersonalDetails(); + const { formValid } = usePersonalDetails(); const router = useRouter(); return ( - form={form}> + <> Personal details
{ }} /> { }} /> { styleType="primary" variant="border" onClick={() => router.push(routes.people.addNew.mainLadder)} - disabled={formValid} + disabled={!formValid} > Continue
- + ); }; diff --git a/frontend/src/components/pages/PersonalDetails/index.ts b/frontend/src/components/pages/addEmployee/PersonalDetails/index.ts similarity index 100% rename from frontend/src/components/pages/PersonalDetails/index.ts rename to frontend/src/components/pages/addEmployee/PersonalDetails/index.ts