From 9378ee6c315b07478403659417f2052844ed4662 Mon Sep 17 00:00:00 2001 From: Ibrahim Date: Tue, 13 Aug 2024 18:46:12 +0000 Subject: [PATCH 1/4] Student Wizard Menu creation. Implementation of student wizard page. Add Stepper component to student wizard page --- .env | 8 +- package.json | 1 + src/components/routes/RouteList.tsx | 7 +- src/components/students/WizardAttendance.tsx | 116 +++++++++++ src/components/students/WizardEnrollment.tsx | 109 ++++++++++ src/components/students/WizardFinalResult.tsx | 87 ++++++++ src/components/students/WizardForm.tsx | 63 ++++++ src/components/students/WizardPerformance.tsx | 87 ++++++++ src/components/students/WizardProgram.tsx | 67 ++++++ .../students/WizardSocioEconomics.tsx | 86 ++++++++ src/components/students/WizardTransfer.tsx | 87 ++++++++ src/components/students/index.module.css | 25 +++ src/components/students/index.ts | 3 +- src/hooks/students/useAttendanceSubmit.ts | 8 +- src/hooks/students/useEnrollmentSubmit.ts | 5 +- src/hooks/students/useGetProgramFormField.ts | 3 +- src/hooks/students/useSocioEconomicsSubmit.ts | 5 +- src/hooks/students/useSubmitProgramDatas.ts | 7 +- src/pages/index.tsx | 29 ++- src/pages/students/Student_Wizard.tsx | 12 ++ src/pages/students/index.ts | 10 +- src/types/moduleConfigurations/index.ts | 1 + src/types/students/index.ts | 1 + src/utils/constants/sideBar/sideBarData.ts | 8 +- yarn.lock | 190 ++++++++++++++++-- 25 files changed, 993 insertions(+), 32 deletions(-) create mode 100644 src/components/students/WizardAttendance.tsx create mode 100644 src/components/students/WizardEnrollment.tsx create mode 100644 src/components/students/WizardFinalResult.tsx create mode 100644 src/components/students/WizardForm.tsx create mode 100644 src/components/students/WizardPerformance.tsx create mode 100644 src/components/students/WizardProgram.tsx create mode 100644 src/components/students/WizardSocioEconomics.tsx create mode 100644 src/components/students/WizardTransfer.tsx create mode 100644 src/components/students/index.module.css create mode 100644 src/pages/students/Student_Wizard.tsx diff --git a/.env b/.env index 3e79626..0b28ba7 100644 --- a/.env +++ b/.env @@ -1,4 +1,4 @@ -REACT_APP_DATA_STORE_NAME="semis" -REACT_APP_DATA_STORE_APP_NAME="apps" -REACT_APP_DATA_STORE_SEMIS_CONFIG_KEY="config" -REACT_APP_DATA_STORE_SEMIS_VALUES_KEY="values" \ No newline at end of file +REACT_APP_DATA_STORE_NAME="ibrahim" +REACT_APP_DATA_STORE_APP_NAME="ibrahimapps" +REACT_APP_DATA_STORE_SEMIS_CONFIG_KEY="ibrahimconfig" +REACT_APP_DATA_STORE_SEMIS_VALUES_KEY="ibrahimvalues" \ No newline at end of file diff --git a/package.json b/package.json index 570e796..4015a03 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "react-dnd": "14.0.3", "react-dnd-html5-backend": "14.0.1", "react-final-form": "^6.5.9", + "react-form-stepper": "^2.0.3", "react-icons": "^4.12.0", "react-router-dom": "^6.14.1", "react-select": "1.3.0", diff --git a/src/components/routes/RouteList.tsx b/src/components/routes/RouteList.tsx index f32e9cf..66deb62 100644 --- a/src/components/routes/RouteList.tsx +++ b/src/components/routes/RouteList.tsx @@ -1,7 +1,7 @@ import { Navigate } from "react-router-dom"; import React from "react"; import { SideBarLayout, SimpleLayout } from "../../layout" -import { AppsConfiguration, AppsInstallation, GenericForm, StaffAttendance, StaffEnrollment, StaffProgram, StudentsAttendance, StudentsEnrollment, StudentsPerformance, StudentsProgram, StudentsSocioEconomics } from "../../pages"; +import { AppsConfiguration, AppsInstallation, GenericForm, StaffAttendance, StaffEnrollment, StaffProgram, StudentWizard, StudentsAttendance, StudentsEnrollment, StudentsPerformance, StudentsProgram, StudentsSocioEconomics } from "../../pages"; import StudentsFinalResults from "../../pages/students/Student_FinalResultConfig"; import StudentsTransfer from "../../pages/students/Student_TransferConfig"; import StaffTransfer from "../../pages/staff/Staff_TransferConfig"; @@ -14,6 +14,11 @@ export default function RouteList() { layout: SimpleLayout, component: () => }, + { + path: "/students/wizard", + layout: SideBarLayout, + component: () => + }, { path: "/students/program", layout: SideBarLayout, diff --git a/src/components/students/WizardAttendance.tsx b/src/components/students/WizardAttendance.tsx new file mode 100644 index 0000000..6d42227 --- /dev/null +++ b/src/components/students/WizardAttendance.tsx @@ -0,0 +1,116 @@ +import React, { useState, useEffect } from "react"; +import { NoticeBox, Button } from '@dhis2/ui' +import { getDataStoreElement } from "../../utils/functions"; +import { useGetAttendanceFormFields } from "../../hooks/students"; +import useLoadProgramStages from "../../hooks/commons/useLoadProgramStages"; +import useLoadDataElements from "../../hooks/commons/useLoadDataElements"; +import { + type SubmitAttendanceValue, + type LoadDataElementsResponse, + type UseFetchEnrollmentDatasResponse +} from "../../types/students"; +import Loading from "../appList/Loading"; +import useLoadDataStoreDatas from "../../hooks/commons/useLoadDataStoreDatas"; +import useAttendanceSubmit from "../../hooks/students/useAttendanceSubmit"; + +import style from './index.module.css' +import { Form } from "react-final-form" +import { GroupForm } from ".."; + +interface ZizardProgramProps { + setWizardSetp: React.Dispatch> +} + +export default function WizardAttendance({ setWizardSetp }: ZizardProgramProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState() + const { getDataElements, dataElementsDatas }: LoadDataElementsResponse = useLoadDataElements() + const { getFormFields } = useGetAttendanceFormFields() + const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() + const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() + const { submit, loadingProcessing } = useAttendanceSubmit() + + useEffect(() => { + if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "student" }) + const programStageId = getDataStoreElement({ dataStores: data?.dataStoreValues, elementKey: "attendance", key: "student" })?.programStage + const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "attendance", key: "student" })?.programStage?.filter + + if (programId === undefined) { + setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") + } + if (programId !== null && programId !== undefined) { + void getProgramStages(programId, studentProgramFilterConfig) + } + if (programStageId !== null && programStageId !== undefined) { + getDataElements(programStageId) + } + } + }, [data]) + + return ( + <> + + { + (error !== undefined && error !== null) && ( + + {error.message} + + ) + } + +
+ {(data !== undefined && data !== null) && ( +
+
{ + await submit({ values, dataStoreValues: data.dataStoreValues, dataStoreConfigs: data.dataStoreConfigs, goToNext: () => { setWizardSetp(4) } }) + }} + initialValues={ + { + programStage: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.programStage, + absenceReason: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.absenceReason, + status: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.status, + absentCode: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.statusOptions?.find((x: any) => x.key === "absent")?.code, + presentCode: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.statusOptions?.find((x: any) => x.key === "present")?.code, + lateCode: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.statusOptions?.find((x: any) => x.key === "late")?.code, + leaveCode: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.statusOptions?.find((x: any) => x.key === "leave")?.code, + } + } + render={ + ({ handleSubmit, form }: any) => { + const cancelBtn = () => { + // form.change("programStage", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.programStage) + // form.change("absenceReason", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.absenceReason) + // form.change("status", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.status) + } + + return programStagesDatas?.programStages?.length > 0 && ( + + 0 + ? dataElementsDatas?.dataElements + : [] + })} + /> +
+
+
+
+ + ) + } + } + /> +
+ )} +
+ + ); +} diff --git a/src/components/students/WizardEnrollment.tsx b/src/components/students/WizardEnrollment.tsx new file mode 100644 index 0000000..2ff5fb6 --- /dev/null +++ b/src/components/students/WizardEnrollment.tsx @@ -0,0 +1,109 @@ +import React, { useState, useEffect } from "react"; +import { NoticeBox, Button } from '@dhis2/ui' +import { getDataStoreElement } from "../../utils/functions"; +import useGetEnrollmentField from "../../hooks/students/useGetEnrollmentField"; +import useLoadProgramStages from "../../hooks/commons/useLoadProgramStages"; +import useLoadDataElements from "../../hooks/commons/useLoadDataElements"; +import useEnrollmentSubmit from "../../hooks/students/useEnrollmentSubmit"; +import useLoadDataStoreDatas from "../../hooks/commons/useLoadDataStoreDatas"; +import Loading from "../appList/Loading"; +import style from './index.module.css' + +import { Form } from "react-final-form" +import GroupForm from "../form/GroupForm"; +import { type SubmitEnrollmentValue } from "../../types/students"; + +interface ZizardProgramProps { + setWizardSetp: React.Dispatch> +} + +export default function WizardEnrollment({ setWizardSetp }: ZizardProgramProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState() + const { getDataElements, dataElementsDatas } = useLoadDataElements() + const { getFormFields } = useGetEnrollmentField() + const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() + const { submit, loadingProcessing } = useEnrollmentSubmit() + const { data, loading, error } = useLoadDataStoreDatas() + + useEffect(() => { + if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null && data?.dataStoreConfigs !== null && data?.dataStoreConfigs !== undefined) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "student" }) + const programStageId = getDataStoreElement({ dataStores: data?.dataStoreValues, elementKey: "registration", key: "student" })?.programStage + const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "registration", key: "student" })?.programStage?.filter + + if (programId === undefined) { + setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") + } + + if (programId !== null && programId !== undefined) { + void getProgramStages(programId, studentProgramFilterConfig) + } + if (programStageId !== null && programStageId !== undefined) { + void getDataElements(programStageId) + } + } + }, [data]) + + return ( + <> + { + console.log(programStagesDatas) + } + { + console.log(dataElementsDatas) + } + + { + (error !== undefined && error !== null) && ( + + {error.message} + + ) + } + +
+ {(data !== undefined && data !== null) && ( +
+
{ + await submit(value, data.dataStoreValues, data.dataStoreConfigs, () => { setWizardSetp(2) }) + }} + render={ + ({ handleSubmit }: { handleSubmit: any }) => { + return programStagesDatas?.programStages?.length > 0 && ( + + +
+
+
+
+ + ) + } + } + /> +
+ )} +
+ + ); +} diff --git a/src/components/students/WizardFinalResult.tsx b/src/components/students/WizardFinalResult.tsx new file mode 100644 index 0000000..c97cb71 --- /dev/null +++ b/src/components/students/WizardFinalResult.tsx @@ -0,0 +1,87 @@ +import React, { useState, useEffect } from "react"; +import { Button, NoticeBox } from '@dhis2/ui' +import { getDataStoreElement } from "../../utils/functions"; +import { useGetSocioEconomicsFormFields, useSocioEconomicsSubmit } from "../../hooks/students"; +import useLoadProgramStages from "../../hooks/commons/useLoadProgramStages"; +import { + type UseFetchEnrollmentDatasResponse +} from "../../types/students"; +import Loading from "../appList/Loading"; +import useLoadDataStoreDatas from "../../hooks/commons/useLoadDataStoreDatas"; + + +import style from './index.module.css' +import { Form } from "react-final-form" +import { type SubmitEnrollmentValue } from "../../types/students"; +import { GroupForm } from ".."; + +interface ZizardProgramProps { + setWizardSetp: React.Dispatch> +} + +export default function WizardFinalResult({ setWizardSetp }: ZizardProgramProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState() + const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() + const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() + const { getFormFields } = useGetSocioEconomicsFormFields() + const { submit, loadingProcessing } = useSocioEconomicsSubmit() + + useEffect(() => { + if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "student" }) + const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "socio-economics", key: "student" })?.programStage?.filter + + if (programId === undefined) { + setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") + } + if (programId !== null && programId !== undefined) { + void getProgramStages(programId, studentProgramFilterConfig) + } + } + }, [data]) + + + return ( + <> + { + console.log(programStagesDatas) + } + + { + (error !== undefined && error !== null) && ( + + {error.message} + + ) + } + +
+ {(data !== undefined && data !== null) && ( +
+
{ await submit({ programStage: values?.programStage }, data?.dataStoreValues, data?.dataStoreConfigs, () => { setWizardSetp(3) }) }} + render={ + ({ handleSubmit }: { handleSubmit: any }) => { + return programStagesDatas?.programStages?.length > 0 && ( + + +
+
+
+
+ + ) + } + } + /> +
+ )} +
+ + ); +} diff --git a/src/components/students/WizardForm.tsx b/src/components/students/WizardForm.tsx new file mode 100644 index 0000000..776a09b --- /dev/null +++ b/src/components/students/WizardForm.tsx @@ -0,0 +1,63 @@ +import React, { useState } from "react"; +import { Stepper, Step } from "react-form-stepper"; +import WizardProgram from "./WizardProgram"; +import WizardEnrollment from "./WizardEnrollment"; +import WizardSocioEconomics from "./WizardSocioEconomics"; +import WizardAttendance from "./WizardAttendance"; +import WizardPerformance from "./WizardPerformance"; +import WizardFinalResult from "./WizardFinalResult"; +import WizardTransfer from "./WizardTransfer"; + +const steps = [ + { label: "Program" }, + { label: "Enrollment" }, + { label: "Socio Economic" }, + { label: "Attendance" }, + { label: "Performance" }, + { label: "Final Result" }, + { label: "Transfer" } +] + +export default function WizardForm() { + const [wizardStep, setWizardSetp] = useState(0) + + const RenderContent = () => { + switch (wizardStep) { + case 0: + return + case 1: + return + case 2: + return + case 3: + return + case 4: + return + case 5: + return + case 6: + return + default: + return <> + } + } + + return ( + <> + + { + steps.map((step, index) => { setWizardSetp(index) }} label={step.label} />) + } + + + + ); +} diff --git a/src/components/students/WizardPerformance.tsx b/src/components/students/WizardPerformance.tsx new file mode 100644 index 0000000..bdd9c43 --- /dev/null +++ b/src/components/students/WizardPerformance.tsx @@ -0,0 +1,87 @@ +import React, { useState, useEffect } from "react"; +import { Button, NoticeBox } from '@dhis2/ui' +import { getDataStoreElement } from "../../utils/functions"; +import { useGetSocioEconomicsFormFields, useSocioEconomicsSubmit } from "../../hooks/students"; +import useLoadProgramStages from "../../hooks/commons/useLoadProgramStages"; +import { + type UseFetchEnrollmentDatasResponse +} from "../../types/students"; +import Loading from "../appList/Loading"; +import useLoadDataStoreDatas from "../../hooks/commons/useLoadDataStoreDatas"; + + +import style from './index.module.css' +import { Form } from "react-final-form" +import { type SubmitEnrollmentValue } from "../../types/students"; +import { GroupForm } from ".."; + +interface ZizardProgramProps { + setWizardSetp: React.Dispatch> +} + +export default function WizardPerformance({ setWizardSetp }: ZizardProgramProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState() + const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() + const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() + const { getFormFields } = useGetSocioEconomicsFormFields() + const { submit, loadingProcessing } = useSocioEconomicsSubmit() + + useEffect(() => { + if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "student" }) + const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "socio-economics", key: "student" })?.programStage?.filter + + if (programId === undefined) { + setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") + } + if (programId !== null && programId !== undefined) { + void getProgramStages(programId, studentProgramFilterConfig) + } + } + }, [data]) + + + return ( + <> + { + console.log(programStagesDatas) + } + + { + (error !== undefined && error !== null) && ( + + {error.message} + + ) + } + +
+ {(data !== undefined && data !== null) && ( +
+
{ await submit({ programStage: values?.programStage }, data?.dataStoreValues, data?.dataStoreConfigs, () => { setWizardSetp(3) }) }} + render={ + ({ handleSubmit }: { handleSubmit: any }) => { + return programStagesDatas?.programStages?.length > 0 && ( + + +
+
+
+
+ + ) + } + } + /> +
+ )} +
+ + ); +} diff --git a/src/components/students/WizardProgram.tsx b/src/components/students/WizardProgram.tsx new file mode 100644 index 0000000..2739304 --- /dev/null +++ b/src/components/students/WizardProgram.tsx @@ -0,0 +1,67 @@ +import React, { useState, useEffect } from "react"; +import Loading from "../appList/Loading"; +import { useGetProgramFormField, useSubmitProgramDatas } from "../../hooks/students"; +import useLoadPrograms from "../../hooks/commons/useLoadPrograms"; +import { NoticeBox, Button } from '@dhis2/ui' +import { Form } from "react-final-form" +import style from './index.module.css' +import GroupForm from "../form/GroupForm"; +import { getDataStoreElement } from "../../utils/functions"; + +interface ZizardProgramProps { + setWizardSetp: React.Dispatch> +} + +export default function WizardProgram({ setWizardSetp }: ZizardProgramProps) { + const { data, error, loading } = useLoadPrograms() + const { getFormFields } = useGetProgramFormField() + const { loadingProcessing, submit } = useSubmitProgramDatas() + + return ( + <> + + { + (error !== undefined && error !== null) && ( + + {error.message} + + ) + } + +
+ {(data !== undefined && data !== null) && ( +
+
{ + await submit({ + data, + program: values.program, + goToNext: () => { setWizardSetp(1) } + }) + }} + render={ + ({ handleSubmit, form }: { handleSubmit: any, form: any }) => { + return data?.programs?.length > 0 && ( + + +
+
+
+
+ + ) + } + } + /> + +
+ )} +
+ + ); +} diff --git a/src/components/students/WizardSocioEconomics.tsx b/src/components/students/WizardSocioEconomics.tsx new file mode 100644 index 0000000..aa263a9 --- /dev/null +++ b/src/components/students/WizardSocioEconomics.tsx @@ -0,0 +1,86 @@ +import React, { useState, useEffect } from "react"; +import { Button, NoticeBox } from '@dhis2/ui' +import { getDataStoreElement } from "../../utils/functions"; +import { useGetSocioEconomicsFormFields, useSocioEconomicsSubmit } from "../../hooks/students"; +import useLoadProgramStages from "../../hooks/commons/useLoadProgramStages"; +import { + type UseFetchEnrollmentDatasResponse +} from "../../types/students"; +import Loading from "../appList/Loading"; +import useLoadDataStoreDatas from "../../hooks/commons/useLoadDataStoreDatas"; + + +import style from './index.module.css' +import { Form } from "react-final-form" +import { type SubmitEnrollmentValue } from "../../types/students"; +import { GroupForm } from ".."; + +interface ZizardProgramProps { + setWizardSetp: React.Dispatch> +} + +export default function WizardSocioEconomics({ setWizardSetp }: ZizardProgramProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState() + const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() + const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() + const { getFormFields } = useGetSocioEconomicsFormFields() + const { submit, loadingProcessing } = useSocioEconomicsSubmit() + + useEffect(() => { + if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "student" }) + const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "socio-economics", key: "student" })?.programStage?.filter + + if (programId === undefined) { + setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") + } + if (programId !== null && programId !== undefined) { + void getProgramStages(programId, studentProgramFilterConfig) + } + } + }, [data]) + + return ( + <> + + { + (error !== undefined && error !== null) && ( + + {error.message} + + ) + } + +
+ {(data !== undefined && data !== null) && ( +
+
{ await submit({ programStage: values?.programStage }, data?.dataStoreValues, data?.dataStoreConfigs, () => { setWizardSetp(3) }) }} + render={ + ({ handleSubmit }: { handleSubmit: any }) => { + return programStagesDatas?.programStages?.length > 0 && ( + + +
+
+
+
+ + ) + } + } + /> +
+ )} +
+ + ); +} diff --git a/src/components/students/WizardTransfer.tsx b/src/components/students/WizardTransfer.tsx new file mode 100644 index 0000000..b8b1935 --- /dev/null +++ b/src/components/students/WizardTransfer.tsx @@ -0,0 +1,87 @@ +import React, { useState, useEffect } from "react"; +import { Button, NoticeBox } from '@dhis2/ui' +import { getDataStoreElement } from "../../utils/functions"; +import { useGetSocioEconomicsFormFields, useSocioEconomicsSubmit } from "../../hooks/students"; +import useLoadProgramStages from "../../hooks/commons/useLoadProgramStages"; +import { + type UseFetchEnrollmentDatasResponse +} from "../../types/students"; +import Loading from "../appList/Loading"; +import useLoadDataStoreDatas from "../../hooks/commons/useLoadDataStoreDatas"; + + +import style from './index.module.css' +import { Form } from "react-final-form" +import { type SubmitEnrollmentValue } from "../../types/students"; +import { GroupForm } from ".."; + +interface ZizardProgramProps { + setWizardSetp: React.Dispatch> +} + +export default function WizardTransfer({ setWizardSetp }: ZizardProgramProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState() + const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() + const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() + const { getFormFields } = useGetSocioEconomicsFormFields() + const { submit, loadingProcessing } = useSocioEconomicsSubmit() + + useEffect(() => { + if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "student" }) + const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "socio-economics", key: "student" })?.programStage?.filter + + if (programId === undefined) { + setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") + } + if (programId !== null && programId !== undefined) { + void getProgramStages(programId, studentProgramFilterConfig) + } + } + }, [data]) + + + return ( + <> + { + console.log(programStagesDatas) + } + + { + (error !== undefined && error !== null) && ( + + {error.message} + + ) + } + +
+ {(data !== undefined && data !== null) && ( +
+
{ await submit({ programStage: values?.programStage }, data?.dataStoreValues, data?.dataStoreConfigs, () => { setWizardSetp(3) }) }} + render={ + ({ handleSubmit }: { handleSubmit: any }) => { + return programStagesDatas?.programStages?.length > 0 && ( + + +
+
+
+
+ + ) + } + } + /> +
+ )} +
+ + ); +} diff --git a/src/components/students/index.module.css b/src/components/students/index.module.css new file mode 100644 index 0000000..8c9640f --- /dev/null +++ b/src/components/students/index.module.css @@ -0,0 +1,25 @@ +.formContent { + padding: 20px; + border-radius: 10px; + background-color: #fff; + margin-top: 10px; + border: 1px solid #f0f0f0; + box-shadow: 1px 2px #00000030; +} + + +.btnContainer { + margin-top: 20px; + padding: 0px 10px; + display: flex; +} + +.btnCancel { + margin-left: 20px; +} + +.loadingContainer { + display: flex; + align-items: center; + margin: 10px 0px; +} \ No newline at end of file diff --git a/src/components/students/index.ts b/src/components/students/index.ts index 0d6bdea..3c2b309 100644 --- a/src/components/students/index.ts +++ b/src/components/students/index.ts @@ -1,4 +1,5 @@ import EnrollmentForm from "./EnrollmentForm" import ProgramForm from "./ProgramForm" +import WizardForm from "./WizardForm"; -export { ProgramForm, EnrollmentForm } +export { ProgramForm, EnrollmentForm, WizardForm }; diff --git a/src/hooks/students/useAttendanceSubmit.ts b/src/hooks/students/useAttendanceSubmit.ts index fe23eb0..2be8935 100644 --- a/src/hooks/students/useAttendanceSubmit.ts +++ b/src/hooks/students/useAttendanceSubmit.ts @@ -10,6 +10,7 @@ interface SubmitFuctionProps { values: SubmitAttendanceValue dataStoreValues: any[] dataStoreConfigs: any[] + goToNext?: () => void } export default function useAttendanceSubmit() { @@ -17,7 +18,7 @@ export default function useAttendanceSubmit() { const { mutate } = useUpdateConfigValues() const { show, hide } = useShowAlerts() - const submit = async ({ dataStoreConfigs, dataStoreValues, values }: SubmitFuctionProps) => { + const submit = async ({ dataStoreConfigs, dataStoreValues, values, goToNext }: SubmitFuctionProps) => { try { setLoadingProcessing(true) let payload: any[] = [] @@ -35,7 +36,7 @@ export default function useAttendanceSubmit() { } const foundElement: any = dataStoreValues?.find((dt: any) => dt.key === "student") - const attendance = getDataStoreElement({ dataStores: dataStoreConfigs, key: "student", elementKey: "attendance" }) + // const attendance = getDataStoreElement({ dataStores: dataStoreConfigs, key: "student", elementKey: "attendance" }) const statusValues = [ { @@ -99,6 +100,9 @@ export default function useAttendanceSubmit() { } await mutate({ data: payload }) + if (goToNext !== undefined) { + goToNext() + } setLoadingProcessing(false) show({ message: `Operation success !`, diff --git a/src/hooks/students/useEnrollmentSubmit.ts b/src/hooks/students/useEnrollmentSubmit.ts index bd1f063..c9da526 100644 --- a/src/hooks/students/useEnrollmentSubmit.ts +++ b/src/hooks/students/useEnrollmentSubmit.ts @@ -11,7 +11,7 @@ export default function useEnrollmentSubmit() { const { mutate } = useUpdateConfigValues() const { show, hide } = useShowAlerts() - const submit = async (values: SubmitEnrollmentValue, dataStoreValues: any[], dataStoreConfigs: any[]) => { + const submit = async (values: SubmitEnrollmentValue, dataStoreValues: any[], dataStoreConfigs: any[], goToNext: any) => { try { setLoadingProcessing(true) let payload: any[] = [] @@ -77,6 +77,9 @@ export default function useEnrollmentSubmit() { } await mutate({ data: payload }) + if (goToNext !== undefined) { + goToNext() + } setLoadingProcessing(false) show({ message: `Operation success !`, diff --git a/src/hooks/students/useGetProgramFormField.ts b/src/hooks/students/useGetProgramFormField.ts index 0b8ac79..5accffa 100644 --- a/src/hooks/students/useGetProgramFormField.ts +++ b/src/hooks/students/useGetProgramFormField.ts @@ -2,7 +2,7 @@ import { type ProgramFormFieldProps } from "../../types/moduleConfigurations" import { type CustomAttributeProps } from "../../types/table/AttributeColumns" export default function useGetProgramFormField() { - const getFormFields = ({ data, programs }: ProgramFormFieldProps) => { + const getFormFields = ({ data, programs}: ProgramFormFieldProps) => { const foundProgram: any = data.dataStoreConfigs?.find((dt: any) => dt.key === "student")?.program?.program if (foundProgram !== undefined) { const list: CustomAttributeProps[] = [ @@ -25,6 +25,7 @@ export default function useGetProgramFormField() { } } ] + return list } else { return [] diff --git a/src/hooks/students/useSocioEconomicsSubmit.ts b/src/hooks/students/useSocioEconomicsSubmit.ts index 976eb23..83c8dc5 100644 --- a/src/hooks/students/useSocioEconomicsSubmit.ts +++ b/src/hooks/students/useSocioEconomicsSubmit.ts @@ -10,7 +10,7 @@ export default function useSocioEconomicsSubmit() { const { mutate } = useUpdateConfigValues() const { show, hide } = useShowAlerts() - const submit = async (values: { programStage: string }, dataStoreValues: any[], dataStoreConfigs: any[]) => { + const submit = async (values: { programStage: string }, dataStoreValues: any[], dataStoreConfigs: any[], goToNext: any) => { try { console.log("values: ", values) setLoadingProcessing(true) @@ -53,6 +53,9 @@ export default function useSocioEconomicsSubmit() { } await mutate({ data: payload }) + if (goToNext !== undefined) { + goToNext() + } setLoadingProcessing(false) show({ message: `Operation success !`, diff --git a/src/hooks/students/useSubmitProgramDatas.ts b/src/hooks/students/useSubmitProgramDatas.ts index 0e6b0b1..fc74bbd 100644 --- a/src/hooks/students/useSubmitProgramDatas.ts +++ b/src/hooks/students/useSubmitProgramDatas.ts @@ -10,9 +10,9 @@ export default function useSubmitProgramDatas() { const { show, hide } = useShowAlerts() const { mutate } = useUpdateProgramDataStoreMutation() - const submit = async ({ data, program }: ProgramSubmitValueProps) => { + const submit = async ({ data, program, goToNext }: ProgramSubmitValueProps) => { try { - if (program !== undefined) { + if (program?.length > 0) { setLoadingProcessing(true) let payload: any[] = [] @@ -44,6 +44,9 @@ export default function useSubmitProgramDatas() { } await mutate({ data: payload }) + if (goToNext !== undefined) { + goToNext() + } setLoadingProcessing(false) show({ message: 'Operation Successfull !', diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 86087fc..0018a9f 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,5 +1,26 @@ -import { StudentsAttendance, StudentsEnrollment, StudentsPerformance, StudentsProgram, StudentsSocioEconomics } from "./students" -import { StaffAttendance, StaffEnrollment, StaffProgram } from "./staff" -import { AppsInstallation, AppsConfiguration } from "./appsOverview" +import { + StudentsAttendance, + StudentsEnrollment, + StudentsPerformance, + StudentsProgram, + StudentsSocioEconomics, + StudentWizard +} from "./students"; + +import { StaffAttendance, StaffEnrollment, StaffProgram } from "./staff"; +import { AppsInstallation, AppsConfiguration } from "./appsOverview"; import GenericForm from "./form/Form"; -export {StudentsAttendance, StudentsEnrollment, StudentsPerformance, StudentsProgram, StudentsSocioEconomics, StaffAttendance, StaffEnrollment, StaffProgram, AppsInstallation, AppsConfiguration, GenericForm} +export { + StudentWizard, + StudentsAttendance, + StudentsEnrollment, + StudentsPerformance, + StudentsProgram, + StudentsSocioEconomics, + StaffAttendance, + StaffEnrollment, + StaffProgram, + AppsInstallation, + AppsConfiguration, + GenericForm +}; diff --git a/src/pages/students/Student_Wizard.tsx b/src/pages/students/Student_Wizard.tsx new file mode 100644 index 0000000..e830536 --- /dev/null +++ b/src/pages/students/Student_Wizard.tsx @@ -0,0 +1,12 @@ +import React from "react"; +import { Title, WithPadding } from "../../components"; +import { WizardForm } from "../../components/students"; + +export default function StudentWizard() { + return ( + + + <WizardForm /> + </WithPadding> + ); +} diff --git a/src/pages/students/index.ts b/src/pages/students/index.ts index 7f5f105..bea037c 100644 --- a/src/pages/students/index.ts +++ b/src/pages/students/index.ts @@ -3,4 +3,12 @@ import StudentsEnrollment from "./Student_EnrollmentConfig"; import StudentsProgram from "./Student_ProgramConfig"; import StudentsPerformance from "./Student_PerformanceConfig"; import StudentsSocioEconomics from "./Student_SocioEconomicsConfig"; -export {StudentsEnrollment, StudentsProgram, StudentsPerformance, StudentsAttendance, StudentsSocioEconomics} +import StudentWizard from "./Student_Wizard"; +export { + StudentsEnrollment, + StudentsProgram, + StudentsPerformance, + StudentsAttendance, + StudentsSocioEconomics, + StudentWizard +}; diff --git a/src/types/moduleConfigurations/index.ts b/src/types/moduleConfigurations/index.ts index c6e88c6..fe92541 100644 --- a/src/types/moduleConfigurations/index.ts +++ b/src/types/moduleConfigurations/index.ts @@ -45,6 +45,7 @@ interface ProgramSubmitValueProps { data: { dataStoreValues: any[] } + goToNext?: () => void } interface ProgramFormFieldProps { diff --git a/src/types/students/index.ts b/src/types/students/index.ts index 8d2ceee..1ea9f3e 100644 --- a/src/types/students/index.ts +++ b/src/types/students/index.ts @@ -35,6 +35,7 @@ interface SubmitAttendanceValue { presentCode: string lateCode: string leaveCode: string + goToNext?: () => void } interface SubmitFinalResultValue { diff --git a/src/utils/constants/sideBar/sideBarData.ts b/src/utils/constants/sideBar/sideBarData.ts index 1f0d205..4e81d92 100644 --- a/src/utils/constants/sideBar/sideBarData.ts +++ b/src/utils/constants/sideBar/sideBarData.ts @@ -30,6 +30,12 @@ function sideBarData(): SideBarItemProps[] { { title: "Students", subItems: [ + { + icon: settings, + label: "Wizard", + showBadge: false, + route: "/students/wizard" + }, { icon: settings, label: "Program", @@ -65,7 +71,7 @@ function sideBarData(): SideBarItemProps[] { label: "Final result", showBadge: false, route: "/students/final-result" - }, + }, { icon: transfer, label: "Transfer", diff --git a/yarn.lock b/yarn.lock index d7db014..0b188be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2145,6 +2145,18 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== +"@emotion/is-prop-valid@^0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.7.3.tgz#a6bf4fa5387cbba59d44e698a4680f481a8da6cc" + integrity sha512-uxJqm/sqwXw3YPA5GXX365OBcJGFtxUVkB6WyezqFHlNe9jqUWH5ur2O2M8dGBz61kn1g3ZBlzUunFQXQIClhA== + dependencies: + "@emotion/memoize" "0.7.1" + +"@emotion/memoize@0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.1.tgz#e93c13942592cf5ef01aa8297444dc192beee52f" + integrity sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg== + "@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -4628,7 +4640,7 @@ cloneable-readable@^1.0.0: process-nextick-args "^2.0.0" readable-stream "^2.3.5" -clsx@^1.0.2, clsx@^1.0.4: +clsx@^1.0.2, clsx@^1.0.4, clsx@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== @@ -4652,7 +4664,7 @@ collect-v8-coverage@^1.0.0: resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== -color-convert@^1.9.0: +color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== @@ -4671,11 +4683,27 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== -color-name@~1.1.4: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-string@^1.6.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" + integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== + dependencies: + color-convert "^1.9.3" + color-string "^1.6.0" + colord@^2.9.1: version "2.9.3" resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" @@ -4955,6 +4983,15 @@ css-has-pseudo@^3.0.4: dependencies: postcss-selector-parser "^6.0.9" +css-jss@10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/css-jss/-/css-jss-10.10.0.tgz#bd51fbd255cc24597ac0f0f32368394794d37ef3" + integrity sha512-YyMIS/LsSKEGXEaVJdjonWe18p4vXLo8CMA4FrW/kcaEyqdIGKCFXao31gbJddXEdIxSXFFURWrenBJPlKTgAA== + dependencies: + "@babel/runtime" "^7.3.1" + jss "^10.10.0" + jss-preset-default "^10.10.0" + css-loader@^6.5.1, css-loader@^6.7.1: version "6.8.1" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.8.1.tgz#0f8f52699f60f5e679eab4ec0fcd68b8e8a50a88" @@ -6872,7 +6909,7 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.2.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -7262,6 +7299,11 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -8289,7 +8331,7 @@ jsprim@^1.2.2: json-schema "0.4.0" verror "1.10.0" -jss-plugin-camel-case@^10.5.1: +jss-plugin-camel-case@10.10.0, jss-plugin-camel-case@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.10.0.tgz#27ea159bab67eb4837fa0260204eb7925d4daa1c" integrity sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw== @@ -8298,7 +8340,16 @@ jss-plugin-camel-case@^10.5.1: hyphenate-style-name "^1.0.3" jss "10.10.0" -jss-plugin-default-unit@^10.5.1: +jss-plugin-compose@10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-compose/-/jss-plugin-compose-10.10.0.tgz#00d7a79adf7fcfe4927a792febdf0deceb0a7cd2" + integrity sha512-F5kgtWpI2XfZ3Z8eP78tZEYFdgTIbpA/TMuX3a8vwrNolYtN1N4qJR/Ob0LAsqIwCMLojtxN7c7Oo/+Vz6THow== + dependencies: + "@babel/runtime" "^7.3.1" + jss "10.10.0" + tiny-warning "^1.0.2" + +jss-plugin-default-unit@10.10.0, jss-plugin-default-unit@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.10.0.tgz#db3925cf6a07f8e1dd459549d9c8aadff9804293" integrity sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ== @@ -8306,7 +8357,24 @@ jss-plugin-default-unit@^10.5.1: "@babel/runtime" "^7.3.1" jss "10.10.0" -jss-plugin-global@^10.5.1: +jss-plugin-expand@10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-expand/-/jss-plugin-expand-10.10.0.tgz#5debd80554174ca2d9b9e38d85d4cb6f3e0393ab" + integrity sha512-ymT62W2OyDxBxr7A6JR87vVX9vTq2ep5jZLIdUSusfBIEENLdkkc0lL/Xaq8W9s3opUq7R0sZQpzRWELrfVYzA== + dependencies: + "@babel/runtime" "^7.3.1" + jss "10.10.0" + +jss-plugin-extend@10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-extend/-/jss-plugin-extend-10.10.0.tgz#94eb450847a8941777e77ea4533a579c1c578430" + integrity sha512-sKYrcMfr4xxigmIwqTjxNcHwXJIfvhvjTNxF+Tbc1NmNdyspGW47Ey6sGH8BcQ4FFQhLXctpWCQSpDwdNmXSwg== + dependencies: + "@babel/runtime" "^7.3.1" + jss "10.10.0" + tiny-warning "^1.0.2" + +jss-plugin-global@10.10.0, jss-plugin-global@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.10.0.tgz#1c55d3c35821fab67a538a38918292fc9c567efd" integrity sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A== @@ -8314,7 +8382,7 @@ jss-plugin-global@^10.5.1: "@babel/runtime" "^7.3.1" jss "10.10.0" -jss-plugin-nested@^10.5.1: +jss-plugin-nested@10.10.0, jss-plugin-nested@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.10.0.tgz#db872ed8925688806e77f1fc87f6e62264513219" integrity sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA== @@ -8323,7 +8391,7 @@ jss-plugin-nested@^10.5.1: jss "10.10.0" tiny-warning "^1.0.2" -jss-plugin-props-sort@^10.5.1: +jss-plugin-props-sort@10.10.0, jss-plugin-props-sort@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.10.0.tgz#67f4dd4c70830c126f4ec49b4b37ccddb680a5d7" integrity sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg== @@ -8331,7 +8399,7 @@ jss-plugin-props-sort@^10.5.1: "@babel/runtime" "^7.3.1" jss "10.10.0" -jss-plugin-rule-value-function@^10.5.1: +jss-plugin-rule-value-function@10.10.0, jss-plugin-rule-value-function@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.10.0.tgz#7d99e3229e78a3712f78ba50ab342e881d26a24b" integrity sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g== @@ -8340,7 +8408,25 @@ jss-plugin-rule-value-function@^10.5.1: jss "10.10.0" tiny-warning "^1.0.2" -jss-plugin-vendor-prefixer@^10.5.1: +jss-plugin-rule-value-observable@10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-observable/-/jss-plugin-rule-value-observable-10.10.0.tgz#d17b28c4401156bbe4cd0c4a73a80aad70613e8b" + integrity sha512-ZLMaYrR3QE+vD7nl3oNXuj79VZl9Kp8/u6A1IbTPDcuOu8b56cFdWRZNZ0vNr8jHewooEeq2doy8Oxtymr2ZPA== + dependencies: + "@babel/runtime" "^7.3.1" + jss "10.10.0" + symbol-observable "^1.2.0" + +jss-plugin-template@10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-plugin-template/-/jss-plugin-template-10.10.0.tgz#072cda74a94c91b02d3a895d9e2408fd978ce033" + integrity sha512-ocXZBIOJOA+jISPdsgkTs8wwpK6UbsvtZK5JI7VUggTD6LWKbtoxUzadd2TpfF+lEtlhUmMsCkTRNkITdPKa6w== + dependencies: + "@babel/runtime" "^7.3.1" + jss "10.10.0" + tiny-warning "^1.0.2" + +jss-plugin-vendor-prefixer@10.10.0, jss-plugin-vendor-prefixer@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.10.0.tgz#c01428ef5a89f2b128ec0af87a314d0c767931c7" integrity sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg== @@ -8349,7 +8435,27 @@ jss-plugin-vendor-prefixer@^10.5.1: css-vendor "^2.0.8" jss "10.10.0" -jss@10.10.0, jss@^10.5.1: +jss-preset-default@10.10.0, jss-preset-default@^10.10.0: + version "10.10.0" + resolved "https://registry.yarnpkg.com/jss-preset-default/-/jss-preset-default-10.10.0.tgz#c8209449a0f6d232526c2ba3a3a6ec69ee97e023" + integrity sha512-GL175Wt2FGhjE+f+Y3aWh+JioL06/QWFgZp53CbNNq6ZkVU0TDplD8Bxm9KnkotAYn3FlplNqoW5CjyLXcoJ7Q== + dependencies: + "@babel/runtime" "^7.3.1" + jss "10.10.0" + jss-plugin-camel-case "10.10.0" + jss-plugin-compose "10.10.0" + jss-plugin-default-unit "10.10.0" + jss-plugin-expand "10.10.0" + jss-plugin-extend "10.10.0" + jss-plugin-global "10.10.0" + jss-plugin-nested "10.10.0" + jss-plugin-props-sort "10.10.0" + jss-plugin-rule-value-function "10.10.0" + jss-plugin-rule-value-observable "10.10.0" + jss-plugin-template "10.10.0" + jss-plugin-vendor-prefixer "10.10.0" + +jss@10.10.0, jss@^10.10.0, jss@^10.5.1: version "10.10.0" resolved "https://registry.yarnpkg.com/jss/-/jss-10.10.0.tgz#a75cc85b0108c7ac8c7b7d296c520a3e4fbc6ccc" integrity sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw== @@ -10002,7 +10108,7 @@ prop-types-extra@^1.1.0: react-is "^16.3.2" warning "^4.0.0" -prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -10197,6 +10303,11 @@ react-dev-utils@^12.0.0, react-dev-utils@^12.0.1: strip-ansi "^6.0.1" text-table "^0.2.0" +react-display-name@^0.2.4: + version "0.2.5" + resolved "https://registry.yarnpkg.com/react-display-name/-/react-display-name-0.2.5.tgz#304c7cbfb59ee40389d436e1a822c17fe27936c6" + integrity sha512-I+vcaK9t4+kypiSgaiVWAipqHRXYmZIuAiS8vzFvXHHXVigg/sMKwlRgLy6LH2i3rmP+0Vzfl5lFsFRwF1r3pg== + react-dnd-html5-backend@14.0.1: version "14.0.1" resolved "https://registry.yarnpkg.com/react-dnd-html5-backend/-/react-dnd-html5-backend-14.0.1.tgz#37d43d6b6ddd91069101969d9eac6d688a9d57ef" @@ -10242,6 +10353,15 @@ react-final-form@^6.5.3, react-final-form@^6.5.9: dependencies: "@babel/runtime" "^7.15.4" +react-form-stepper@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/react-form-stepper/-/react-form-stepper-2.0.3.tgz#5b424fe6bf9fd1e43bfe80a2f11bc16f59c75a31" + integrity sha512-j6UAQAX4iMR8uMkFSvApWkOpMRhJzVahKwGOMDL4TwZF7POPxxDslBlITZBj9QEc9d/HFkMK4+ql06o2O4DS5Q== + dependencies: + clsx "^1.1.1" + color "^3.2.1" + react-jss "^10.9.1-alpha.2" + react-icons@^4.12.0: version "4.12.0" resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.12.0.tgz#54806159a966961bfd5cdb26e492f4dafd6a8d78" @@ -10269,6 +10389,23 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +react-jss@^10.9.1-alpha.2: + version "10.10.0" + resolved "https://registry.yarnpkg.com/react-jss/-/react-jss-10.10.0.tgz#d08ab3257b0eed01e15d6d8275840055c279b0da" + integrity sha512-WLiq84UYWqNBF6579/uprcIUnM1TSywYq6AIjKTTTG5ziJl9Uy+pwuvpN3apuyVwflMbD60PraeTKT7uWH9XEQ== + dependencies: + "@babel/runtime" "^7.3.1" + "@emotion/is-prop-valid" "^0.7.3" + css-jss "10.10.0" + hoist-non-react-statics "^3.2.0" + is-in-browser "^1.1.3" + jss "10.10.0" + jss-preset-default "10.10.0" + prop-types "^15.6.0" + shallow-equal "^1.2.0" + theming "^3.3.0" + tiny-warning "^1.0.2" + react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" @@ -10972,6 +11109,11 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" +shallow-equal@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da" + integrity sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA== + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -11015,6 +11157,13 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== + dependencies: + is-arrayish "^0.3.1" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -11500,6 +11649,11 @@ svgo@^2.7.0: picocolors "^1.0.0" stable "^0.1.8" +symbol-observable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== + symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -11641,6 +11795,16 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +theming@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/theming/-/theming-3.3.0.tgz#dacabf04aa689edde35f1e1c117ec6de73fbf870" + integrity sha512-u6l4qTJRDaWZsqa8JugaNt7Xd8PPl9+gonZaIe28vAhqgHMIG/DOyFPqiKN/gQLQYj05tHv+YQdNILL4zoiAVA== + dependencies: + hoist-non-react-statics "^3.3.0" + prop-types "^15.5.8" + react-display-name "^0.2.4" + tiny-warning "^1.0.2" + thenify-all@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" From 424a28e876ecdd5618605c3dd3abc3a296be4bb7 Mon Sep 17 00:00:00 2001 From: Ibrahim <ikomna@hispwca.org> Date: Wed, 14 Aug 2024 18:22:10 +0000 Subject: [PATCH 2/4] update on wizard student page --- .eslintrc.json | 9 +- .prettierrc.json | 8 + .../genericFields/fields/SingleSelect.tsx | 138 ++++--- src/components/routes/RouteList.tsx | 40 +- src/components/staffs/WizardAttendance.tsx | 263 +++++++++++++ src/components/staffs/WizardEnrollment.tsx | 198 ++++++++++ src/components/staffs/WizardForm.tsx | 73 ++++ src/components/staffs/WizardProgram.tsx | 104 ++++++ src/components/staffs/WizardTransfer.tsx | 161 ++++++++ src/components/staffs/index.module.css | 60 +++ src/components/staffs/index.ts | 3 +- src/components/students/TransferForm.tsx | 2 - src/components/students/WizardAttendance.tsx | 353 +++++++++++++----- src/components/students/WizardConfigDone.tsx | 14 + src/components/students/WizardEnrollment.tsx | 285 +++++++++----- src/components/students/WizardFinalResult.tsx | 203 ++++++---- src/components/students/WizardForm.tsx | 48 ++- src/components/students/WizardPerformance.tsx | 204 ++++++---- src/components/students/WizardProgram.tsx | 156 +++++--- .../students/WizardSocioEconomics.tsx | 206 ++++++---- src/components/students/WizardTransfer.tsx | 226 +++++++---- src/components/students/index.module.css | 53 ++- src/hooks/commons/useLoadDataElements.ts | 2 +- src/hooks/staffs/useEnrollmentSubmit.ts | 5 +- src/hooks/staffs/useSubmitProgramDatas.ts | 5 +- src/hooks/students/useAttendanceSubmit.ts | 4 +- src/hooks/students/useFinalResultSubmit.ts | 10 +- .../students/useGetAttendanceFormFields.ts | 2 +- .../students/useGetFinalResultFormFields.ts | 2 +- src/hooks/students/useGetTransferField.ts | 15 +- src/hooks/students/usePerformanceSubmit.ts | 7 +- src/hooks/students/useTransferSubmit.ts | 5 +- src/pages/staff/Staff_Wizard.tsx | 12 + src/pages/staff/index.ts | 3 +- src/types/table/AttributeColumns.ts | 1 + src/utils/constants/sideBar/sideBarData.ts | 6 + 36 files changed, 2196 insertions(+), 690 deletions(-) create mode 100644 .prettierrc.json create mode 100644 src/components/staffs/WizardAttendance.tsx create mode 100644 src/components/staffs/WizardEnrollment.tsx create mode 100644 src/components/staffs/WizardForm.tsx create mode 100644 src/components/staffs/WizardProgram.tsx create mode 100644 src/components/staffs/WizardTransfer.tsx create mode 100644 src/components/staffs/index.module.css create mode 100644 src/components/students/WizardConfigDone.tsx create mode 100644 src/pages/staff/Staff_Wizard.tsx diff --git a/.eslintrc.json b/.eslintrc.json index a927a39..d6698b4 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -24,6 +24,13 @@ "@typescript-eslint/explicit-function-return-type": "off", "@typescript-eslint/space-before-function-paren": "off", "@typescript-eslint/object-curly-spacing": "off", - "@typescript-eslint/semi": "off" + "@typescript-eslint/semi": "off", + "@typescript-eslint/strict-boolean-expressions":"off", + "@typescript-eslint/comma-dangle": "off", + "@typescript-eslint/restrict-template-expressions":"off", + "@typescript-eslint/no-floating-promises":"off", + "@typescript-eslint/no-confusing-void-expression":"off", + "@typescript-eslint/no-misused-promises":"off", + "@typescript-eslint/prefer-nullish-coalescing":"off" } } diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..5c873d4 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,8 @@ +{ + "tabWidth": 4, + "bracketSpacing": true, + "semi": false, + "singleQuote": true, + "trailingComma": "none", + "printWidth": 120 +} \ No newline at end of file diff --git a/src/components/genericFields/fields/SingleSelect.tsx b/src/components/genericFields/fields/SingleSelect.tsx index 6111fc4..acbab94 100644 --- a/src/components/genericFields/fields/SingleSelect.tsx +++ b/src/components/genericFields/fields/SingleSelect.tsx @@ -1,71 +1,91 @@ -import { TextField } from "@material-ui/core"; -import { Autocomplete } from "@material-ui/lab"; -import React from "react"; -import { useField, type FieldRenderProps } from "react-final-form"; -import { type CustomAttributeProps } from "../../../types/table/AttributeColumns"; +import { TextField } from '@material-ui/core' +import { Autocomplete } from '@material-ui/lab' +import React from 'react' +import { useField, type FieldRenderProps } from 'react-final-form' +import { type CustomAttributeProps } from '../../../types/table/AttributeColumns' interface AutoCompleteProps { - disabled?: boolean - options?: CustomAttributeProps["options"] - name: string - label?: string - multiple?: boolean - onChange?: any + disabled?: boolean + options?: CustomAttributeProps['options'] + name: string + label?: string + defaultValue?: any + multiple?: boolean + onChange?: any } const OptionSetAutocomplete = (props: AutoCompleteProps) => { - const { input, meta }: FieldRenderProps<any, HTMLElement> = useField(props.name); + const { input, meta }: FieldRenderProps<any, HTMLElement> = useField(props.name) - const options = (props?.options?.optionSet?.options != null) - ? props?.options.optionSet?.options.map((option: { value: string, label: string }) => ({ - value: option?.value, - label: option?.label - })) - : []; + const options = + props?.options?.optionSet?.options != null + ? props?.options.optionSet?.options.map((option: { value: string; label: string }) => ({ + value: option?.value, + label: option?.label + })) + : [] - return ( - <Autocomplete - {...props} - multiple={props.multiple !== undefined ? props.multiple : false} - options={options} - closeIcon={null} - disabled={props.disabled} - getOptionLabel={(option: any) => option.label} - value={ - props.multiple !== undefined && Boolean(props.multiple) - ? input.value?.length > 0 ? input.value.map((val: any) => options.find((element: { value: string }) => element.value === val)) : [] - : options.find((element: { value: string }) => element.value === input.value) - } - renderInput={(params: any) => ( - <TextField - {...params} - variant="outlined" - error={(meta.touched === true) && meta.error} - helperText={(meta.touched === true) && meta.error} - size="small" - label={props.label !== undefined ? props.label : ''} - InputProps={{ - ...params.InputProps, - style: { - backgroundColor: "#fff" - } + if (props?.defaultValue) { + input.onChange(props.defaultValue) + } + + return ( + <Autocomplete + {...props} + multiple={props.multiple !== undefined ? props.multiple : false} + options={options} + closeIcon={null} + disabled={props.disabled} + getOptionLabel={(option: any) => option.label} + value={ + props.multiple !== undefined && Boolean(props.multiple) + ? input.value?.length > 0 + ? input.value.map((val: any) => + options.find((element: { value: string }) => element.value === val) + ) + : props?.defaultValue?.map((val: any) => + options.find((element: { value: string }) => element.value === val) + ) || [] + : options.find((element: { value: string }) => element.value === input.value) || + options.find((element: { value: string }) => element.value === props?.defaultValue) + } + renderInput={(params: any) => ( + <TextField + {...params} + variant="outlined" + error={meta.touched === true && meta.error} + helperText={meta.touched === true && meta.error} + size="small" + label={props.label !== undefined ? props.label : ''} + InputProps={{ + ...params.InputProps, + style: { + backgroundColor: '#fff' + } + }} + /> + )} + onChange={(_, value: any) => { + console.log('onchange value: ', value) + input.onChange( + props.multiple !== undefined && props.multiple !== null && Boolean(props.multiple) + ? value?.length > 0 + ? value.map((v: { value: string }) => v.value) + : [] + : value?.value + ) + Boolean(props.onChange) && props.onChange(value) }} - /> - )} - onChange={(_, value: any) => { - input.onChange(props.multiple !== undefined && props.multiple !== null && Boolean(props.multiple) ? value?.length > 0 ? value.map((v: { value: string }) => v.value) : [] : value?.value); - (Boolean(props.onChange)) && props.onChange(value) - }} - /> - ); -}; + /> + ) +} function SingleSelectField(props: AutoCompleteProps) { - return ( - <div> - <OptionSetAutocomplete {...props} name={props.name} /> - </div> - ); + return ( + <div> + <OptionSetAutocomplete {...props} name={props.name} /> + </div> + ) } -export default SingleSelectField; +export default SingleSelectField diff --git a/src/components/routes/RouteList.tsx b/src/components/routes/RouteList.tsx index 66deb62..02e4389 100644 --- a/src/components/routes/RouteList.tsx +++ b/src/components/routes/RouteList.tsx @@ -6,91 +6,97 @@ import StudentsFinalResults from "../../pages/students/Student_FinalResultConfig import StudentsTransfer from "../../pages/students/Student_TransferConfig"; import StaffTransfer from "../../pages/staff/Staff_TransferConfig"; import DefaultSettings from "../../pages/appsOverview/DefaultSettings"; +import { StaffWizard } from "../../pages/staff"; export default function RouteList() { return [ { - path: "/", + path: '/', layout: SimpleLayout, component: () => <Navigate to="/students/program" replace /> }, { - path: "/students/wizard", + path: '/students/wizard', layout: SideBarLayout, component: () => <StudentWizard /> }, { - path: "/students/program", + path: '/students/program', layout: SideBarLayout, component: () => <StudentsProgram /> }, { - path: "/students/enrollment", + path: '/students/enrollment', layout: SideBarLayout, component: () => <StudentsEnrollment /> }, { - path: "/students/socio-economics", + path: '/students/socio-economics', layout: SideBarLayout, component: () => <StudentsSocioEconomics /> }, { - path: "/students/attendance", + path: '/students/attendance', layout: SideBarLayout, component: () => <StudentsAttendance /> }, { - path: "/students/performance", + path: '/students/performance', layout: SideBarLayout, component: () => <StudentsPerformance /> }, { - path: "/students/final-result", + path: '/students/final-result', layout: SideBarLayout, component: () => <StudentsFinalResults /> }, { - path: "/students/transfer", + path: '/students/transfer', layout: SideBarLayout, component: () => <StudentsTransfer /> }, { - path: "/apps/default-settings", + path: '/apps/default-settings', layout: SideBarLayout, component: () => <DefaultSettings /> }, { - path: "/staffs/program", + path: '/staffs/wizard', + layout: SideBarLayout, + component: () => <StaffWizard /> + }, + { + path: '/staffs/program', layout: SideBarLayout, component: () => <StaffProgram /> }, { - path: "/staffs/enrollment", + path: '/staffs/enrollment', layout: SideBarLayout, component: () => <StaffEnrollment /> }, { - path: "/staffs/attendance", + path: '/staffs/attendance', layout: SideBarLayout, component: () => <StaffAttendance /> }, { - path: "/staffs/transfer", + path: '/staffs/transfer', layout: SideBarLayout, component: () => <StaffTransfer /> }, { - path: "/apps/installation", + path: '/apps/installation', layout: SideBarLayout, component: () => <AppsInstallation /> }, { - path: "/apps/configuration", + path: '/apps/configuration', layout: SideBarLayout, component: () => <AppsConfiguration /> }, { - path: "/form", + path: '/form', layout: SideBarLayout, component: GenericForm } diff --git a/src/components/staffs/WizardAttendance.tsx b/src/components/staffs/WizardAttendance.tsx new file mode 100644 index 0000000..cce1e45 --- /dev/null +++ b/src/components/staffs/WizardAttendance.tsx @@ -0,0 +1,263 @@ +import React, { useState, useEffect } from 'react' +import { NoticeBox, Button } from '@dhis2/ui' +import { getDataStoreElement } from '../../utils/functions' +import { useGetAttendanceFormFields } from '../../hooks/students' +import useLoadProgramStages from '../../hooks/commons/useLoadProgramStages' +import useLoadDataElements from '../../hooks/commons/useLoadDataElements' +import { + type SubmitAttendanceValue, + type LoadDataElementsResponse, + type UseFetchEnrollmentDatasResponse +} from '../../types/students' +import Loading from '../appList/Loading' +import useLoadDataStoreDatas from '../../hooks/commons/useLoadDataStoreDatas' +import useAttendanceSubmit from '../../hooks/students/useAttendanceSubmit' + +import style from './index.module.css' +import { Form } from 'react-final-form' +import { GroupForm } from '..' +import { IoIosArrowRoundForward } from 'react-icons/io' + +interface WizardPageProps { + setWizardSetp: React.Dispatch<React.SetStateAction<number>> +} + +export default function WizardAttendance({ setWizardSetp }: WizardPageProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() + const { getDataElements, dataElementsDatas }: LoadDataElementsResponse = useLoadDataElements() + const { getFormFields } = useGetAttendanceFormFields() + const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() + const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() + const { submit, loadingProcessing } = useAttendanceSubmit() + + useEffect(() => { + if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'program', + key: 'student' + }) + const programStageId = getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.programStage + const studentProgramFilterConfig = getDataStoreElement({ + dataStores: data?.dataStoreConfigs, + elementKey: 'attendance', + key: 'student' + })?.programStage?.filter + + if (programId === undefined) { + setNoProgramErrorMessage('No programs have been configured. Please configure it before continuing !') + } + if (programId !== null && programId !== undefined) { + void getProgramStages(programId, studentProgramFilterConfig) + } + if (programStageId !== null && programStageId !== undefined) { + getDataElements(programStageId) + } + } + }, [data]) + + return ( + <> + <Loading loadings={[loading, loadingProgramStages]} /> + {error !== undefined && error !== null && ( + <NoticeBox title="Configurations" warning> + {error.message} + </NoticeBox> + )} + {noProgramErrorMessage !== undefined && noProgramErrorMessage !== null && ( + <NoticeBox title="Configuration" warning> + {`${noProgramErrorMessage}`} + </NoticeBox> + )} + + <div className={style.formContent}> + {data && ( + <div> + <Form + onSubmit={async (values: SubmitAttendanceValue) => { + await submit({ + values, + dataStoreValues: data.dataStoreValues, + dataStoreConfigs: data.dataStoreConfigs, + goToNext: () => { + setWizardSetp(4) + } + }) + }} + render={({ handleSubmit }: any) => { + return ( + programStagesDatas?.programStages?.length > 0 && ( + <form onSubmit={handleSubmit}> + <GroupForm + disabled={false} + name="Attendance" + fields={getFormFields({ + dataStoreConfigs: data.dataStoreConfigs, + programStages: programStagesDatas.programStages, + getDataElements, + dataElements: + dataElementsDatas?.dataElements !== undefined && + dataElementsDatas?.dataElements !== null && + dataElementsDatas?.dataElements?.length > 0 + ? dataElementsDatas?.dataElements + : [] + }).map((p) => { + if (p.name === 'programStage') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.programStage + } + } + + if (p.name === 'absenceReason') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.absenceReason + } + } + + if (p.name === 'status') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.status + } + } + + if (p.name === 'absentCode') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'absent') + ?.code + } + } + + if (p.name === 'presentCode') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'present') + ?.code + } + } + + if (p.name === 'lateCode') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'late')?.code + } + } + + if (p.name === 'leaveCode') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'leave')?.code + } + } + + return p + })} + /> + <div className={style.flexBetween}> + <div className={style.flex}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> + </div> + <div className={style.btnCancel}> + <Button disabled type="button"> + Cancel + </Button> + </div> + </div> + {getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.programStage && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.absenceReason && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.status && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'absent')?.code && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'present')?.code && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'late')?.code && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'leave')?.code && ( + <div> + <Button + primary + onClick={() => { + setWizardSetp(4) + }} + > + <IoIosArrowRoundForward style={{ fontSize: '20px' }} /> + Next + </Button> + </div> + )} + </div> + </form> + ) + ) + }} + /> + </div> + )} + </div> + </> + ) +} diff --git a/src/components/staffs/WizardEnrollment.tsx b/src/components/staffs/WizardEnrollment.tsx new file mode 100644 index 0000000..ba3bb9b --- /dev/null +++ b/src/components/staffs/WizardEnrollment.tsx @@ -0,0 +1,198 @@ +import React, { useState, useEffect } from 'react' +import { NoticeBox, Button } from '@dhis2/ui' +import { getDataStoreElement } from '../../utils/functions' +import useLoadProgramStages from '../../hooks/commons/useLoadProgramStages' +import useLoadDataElements from '../../hooks/commons/useLoadDataElements' +import Loading from '../appList/Loading' +import useLoadDataStoreDatas from '../../hooks/commons/useLoadDataStoreDatas' +import { useEnrollmentSubmit, useGetEnrollmentField } from '../../hooks/staffs' + +import { Form } from 'react-final-form' +import GroupForm from '../form/GroupForm' +import { IoIosArrowRoundForward } from 'react-icons/io' + +import style from './index.module.css' + +interface WizardPageProps { + setWizardSetp: React.Dispatch<React.SetStateAction<number>> +} + +export default function WizardEnrollment({ setWizardSetp }: WizardPageProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() + const { getDataElements, dataElementsDatas } = useLoadDataElements() + const { getFormFields } = useGetEnrollmentField() + const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() + const { submit, loadingProcessing } = useEnrollmentSubmit() + const { data, loading, error } = useLoadDataStoreDatas() + + useEffect(() => { + if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'program', + key: 'staff' + }) + const programStageId = getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'registration', + key: 'staff' + })?.programStage + const staffProgramFilterConfig = getDataStoreElement({ + dataStores: data?.dataStoreConfigs, + elementKey: 'registration', + key: 'staff' + })?.programStage?.filter + + if (programId === undefined) { + setNoProgramErrorMessage('No programs have been configured. Please configure it before continuing !') + } + + if (programId !== null && programId !== undefined) { + getProgramStages(programId, staffProgramFilterConfig) + } + if (programStageId !== null && programStageId !== undefined) { + getDataElements(programStageId) + } + } + }, [data]) + return ( + <> + <Loading loadings={[loading, loadingProgramStages]} /> + {error !== undefined && error !== null && ( + <NoticeBox title="Configurations" warning> + {error.message} + </NoticeBox> + )} + {noProgramErrorMessage !== undefined && noProgramErrorMessage !== null && ( + <NoticeBox title="Configuration" warning> + {`${noProgramErrorMessage}`} + </NoticeBox> + )} + + <div className={style.formContent}> + {data !== undefined && data !== null && ( + <div> + <Form + onSubmit={async (value: any) => { + await submit(value, data.dataStoreValues, data.dataStoreConfigs, () => { + setWizardSetp(2) + }) + }} + component={({ handleSubmit, form }) => { + return ( + programStagesDatas?.programStages?.length > 0 && ( + <form onSubmit={handleSubmit}> + <GroupForm + disabled={false} + name="Staff Enrollment" + fields={getFormFields({ + dataStoreConfigs: data.dataStoreConfigs, + programStages: programStagesDatas?.programStages, + getDataElements, + dataElements: + dataElementsDatas?.dataElements !== undefined && + dataElementsDatas?.dataElements !== null + ? dataElementsDatas?.dataElements + : [] + }).map((p) => { + if (p.name === 'programStage') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'staff' + })?.programStage + } + } + if (p.name === 'grade') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'staff' + })?.grade + } + } + if (p.name === 'section') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'staff' + })?.section + } + } + if (p.name === 'academicYear') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'staff' + })?.academicYear + } + } + return p + })} + /> + <div className={style.flexBetween}> + <div className={style.flex}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> + </div> + <div className={style.btnCancel}> + <Button disabled type="button"> + Cancel + </Button> + </div> + </div> + {getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'staff' + })?.programStage && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'staff' + })?.grade && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'staff' + })?.section && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'staff' + })?.academicYear && ( + <div> + <Button + primary + onClick={() => { + setWizardSetp(2) + }} + > + <IoIosArrowRoundForward style={{ fontSize: '20px' }} /> + Next + </Button> + </div> + )} + </div> + </form> + ) + ) + }} + /> + </div> + )} + </div> + </> + ) +} diff --git a/src/components/staffs/WizardForm.tsx b/src/components/staffs/WizardForm.tsx new file mode 100644 index 0000000..4e9f4ad --- /dev/null +++ b/src/components/staffs/WizardForm.tsx @@ -0,0 +1,73 @@ +import React, { useState } from 'react' +import { Stepper, Step } from 'react-form-stepper' +// import WizardProgram from "./WizardProgram"; +import WizardEnrollment from './WizardEnrollment' +import WizardProgram from './WizardProgram' +// import WizardSocioEconomics from "./WizardSocioEconomics"; +// import WizardAttendance from "./WizardAttendance"; +// import WizardPerformance from "./WizardPerformance"; +// import WizardFinalResult from "./WizardFinalResult"; +// import WizardTransfer from "./WizardTransfer"; +// import WizardConfigDone from "./WizardConfigDone"; + +const steps = [ + { label: 'Program' }, + { label: 'Staff registry' }, + { label: 'Attendance' }, + { label: 'Transfer' } +] + +export default function WizardForm() { + const [wizardStep, setWizardSetp] = useState(0) + + const RenderContent = () => { + switch (wizardStep) { + case 0: + return <WizardProgram setWizardSetp={setWizardSetp} /> + case 1: + return <WizardEnrollment setWizardSetp={setWizardSetp} /> + // case 2: + // return <WizardSocioEconomics setWizardSetp={setWizardSetp} /> + // case 3: + // return <WizardAttendance setWizardSetp={setWizardSetp} /> + // case 4: + // return <WizardPerformance setWizardSetp={setWizardSetp} /> + // case 5: + // return <WizardFinalResult setWizardSetp={setWizardSetp} /> + // case 6: + // return <WizardTransfer setWizardSetp={setWizardSetp} /> + // case 7: + // return <WizardConfigDone /> + default: + return <></> + } + } + + return ( + <> + <Stepper + activeStep={wizardStep} + connectorStateColors={true} + styleConfig={{ + size: 40, + activeBgColor: 'blue', + completedBgColor: 'green' + }} + connectorStyleConfig={{ + activeColor: 'green' + }} + > + {steps.map((step, index) => ( + <Step + key={index} + onClick={() => { + setWizardSetp(index) + }} + label={step.label} + /> + ))} + </Stepper> + <RenderContent /> + </> + ) +} diff --git a/src/components/staffs/WizardProgram.tsx b/src/components/staffs/WizardProgram.tsx new file mode 100644 index 0000000..2af8754 --- /dev/null +++ b/src/components/staffs/WizardProgram.tsx @@ -0,0 +1,104 @@ +import React from 'react' +import { NoticeBox, Button } from '@dhis2/ui' +import { GroupForm } from '..' +import { Form } from 'react-final-form' +import { getDataStoreElement } from '../../utils/functions' +import { type SubmitProgramDataProps, type FetchProgramDatasHooksProps } from '../../types/moduleConfigurations' +import useLoadPrograms from '../../hooks/commons/useLoadPrograms' +import { useGetProgramFormField, useSubmitProgramDatas } from '../../hooks/staffs' +import Loading from '../appList/Loading' +import { IoIosArrowRoundForward } from 'react-icons/io' +import style from './index.module.css' + +interface WizardPageProps { + setWizardSetp: React.Dispatch<React.SetStateAction<number>> +} + +export default function WizardProgram({ setWizardSetp }: WizardPageProps) { + const { getFormFields } = useGetProgramFormField() + const { loadingProcessing, submit }: SubmitProgramDataProps = useSubmitProgramDatas() + const { data, error, loading }: FetchProgramDatasHooksProps = useLoadPrograms() + return ( + <> + <Loading loadings={[loading]} /> + {error !== undefined && error !== null && ( + <NoticeBox title="Configurations" warning> + {error.message} + </NoticeBox> + )} + + <div className={style.formContent}> + {data !== undefined && data !== null && ( + <div> + <Form + onSubmit={(values: { program: string }) => { + submit({ + data, + program: values.program, + goToNext: () => { + setWizardSetp(1) + } + }) + }} + render={({ handleSubmit }: { handleSubmit: any }) => { + return ( + data?.programs?.length > 0 && ( + <form onSubmit={handleSubmit}> + <GroupForm + disabled={false} + name="Staffs Program" + fields={getFormFields({ + programs: data.programs, + data + }).map((p) => { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'program', + key: 'staff' + }) + } + })} + /> + <div className={style.flexBetween}> + <div className={style.flex}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> + </div> + <div className={style.btnCancel}> + <Button disabled type="button"> + Cancel + </Button> + </div> + </div> + {getFormFields({ + programs: data.programs, + data + })?.length > 0 && ( + <div> + <Button + primary + onClick={() => { + setWizardSetp(1) + }} + > + <IoIosArrowRoundForward style={{ fontSize: '20px' }} /> + Next + </Button> + </div> + )} + </div> + </form> + ) + ) + }} + /> + </div> + )} + </div> + </> + ) +} diff --git a/src/components/staffs/WizardTransfer.tsx b/src/components/staffs/WizardTransfer.tsx new file mode 100644 index 0000000..3a85a87 --- /dev/null +++ b/src/components/staffs/WizardTransfer.tsx @@ -0,0 +1,161 @@ +import React, { useState, useEffect } from 'react' +import { NoticeBox, Button } from '@dhis2/ui' +import { getDataStoreElement } from '../../utils/functions' +import useLoadProgramStages from '../../hooks/commons/useLoadProgramStages' +import useLoadDataElements from '../../hooks/commons/useLoadDataElements' +import useLoadDataStoreDatas from '../../hooks/commons/useLoadDataStoreDatas' +import Loading from '../appList/Loading' +import useGetTransferField from '../../hooks/students/useGetTransferField' +import useTransferSubmit from '../../hooks/students/useTransferSubmit' + +import style from './index.module.css' +import { Form } from 'react-final-form' +import { GroupForm } from '..' +import { type SubmitTransferValue } from '../../types/students' + +interface WizardPageProps { + setWizardSetp: React.Dispatch<React.SetStateAction<number>> +} + +export default function WizardTransfer({ setWizardSetp }: WizardPageProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() + const { getDataElements, dataElementsDatas } = useLoadDataElements() + const { getFormFields } = useGetTransferField() + const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() + const { submit, loadingProcessing } = useTransferSubmit() + const { data, loading, error } = useLoadDataStoreDatas() + + useEffect(() => { + if ( + data?.dataStoreValues !== undefined && + data?.dataStoreValues !== null && + data?.dataStoreConfigs !== null && + data?.dataStoreConfigs !== undefined + ) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'program', + key: 'student' + }) + const programStageId = getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.programStage + const studentProgramFilterConfig = getDataStoreElement({ + dataStores: data?.dataStoreConfigs, + elementKey: 'transfer', + key: 'student' + })?.programStage?.filter + + if (programId === undefined) { + setNoProgramErrorMessage('No programs have been configured. Please configure it before continuing !') + } + + if (programId !== null && programId !== undefined) { + getProgramStages(programId, studentProgramFilterConfig) + } + if (programStageId !== null && programStageId !== undefined) { + getDataElements(programStageId) + } + } + }, [data]) + + return ( + <> + <Loading loadings={[loading, loadingProgramStages]} /> + {error !== undefined && error !== null && ( + <NoticeBox title="Configurations" warning> + {error.message} + </NoticeBox> + )} + + {noProgramErrorMessage !== undefined && noProgramErrorMessage !== null && ( + <NoticeBox title="Configuration" warning> + {`${noProgramErrorMessage}`} + </NoticeBox> + )} + + <div className={style.formContent}> + {data !== undefined && data !== null && ( + <div> + <Form + onSubmit={async (value: SubmitTransferValue) => { + await submit(value, data.dataStoreValues, data.dataStoreConfigs, () => { + setWizardSetp(7) + }) + }} + initialValues={{ + programStage: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.programStage, + destinySchool: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.destinySchool, + originSchool: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.originSchool, + status: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.status, + reason: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.reason + }} + render={({ handleSubmit, form }: any) => { + const handleCancel = () => { + // form.change("programStage", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.programStage) + // form.change("destinySchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.destinySchool) + // form.change("originSchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.originSchool) + // form.change("status", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.status) + } + + return ( + programStagesDatas?.programStages?.length > 0 && ( + <div> + <form onSubmit={handleSubmit}> + <GroupForm + disabled={false} + name="transfer" + fields={getFormFields({ + dataStoreConfigs: data.dataStoreConfigs, + programStages: programStagesDatas.programStages, + getDataElements, + dataElements: dataElementsDatas?.dataElements || [] + })} + /> + <div className={style.btnContainer}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> + </div> + <div className={style.btnCancel}> + <Button disabled onClick={handleCancel} type="button"> + Cancel + </Button> + </div> + </div> + </form> + </div> + ) + ) + }} + /> + </div> + )} + </div> + </> + ) +} diff --git a/src/components/staffs/index.module.css b/src/components/staffs/index.module.css new file mode 100644 index 0000000..7afb2aa --- /dev/null +++ b/src/components/staffs/index.module.css @@ -0,0 +1,60 @@ +.formContent { + padding: 20px; + border-radius: 10px; + background-color: #fff; + margin-top: 10px; + border: 1px solid #f0f0f0; + box-shadow: 1px 2px #00000030; +} + +.btnContainer { + margin-top: 20px; + padding: 0px 10px; + display: flex; +} + +.btnCancel { + margin-left: 20px; +} + +.loadingContainer { + display: flex; + align-items: center; + margin: 10px 0px; +} + +.flex { + display: flex; + align-items: center; +} + +.flexBetween { + margin-top: 20px; + padding: 0px 10px; + display: flex; + justify-content: space-between; +} + +.configDoneContainer { + display: flex; + justify-content: center; + align-items: center; + padding: 40px; + border-radius: 10px; + flex-direction: row; + background-color: #fff; + margin-top: 10px; + border: 1px solid #f0f0f0; + box-shadow: 1px 2px #00000030; +} + +.configDoneIcon { + font-size: 50px; + color: green; +} + +.configDoneSuccessText { + margin-top: 10px; + font-weight: bold; + font-size: 20px; +} diff --git a/src/components/staffs/index.ts b/src/components/staffs/index.ts index 9e3f153..0e8f77d 100644 --- a/src/components/staffs/index.ts +++ b/src/components/staffs/index.ts @@ -1,5 +1,6 @@ import AttendanceForm from "./AttendanceForm"; import EnrollmentForm from "./EnrollmentForm"; import ProgramForm from "./ProgramForm"; +import WizardForm from "./WizardForm"; -export { ProgramForm, EnrollmentForm, AttendanceForm } +export { ProgramForm, EnrollmentForm, AttendanceForm, WizardForm } diff --git a/src/components/students/TransferForm.tsx b/src/components/students/TransferForm.tsx index 08071bf..13d8d39 100644 --- a/src/components/students/TransferForm.tsx +++ b/src/components/students/TransferForm.tsx @@ -1,5 +1,3 @@ -/* eslint-disable*/ - import React, { useState, useEffect } from "react"; import { NoticeBox } from '@dhis2/ui' import { getDataStoreElement } from "../../utils/functions"; diff --git a/src/components/students/WizardAttendance.tsx b/src/components/students/WizardAttendance.tsx index 6d42227..cce1e45 100644 --- a/src/components/students/WizardAttendance.tsx +++ b/src/components/students/WizardAttendance.tsx @@ -1,116 +1,263 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect } from 'react' import { NoticeBox, Button } from '@dhis2/ui' -import { getDataStoreElement } from "../../utils/functions"; -import { useGetAttendanceFormFields } from "../../hooks/students"; -import useLoadProgramStages from "../../hooks/commons/useLoadProgramStages"; -import useLoadDataElements from "../../hooks/commons/useLoadDataElements"; +import { getDataStoreElement } from '../../utils/functions' +import { useGetAttendanceFormFields } from '../../hooks/students' +import useLoadProgramStages from '../../hooks/commons/useLoadProgramStages' +import useLoadDataElements from '../../hooks/commons/useLoadDataElements' import { - type SubmitAttendanceValue, - type LoadDataElementsResponse, - type UseFetchEnrollmentDatasResponse -} from "../../types/students"; -import Loading from "../appList/Loading"; -import useLoadDataStoreDatas from "../../hooks/commons/useLoadDataStoreDatas"; -import useAttendanceSubmit from "../../hooks/students/useAttendanceSubmit"; + type SubmitAttendanceValue, + type LoadDataElementsResponse, + type UseFetchEnrollmentDatasResponse +} from '../../types/students' +import Loading from '../appList/Loading' +import useLoadDataStoreDatas from '../../hooks/commons/useLoadDataStoreDatas' +import useAttendanceSubmit from '../../hooks/students/useAttendanceSubmit' import style from './index.module.css' -import { Form } from "react-final-form" -import { GroupForm } from ".."; +import { Form } from 'react-final-form' +import { GroupForm } from '..' +import { IoIosArrowRoundForward } from 'react-icons/io' -interface ZizardProgramProps { - setWizardSetp: React.Dispatch<React.SetStateAction<number>> +interface WizardPageProps { + setWizardSetp: React.Dispatch<React.SetStateAction<number>> } -export default function WizardAttendance({ setWizardSetp }: ZizardProgramProps) { - const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() - const { getDataElements, dataElementsDatas }: LoadDataElementsResponse = useLoadDataElements() - const { getFormFields } = useGetAttendanceFormFields() - const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() - const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() - const { submit, loadingProcessing } = useAttendanceSubmit() +export default function WizardAttendance({ setWizardSetp }: WizardPageProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() + const { getDataElements, dataElementsDatas }: LoadDataElementsResponse = useLoadDataElements() + const { getFormFields } = useGetAttendanceFormFields() + const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() + const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() + const { submit, loadingProcessing } = useAttendanceSubmit() - useEffect(() => { - if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { - setNoProgramErrorMessage(null) - const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "student" }) - const programStageId = getDataStoreElement({ dataStores: data?.dataStoreValues, elementKey: "attendance", key: "student" })?.programStage - const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "attendance", key: "student" })?.programStage?.filter + useEffect(() => { + if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'program', + key: 'student' + }) + const programStageId = getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.programStage + const studentProgramFilterConfig = getDataStoreElement({ + dataStores: data?.dataStoreConfigs, + elementKey: 'attendance', + key: 'student' + })?.programStage?.filter - if (programId === undefined) { - setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") - } - if (programId !== null && programId !== undefined) { - void getProgramStages(programId, studentProgramFilterConfig) - } - if (programStageId !== null && programStageId !== undefined) { - getDataElements(programStageId) - } - } - }, [data]) + if (programId === undefined) { + setNoProgramErrorMessage('No programs have been configured. Please configure it before continuing !') + } + if (programId !== null && programId !== undefined) { + void getProgramStages(programId, studentProgramFilterConfig) + } + if (programStageId !== null && programStageId !== undefined) { + getDataElements(programStageId) + } + } + }, [data]) - return ( - <> - <Loading loadings={[loading, loadingProgramStages]} /> - { - (error !== undefined && error !== null) && ( - <NoticeBox title="Configurations" warning> - {error.message} - </NoticeBox> - ) - } + return ( + <> + <Loading loadings={[loading, loadingProgramStages]} /> + {error !== undefined && error !== null && ( + <NoticeBox title="Configurations" warning> + {error.message} + </NoticeBox> + )} + {noProgramErrorMessage !== undefined && noProgramErrorMessage !== null && ( + <NoticeBox title="Configuration" warning> + {`${noProgramErrorMessage}`} + </NoticeBox> + )} - <div className={style.formContent}> - {(data !== undefined && data !== null) && ( - <div> - <Form - onSubmit={async (values: SubmitAttendanceValue) => { - await submit({ values, dataStoreValues: data.dataStoreValues, dataStoreConfigs: data.dataStoreConfigs, goToNext: () => { setWizardSetp(4) } }) - }} - initialValues={ - { - programStage: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.programStage, - absenceReason: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.absenceReason, - status: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.status, - absentCode: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.statusOptions?.find((x: any) => x.key === "absent")?.code, - presentCode: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.statusOptions?.find((x: any) => x.key === "present")?.code, - lateCode: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.statusOptions?.find((x: any) => x.key === "late")?.code, - leaveCode: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.statusOptions?.find((x: any) => x.key === "leave")?.code, - } - } - render={ - ({ handleSubmit, form }: any) => { - const cancelBtn = () => { - // form.change("programStage", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.programStage) - // form.change("absenceReason", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.absenceReason) - // form.change("status", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "attendance", key: "student" })?.status) - } + <div className={style.formContent}> + {data && ( + <div> + <Form + onSubmit={async (values: SubmitAttendanceValue) => { + await submit({ + values, + dataStoreValues: data.dataStoreValues, + dataStoreConfigs: data.dataStoreConfigs, + goToNext: () => { + setWizardSetp(4) + } + }) + }} + render={({ handleSubmit }: any) => { + return ( + programStagesDatas?.programStages?.length > 0 && ( + <form onSubmit={handleSubmit}> + <GroupForm + disabled={false} + name="Attendance" + fields={getFormFields({ + dataStoreConfigs: data.dataStoreConfigs, + programStages: programStagesDatas.programStages, + getDataElements, + dataElements: + dataElementsDatas?.dataElements !== undefined && + dataElementsDatas?.dataElements !== null && + dataElementsDatas?.dataElements?.length > 0 + ? dataElementsDatas?.dataElements + : [] + }).map((p) => { + if (p.name === 'programStage') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.programStage + } + } - return programStagesDatas?.programStages?.length > 0 && ( - <form onSubmit={handleSubmit}> - <GroupForm - disabled={false} - name="Attendance" - fields={getFormFields({ - dataStoreConfigs: data.dataStoreConfigs, - programStages: programStagesDatas.programStages, - getDataElements, - dataElements: dataElementsDatas?.dataElements !== undefined && dataElementsDatas?.dataElements !== null && dataElementsDatas?.dataElements?.length > 0 - ? dataElementsDatas?.dataElements - : [] - })} - /> - <div className={style.btnContainer}> - <div><Button type="submit" primary loading={loadingProcessing}>Save</Button></div> - <div className={style.btnCancel}><Button type="button" disabled onClick={cancelBtn}>Cancel</Button></div> - </div> - </form> - ) - } - } - /> - </div> - )} - </div> - </> - ); + if (p.name === 'absenceReason') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.absenceReason + } + } + + if (p.name === 'status') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.status + } + } + + if (p.name === 'absentCode') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'absent') + ?.code + } + } + + if (p.name === 'presentCode') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'present') + ?.code + } + } + + if (p.name === 'lateCode') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'late')?.code + } + } + + if (p.name === 'leaveCode') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'leave')?.code + } + } + + return p + })} + /> + <div className={style.flexBetween}> + <div className={style.flex}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> + </div> + <div className={style.btnCancel}> + <Button disabled type="button"> + Cancel + </Button> + </div> + </div> + {getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.programStage && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.absenceReason && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.status && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'absent')?.code && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'present')?.code && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'late')?.code && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'leave')?.code && ( + <div> + <Button + primary + onClick={() => { + setWizardSetp(4) + }} + > + <IoIosArrowRoundForward style={{ fontSize: '20px' }} /> + Next + </Button> + </div> + )} + </div> + </form> + ) + ) + }} + /> + </div> + )} + </div> + </> + ) } diff --git a/src/components/students/WizardConfigDone.tsx b/src/components/students/WizardConfigDone.tsx new file mode 100644 index 0000000..b76de0c --- /dev/null +++ b/src/components/students/WizardConfigDone.tsx @@ -0,0 +1,14 @@ +import React from 'react' +import { IoCheckmarkDoneCircle } from 'react-icons/io5' +import style from './index.module.css' + +export default function WizardConfigDone() { + return ( + <> + <div className={style.configDoneContainer}> + <IoCheckmarkDoneCircle className={style.configDoneIcon} /> + <div className={style.configDoneSuccessText}>Configuration Done with Success</div> + </div> + </> + ) +} diff --git a/src/components/students/WizardEnrollment.tsx b/src/components/students/WizardEnrollment.tsx index 2ff5fb6..56dd399 100644 --- a/src/components/students/WizardEnrollment.tsx +++ b/src/components/students/WizardEnrollment.tsx @@ -1,109 +1,200 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect } from 'react' import { NoticeBox, Button } from '@dhis2/ui' -import { getDataStoreElement } from "../../utils/functions"; -import useGetEnrollmentField from "../../hooks/students/useGetEnrollmentField"; -import useLoadProgramStages from "../../hooks/commons/useLoadProgramStages"; -import useLoadDataElements from "../../hooks/commons/useLoadDataElements"; -import useEnrollmentSubmit from "../../hooks/students/useEnrollmentSubmit"; -import useLoadDataStoreDatas from "../../hooks/commons/useLoadDataStoreDatas"; -import Loading from "../appList/Loading"; +import { getDataStoreElement } from '../../utils/functions' +import useGetEnrollmentField from '../../hooks/students/useGetEnrollmentField' +import useLoadProgramStages from '../../hooks/commons/useLoadProgramStages' +import useLoadDataElements from '../../hooks/commons/useLoadDataElements' +import useEnrollmentSubmit from '../../hooks/students/useEnrollmentSubmit' +import useLoadDataStoreDatas from '../../hooks/commons/useLoadDataStoreDatas' +import Loading from '../appList/Loading' import style from './index.module.css' -import { Form } from "react-final-form" -import GroupForm from "../form/GroupForm"; -import { type SubmitEnrollmentValue } from "../../types/students"; +import { Form } from 'react-final-form' +import GroupForm from '../form/GroupForm' +import { type SubmitEnrollmentValue } from '../../types/students' +import { IoIosArrowRoundForward } from 'react-icons/io' -interface ZizardProgramProps { - setWizardSetp: React.Dispatch<React.SetStateAction<number>> +interface WizardPageProps { + setWizardSetp: React.Dispatch<React.SetStateAction<number>> } -export default function WizardEnrollment({ setWizardSetp }: ZizardProgramProps) { - const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() - const { getDataElements, dataElementsDatas } = useLoadDataElements() - const { getFormFields } = useGetEnrollmentField() - const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() - const { submit, loadingProcessing } = useEnrollmentSubmit() - const { data, loading, error } = useLoadDataStoreDatas() +export default function WizardEnrollment({ setWizardSetp }: WizardPageProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() + const { getDataElements, dataElementsDatas } = useLoadDataElements() + const { getFormFields } = useGetEnrollmentField() + const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() + const { submit, loadingProcessing } = useEnrollmentSubmit() + const { data, loading, error } = useLoadDataStoreDatas() - useEffect(() => { - if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null && data?.dataStoreConfigs !== null && data?.dataStoreConfigs !== undefined) { - setNoProgramErrorMessage(null) - const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "student" }) - const programStageId = getDataStoreElement({ dataStores: data?.dataStoreValues, elementKey: "registration", key: "student" })?.programStage - const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "registration", key: "student" })?.programStage?.filter + useEffect(() => { + if (data?.dataStoreValues && data?.dataStoreConfigs) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'program', + key: 'student' + }) + const programStageId = getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'registration', + key: 'student' + })?.programStage + const studentProgramFilterConfig = getDataStoreElement({ + dataStores: data?.dataStoreConfigs, + elementKey: 'registration', + key: 'student' + })?.programStage?.filter - if (programId === undefined) { - setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") - } + if (programId === undefined) { + setNoProgramErrorMessage('No programs have been configured. Please configure it before continuing !') + } - if (programId !== null && programId !== undefined) { - void getProgramStages(programId, studentProgramFilterConfig) - } - if (programStageId !== null && programStageId !== undefined) { - void getDataElements(programStageId) - } - } - }, [data]) + if (programId !== null && programId !== undefined) { + void getProgramStages(programId, studentProgramFilterConfig) + } + if (programStageId !== null && programStageId !== undefined) { + void getDataElements(programStageId) + } + } + }, [data]) - return ( - <> - { - console.log(programStagesDatas) - } - { - console.log(dataElementsDatas) - } - <Loading loadings={[loading, loadingProgramStages]} /> - { - (error !== undefined && error !== null) && ( - <NoticeBox title="Configurations" warning> - {error.message} - </NoticeBox> - ) - } + return ( + <> + <Loading loadings={[loading, loadingProgramStages]} /> + {error !== undefined && error !== null && ( + <NoticeBox title="Configurations" warning> + {error.message} + </NoticeBox> + )} + {noProgramErrorMessage !== undefined && noProgramErrorMessage !== null && ( + <NoticeBox title="Configuration" warning> + {`${noProgramErrorMessage}`} + </NoticeBox> + )} - <div className={style.formContent}> - {(data !== undefined && data !== null) && ( - <div> - <Form - initialValues={{ - programStage: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "registration", key: "student" })?.programStage, - grade: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "registration", key: "student" })?.grade, - section: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "registration", key: "student" })?.section, - academicYear: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "registration", key: "student" })?.academicYear - }} - onSubmit={async (value: SubmitEnrollmentValue) => { - await submit(value, data.dataStoreValues, data.dataStoreConfigs, () => { setWizardSetp(2) }) - }} - render={ - ({ handleSubmit }: { handleSubmit: any }) => { - return programStagesDatas?.programStages?.length > 0 && ( - <form onSubmit={handleSubmit}> - <GroupForm - disabled={false} - name="Student Enrollment" - fields={ - getFormFields({ - dataStoreConfigs: data.dataStoreConfigs, - programStages: programStagesDatas?.programStages, - getDataElements, - dataElements: (dataElementsDatas?.dataElements !== undefined && dataElementsDatas?.dataElements !== null) - ? dataElementsDatas?.dataElements - : [] - })} - /> - <div className={style.btnContainer}> - <div><Button type="submit" primary loading={loadingProcessing}>Save</Button></div> - <div className={style.btnCancel}><Button disabled type="button">Cancel</Button></div> - </div> - </form> - ) - } - } - /> - </div> - )} - </div> - </> - ); + <div className={style.formContent}> + {data !== undefined && data !== null && ( + <div> + <Form + onSubmit={async (value: SubmitEnrollmentValue) => { + await submit(value, data.dataStoreValues, data.dataStoreConfigs, () => { + setWizardSetp(2) + }) + }} + component={({ handleSubmit, form }) => { + return ( + programStagesDatas?.programStages?.length > 0 && ( + <form onSubmit={handleSubmit}> + <GroupForm + disabled={false} + name="Student Enrollment" + fields={getFormFields({ + dataStoreConfigs: data.dataStoreConfigs, + programStages: programStagesDatas?.programStages, + getDataElements, + dataElements: + dataElementsDatas?.dataElements !== undefined && + dataElementsDatas?.dataElements !== null + ? dataElementsDatas?.dataElements + : [] + }).map((p) => { + if (p.name === 'programStage') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'student' + })?.programStage + } + } + if (p.name === 'grade') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'student' + })?.grade + } + } + if (p.name === 'section') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'student' + })?.section + } + } + if (p.name === 'academicYear') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'student' + })?.academicYear + } + } + return p + })} + /> + <div className={style.flexBetween}> + <div className={style.flex}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> + </div> + <div className={style.btnCancel}> + <Button disabled type="button"> + Cancel + </Button> + </div> + </div> + {getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'student' + })?.programStage && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'student' + })?.grade && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'student' + })?.section && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'student' + })?.academicYear && ( + <div> + <Button + primary + onClick={() => { + setWizardSetp(2) + }} + > + <IoIosArrowRoundForward style={{ fontSize: '20px' }} /> + Next + </Button> + </div> + )} + </div> + </form> + ) + ) + }} + /> + </div> + )} + </div> + </> + ) } diff --git a/src/components/students/WizardFinalResult.tsx b/src/components/students/WizardFinalResult.tsx index c97cb71..edcf4a4 100644 --- a/src/components/students/WizardFinalResult.tsx +++ b/src/components/students/WizardFinalResult.tsx @@ -1,87 +1,138 @@ -import React, { useState, useEffect } from "react"; -import { Button, NoticeBox } from '@dhis2/ui' -import { getDataStoreElement } from "../../utils/functions"; -import { useGetSocioEconomicsFormFields, useSocioEconomicsSubmit } from "../../hooks/students"; -import useLoadProgramStages from "../../hooks/commons/useLoadProgramStages"; -import { - type UseFetchEnrollmentDatasResponse -} from "../../types/students"; -import Loading from "../appList/Loading"; -import useLoadDataStoreDatas from "../../hooks/commons/useLoadDataStoreDatas"; - +import React, { useState, useEffect } from 'react' +import { NoticeBox, Button } from '@dhis2/ui' +import { getDataStoreElement } from '../../utils/functions' +import useLoadProgramStages from '../../hooks/commons/useLoadProgramStages' +import useLoadDataElements from '../../hooks/commons/useLoadDataElements' +import { type SubmitFinalResultValue, type UseFetchEnrollmentDatasResponse } from '../../types/students' +import Loading from '../appList/Loading' +import useLoadDataStoreDatas from '../../hooks/commons/useLoadDataStoreDatas' +import useGetFinalResultFormFields from '../../hooks/students/useGetFinalResultFormFields' +import useFinalResultSubmit from '../../hooks/students/useFinalResultSubmit' import style from './index.module.css' -import { Form } from "react-final-form" -import { type SubmitEnrollmentValue } from "../../types/students"; -import { GroupForm } from ".."; +import { Form } from 'react-final-form' +import { GroupForm } from '..' -interface ZizardProgramProps { - setWizardSetp: React.Dispatch<React.SetStateAction<number>> +interface WizardPageProps { + setWizardSetp: React.Dispatch<React.SetStateAction<number>> } -export default function WizardFinalResult({ setWizardSetp }: ZizardProgramProps) { - const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() - const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() - const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() - const { getFormFields } = useGetSocioEconomicsFormFields() - const { submit, loadingProcessing } = useSocioEconomicsSubmit() +export default function WizardFinalResult({ setWizardSetp }: WizardPageProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() + const { getDataElements, dataElementsDatas } = useLoadDataElements() + const { getFormFields } = useGetFinalResultFormFields() + const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() + const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() + const { submit, loadingProcessing } = useFinalResultSubmit() + + useEffect(() => { + if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'program', + key: 'student' + }) + const programStageId = getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'final-result', + key: 'student' + })?.programStage + const studentProgramFilterConfig = getDataStoreElement({ + dataStores: data?.dataStoreConfigs, + elementKey: 'final-result', + key: 'student' + })?.programStage?.filter - useEffect(() => { - if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { - setNoProgramErrorMessage(null) - const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "student" }) - const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "socio-economics", key: "student" })?.programStage?.filter + if (programId === undefined) { + setNoProgramErrorMessage('No programs have been configured. Please configure it before continuing !') + } + if (programId) { + void getProgramStages(programId, studentProgramFilterConfig) + } + if (programStageId) { + getDataElements(programStageId) + } + } + }, [data]) - if (programId === undefined) { - setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") - } - if (programId !== null && programId !== undefined) { - void getProgramStages(programId, studentProgramFilterConfig) - } - } - }, [data]) + return ( + <> + <Loading loadings={[loading, loadingProgramStages]} /> + {error !== undefined && error !== null && ( + <NoticeBox title="Configurations" warning> + {error.message} + </NoticeBox> + )} + {noProgramErrorMessage !== undefined && noProgramErrorMessage !== null && ( + <NoticeBox title="Configuration" warning> + {`${noProgramErrorMessage}`} + </NoticeBox> + )} - return ( - <> - { - console.log(programStagesDatas) - } - <Loading loadings={[loading, loadingProgramStages]} /> - { - (error !== undefined && error !== null) && ( - <NoticeBox title="Configurations" warning> - {error.message} - </NoticeBox> - ) - } + <div className={style.formContent}> + {data && ( + <div> + <Form + onSubmit={async (values: SubmitFinalResultValue) => { + await submit({ + values, + dataStoreValues: data.dataStoreValues, + dataStoreConfigs: data.dataStoreConfigs, + goToNext: () => { + setWizardSetp(6) + } + }) + }} + initialValues={{ + programStage: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'final-result', + key: 'student' + })?.programStage, + status: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'final-result', + key: 'student' + })?.status + }} + render={({ handleSubmit, form }: any) => { + const cancelBtn = () => {} - <div className={style.formContent}> - {(data !== undefined && data !== null) && ( - <div> - <Form - onSubmit={async (values: { programStage: string }) => { await submit({ programStage: values?.programStage }, data?.dataStoreValues, data?.dataStoreConfigs, () => { setWizardSetp(3) }) }} - render={ - ({ handleSubmit }: { handleSubmit: any }) => { - return programStagesDatas?.programStages?.length > 0 && ( - <form onSubmit={handleSubmit}> - <GroupForm - disabled={false} - name="socio-economics" - fields={getFormFields(data, programStagesDatas.programStages)} - /> - <div className={style.btnContainer}> - <div><Button type="submit" primary loading={loadingProcessing}>Save</Button></div> - <div className={style.btnCancel}><Button disabled type="button">Cancel</Button></div> - </div> - </form> - ) - } - } - /> - </div> - )} - </div> - </> - ); + return ( + programStagesDatas?.programStages?.length > 0 && ( + <form onSubmit={handleSubmit}> + <GroupForm + disabled={false} + name="final-result" + fields={getFormFields({ + dataStoreConfigs: data.dataStoreConfigs, + programStages: programStagesDatas.programStages, + getDataElements, + dataElements: dataElementsDatas?.dataElements || [] + })} + /> + <div className={style.btnContainer}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> + </div> + <div className={style.btnCancel}> + <Button type="button" disabled onClick={cancelBtn}> + Cancel + </Button> + </div> + </div> + </form> + ) + ) + }} + /> + </div> + )} + </div> + </> + ) } diff --git a/src/components/students/WizardForm.tsx b/src/components/students/WizardForm.tsx index 776a09b..cef3e7a 100644 --- a/src/components/students/WizardForm.tsx +++ b/src/components/students/WizardForm.tsx @@ -7,6 +7,7 @@ import WizardAttendance from "./WizardAttendance"; import WizardPerformance from "./WizardPerformance"; import WizardFinalResult from "./WizardFinalResult"; import WizardTransfer from "./WizardTransfer"; +import WizardConfigDone from "./WizardConfigDone"; const steps = [ { label: "Program" }, @@ -15,47 +16,58 @@ const steps = [ { label: "Attendance" }, { label: "Performance" }, { label: "Final Result" }, - { label: "Transfer" } -] + { label: "Transfer" }, +]; export default function WizardForm() { - const [wizardStep, setWizardSetp] = useState(0) + const [wizardStep, setWizardSetp] = useState(0); const RenderContent = () => { switch (wizardStep) { case 0: - return <WizardProgram setWizardSetp={setWizardSetp} /> + return <WizardProgram setWizardSetp={setWizardSetp} />; case 1: - return <WizardEnrollment setWizardSetp={setWizardSetp} /> + return <WizardEnrollment setWizardSetp={setWizardSetp} />; case 2: - return <WizardSocioEconomics setWizardSetp={setWizardSetp} /> + return <WizardSocioEconomics setWizardSetp={setWizardSetp} />; case 3: - return <WizardAttendance setWizardSetp={setWizardSetp} /> + return <WizardAttendance setWizardSetp={setWizardSetp} />; case 4: - return <WizardPerformance setWizardSetp={setWizardSetp} /> + return <WizardPerformance setWizardSetp={setWizardSetp} />; case 5: - return <WizardFinalResult setWizardSetp={setWizardSetp} /> + return <WizardFinalResult setWizardSetp={setWizardSetp} />; case 6: - return <WizardTransfer setWizardSetp={setWizardSetp} /> + return <WizardTransfer setWizardSetp={setWizardSetp} />; + case 7: + return <WizardConfigDone />; default: - return <></> + return <></>; } - } + }; return ( <> <Stepper activeStep={wizardStep} connectorStateColors={true} - styleConfig={{ size: 40, activeBgColor: 'blue', completedBgColor: 'green' }} + styleConfig={{ + size: 40, + activeBgColor: "blue", + completedBgColor: "green", + }} connectorStyleConfig={{ - activeColor: 'green' + activeColor: "green", }} > - { - steps.map((step, index) => <Step - key={index} onClick={() => { setWizardSetp(index) }} label={step.label} />) - } + {steps.map((step, index) => ( + <Step + key={index} + onClick={() => { + setWizardSetp(index); + }} + label={step.label} + /> + ))} </Stepper> <RenderContent /> </> diff --git a/src/components/students/WizardPerformance.tsx b/src/components/students/WizardPerformance.tsx index bdd9c43..97af01d 100644 --- a/src/components/students/WizardPerformance.tsx +++ b/src/components/students/WizardPerformance.tsx @@ -1,87 +1,141 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect } from 'react' import { Button, NoticeBox } from '@dhis2/ui' -import { getDataStoreElement } from "../../utils/functions"; -import { useGetSocioEconomicsFormFields, useSocioEconomicsSubmit } from "../../hooks/students"; -import useLoadProgramStages from "../../hooks/commons/useLoadProgramStages"; -import { - type UseFetchEnrollmentDatasResponse -} from "../../types/students"; -import Loading from "../appList/Loading"; -import useLoadDataStoreDatas from "../../hooks/commons/useLoadDataStoreDatas"; - +import { getDataStoreElement } from '../../utils/functions' +import { usePerformanceFormFields, usePerformanceSubmit } from '../../hooks/students' +import useLoadProgramStages from '../../hooks/commons/useLoadProgramStages' +import Loading from '../appList/Loading' +import useLoadDataStoreDatas from '../../hooks/commons/useLoadDataStoreDatas' +import { IoIosArrowRoundForward } from 'react-icons/io' import style from './index.module.css' -import { Form } from "react-final-form" -import { type SubmitEnrollmentValue } from "../../types/students"; -import { GroupForm } from ".."; +import { Form } from 'react-final-form' +import { GroupForm } from '..' -interface ZizardProgramProps { - setWizardSetp: React.Dispatch<React.SetStateAction<number>> +interface WizardPageProps { + setWizardSetp: React.Dispatch<React.SetStateAction<number>> } -export default function WizardPerformance({ setWizardSetp }: ZizardProgramProps) { - const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() - const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() - const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() - const { getFormFields } = useGetSocioEconomicsFormFields() - const { submit, loadingProcessing } = useSocioEconomicsSubmit() +export default function WizardPerformance({ setWizardSetp }: WizardPageProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() + const { loadingProgramStages, programStagesDatas, getProgramStages }: any = useLoadProgramStages() + const { data, loading, error, refetch }: any = useLoadDataStoreDatas() + const { getFormFields } = usePerformanceFormFields() + const { loadingProcessing, submit } = usePerformanceSubmit() - useEffect(() => { - if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { - setNoProgramErrorMessage(null) - const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "student" }) - const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "socio-economics", key: "student" })?.programStage?.filter + useEffect(() => { + if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'program', + key: 'student' + }) + const studentProgramFilterConfig = getDataStoreElement({ + dataStores: data?.dataStoreConfigs, + elementKey: 'performance', + key: 'student' + })?.programStages?.filter - if (programId === undefined) { - setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") - } - if (programId !== null && programId !== undefined) { - void getProgramStages(programId, studentProgramFilterConfig) - } - } - }, [data]) + if (programId === undefined) { + setNoProgramErrorMessage('No programs have been configured. Please configure it before continuing !') + } + if (programId !== null && programId !== undefined) { + getProgramStages(programId, studentProgramFilterConfig) + } + } + }, [data]) + return ( + <> + <Loading loadings={[loading, loadingProgramStages]} /> + {error !== undefined && error !== null && ( + <NoticeBox title="Configurations" warning> + {error.message} + </NoticeBox> + )} - return ( - <> - { - console.log(programStagesDatas) - } - <Loading loadings={[loading, loadingProgramStages]} /> - { - (error !== undefined && error !== null) && ( - <NoticeBox title="Configurations" warning> - {error.message} - </NoticeBox> - ) - } + {noProgramErrorMessage !== undefined && noProgramErrorMessage !== null && ( + <NoticeBox title="Configuration" warning> + {`${noProgramErrorMessage}`} + </NoticeBox> + )} - <div className={style.formContent}> - {(data !== undefined && data !== null) && ( - <div> - <Form - onSubmit={async (values: { programStage: string }) => { await submit({ programStage: values?.programStage }, data?.dataStoreValues, data?.dataStoreConfigs, () => { setWizardSetp(3) }) }} - render={ - ({ handleSubmit }: { handleSubmit: any }) => { - return programStagesDatas?.programStages?.length > 0 && ( - <form onSubmit={handleSubmit}> - <GroupForm - disabled={false} - name="socio-economics" - fields={getFormFields(data, programStagesDatas.programStages)} - /> - <div className={style.btnContainer}> - <div><Button type="submit" primary loading={loadingProcessing}>Save</Button></div> - <div className={style.btnCancel}><Button disabled type="button">Cancel</Button></div> - </div> - </form> - ) - } - } - /> - </div> - )} - </div> - </> - ); + <div className={style.formContent}> + {data !== undefined && data !== null && ( + <div> + <Form + initialValues={{ + programStages: + getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'performance', + key: 'student' + })?.programStages?.map((p: { programStage: string }) => p.programStage) || [] + }} + onSubmit={async (values: { programStages: any[] }) => { + await submit({ + values, + dataStoreConfigs: data?.dataStoreConfigs || [], + dataStoreValues: data?.dataStoreValues || [], + goToNext: () => { + setWizardSetp(5) + } + }) + refetch() + }} + render={({ handleSubmit, form }: any) => { + return ( + data?.dataStoreConfigs?.length > 0 && + programStagesDatas?.programStages?.length > 0 && ( + <form onSubmit={handleSubmit}> + <GroupForm + disabled={false} + name="Performance" + fields={getFormFields({ + dataStoreConfigs: data?.dataStoreConfigs, + programStages: programStagesDatas.programStages + })} + /> + <div className={style.flexBetween}> + <div className={style.flex}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> + </div> + <div className={style.btnCancel}> + <Button disabled type="button"> + Cancel + </Button> + </div> + </div> + {getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'performance', + key: 'student' + })?.programStages?.map((p: { programStage: string }) => p.programStage) + ?.length > 0 && ( + <div> + <Button + primary + onClick={() => { + setWizardSetp(5) + }} + > + <IoIosArrowRoundForward style={{ fontSize: '20px' }} /> + Next + </Button> + </div> + )} + </div> + </form> + ) + ) + }} + /> + </div> + )} + </div> + </> + ) } diff --git a/src/components/students/WizardProgram.tsx b/src/components/students/WizardProgram.tsx index 2739304..f364bc9 100644 --- a/src/components/students/WizardProgram.tsx +++ b/src/components/students/WizardProgram.tsx @@ -1,67 +1,105 @@ -import React, { useState, useEffect } from "react"; -import Loading from "../appList/Loading"; -import { useGetProgramFormField, useSubmitProgramDatas } from "../../hooks/students"; -import useLoadPrograms from "../../hooks/commons/useLoadPrograms"; +import React from 'react' +import Loading from '../appList/Loading' +import { useGetProgramFormField, useSubmitProgramDatas } from '../../hooks/students' +import useLoadPrograms from '../../hooks/commons/useLoadPrograms' import { NoticeBox, Button } from '@dhis2/ui' -import { Form } from "react-final-form" +import { Form } from 'react-final-form' +import GroupForm from '../form/GroupForm' +import { getDataStoreElement } from '../../utils/functions' +import { IoIosArrowRoundForward } from 'react-icons/io' import style from './index.module.css' -import GroupForm from "../form/GroupForm"; -import { getDataStoreElement } from "../../utils/functions"; -interface ZizardProgramProps { - setWizardSetp: React.Dispatch<React.SetStateAction<number>> +interface WizardPageProps { + setWizardSetp: React.Dispatch<React.SetStateAction<number>> } -export default function WizardProgram({ setWizardSetp }: ZizardProgramProps) { - const { data, error, loading } = useLoadPrograms() - const { getFormFields } = useGetProgramFormField() - const { loadingProcessing, submit } = useSubmitProgramDatas() +export default function WizardProgram({ setWizardSetp }: WizardPageProps) { + const { data, error, loading } = useLoadPrograms() + const { getFormFields } = useGetProgramFormField() + const { loadingProcessing, submit } = useSubmitProgramDatas() - return ( - <> - <Loading loadings={[loading]} /> - { - (error !== undefined && error !== null) && ( - <NoticeBox title="Configurations" warning> - {error.message} - </NoticeBox> - ) - } + return ( + <> + <Loading loadings={[loading]} /> + {error !== undefined && error !== null && ( + <NoticeBox title="Configurations" warning> + {error.message} + </NoticeBox> + )} - <div className={style.formContent}> - {(data !== undefined && data !== null) && ( - <div> - <Form - initialValues={{ program: getDataStoreElement({ dataStores: data?.dataStoreValues, elementKey: "program", key: "student" }) }} - onSubmit={async (values: { program: string }) => { - await submit({ - data, - program: values.program, - goToNext: () => { setWizardSetp(1) } - }) - }} - render={ - ({ handleSubmit, form }: { handleSubmit: any, form: any }) => { - return data?.programs?.length > 0 && ( - <form onSubmit={handleSubmit}> - <GroupForm - disabled={false} - name="Student Program" - fields={getFormFields({ programs: data.programs, data })} - /> - <div className={style.btnContainer}> - <div><Button type="submit" primary loading={loadingProcessing}>Save</Button></div> - <div className={style.btnCancel}><Button disabled type="button">Cancel</Button></div> - </div> - </form> - ) - } - } - /> - - </div> - )} - </div> - </> - ); + <div className={style.formContent}> + {data !== undefined && data !== null && ( + <div> + <Form + onSubmit={async (values: { program: string }) => { + await submit({ + data, + program: values.program, + goToNext: () => { + setWizardSetp(1) + } + }) + }} + render={({ handleSubmit }: { handleSubmit: any }) => { + return ( + data?.programs?.length > 0 && ( + <form onSubmit={handleSubmit}> + <GroupForm + disabled={false} + name="Student Program" + fields={getFormFields({ + programs: data.programs, + data + }).map((p) => { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'program', + key: 'student' + }) + } + })} + /> + <div className={style.flexBetween}> + <div className={style.flex}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> + </div> + <div className={style.btnCancel}> + <Button disabled type="button"> + Cancel + </Button> + </div> + </div> + {getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'program', + key: 'student' + })?.length > 0 && ( + <div> + <Button + primary + onClick={() => { + setWizardSetp(1) + }} + > + <IoIosArrowRoundForward style={{ fontSize: '20px' }} /> + Next + </Button> + </div> + )} + </div> + </form> + ) + ) + }} + /> + </div> + )} + </div> + </> + ) } diff --git a/src/components/students/WizardSocioEconomics.tsx b/src/components/students/WizardSocioEconomics.tsx index aa263a9..7cc85f4 100644 --- a/src/components/students/WizardSocioEconomics.tsx +++ b/src/components/students/WizardSocioEconomics.tsx @@ -1,86 +1,142 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect } from 'react' import { Button, NoticeBox } from '@dhis2/ui' -import { getDataStoreElement } from "../../utils/functions"; -import { useGetSocioEconomicsFormFields, useSocioEconomicsSubmit } from "../../hooks/students"; -import useLoadProgramStages from "../../hooks/commons/useLoadProgramStages"; -import { - type UseFetchEnrollmentDatasResponse -} from "../../types/students"; -import Loading from "../appList/Loading"; -import useLoadDataStoreDatas from "../../hooks/commons/useLoadDataStoreDatas"; - +import { getDataStoreElement } from '../../utils/functions' +import { useGetSocioEconomicsFormFields, useSocioEconomicsSubmit } from '../../hooks/students' +import useLoadProgramStages from '../../hooks/commons/useLoadProgramStages' +import { type UseFetchEnrollmentDatasResponse } from '../../types/students' +import Loading from '../appList/Loading' +import useLoadDataStoreDatas from '../../hooks/commons/useLoadDataStoreDatas' import style from './index.module.css' -import { Form } from "react-final-form" -import { type SubmitEnrollmentValue } from "../../types/students"; -import { GroupForm } from ".."; +import { Form } from 'react-final-form' +import { GroupForm } from '..' +import { IoIosArrowRoundForward } from 'react-icons/io' -interface ZizardProgramProps { - setWizardSetp: React.Dispatch<React.SetStateAction<number>> +interface WizardPageProps { + setWizardSetp: React.Dispatch<React.SetStateAction<number>> } -export default function WizardSocioEconomics({ setWizardSetp }: ZizardProgramProps) { - const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() - const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() - const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() - const { getFormFields } = useGetSocioEconomicsFormFields() - const { submit, loadingProcessing } = useSocioEconomicsSubmit() +export default function WizardSocioEconomics({ setWizardSetp }: WizardPageProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() + const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() + const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() + const { getFormFields } = useGetSocioEconomicsFormFields() + const { submit, loadingProcessing } = useSocioEconomicsSubmit() + + useEffect(() => { + if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'program', + key: 'student' + }) + const studentProgramFilterConfig = getDataStoreElement({ + dataStores: data?.dataStoreConfigs, + elementKey: 'socio-economics', + key: 'student' + })?.programStage?.filter - useEffect(() => { - if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { - setNoProgramErrorMessage(null) - const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "student" }) - const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "socio-economics", key: "student" })?.programStage?.filter + if (programId === undefined) { + setNoProgramErrorMessage('No programs have been configured. Please configure it before continuing !') + } + if (programId !== null && programId !== undefined) { + void getProgramStages(programId, studentProgramFilterConfig) + } + } + }, [data]) - if (programId === undefined) { - setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") - } - if (programId !== null && programId !== undefined) { - void getProgramStages(programId, studentProgramFilterConfig) - } - } - }, [data]) + return ( + <> + <Loading loadings={[loading, loadingProgramStages]} /> + {error !== undefined && error !== null && ( + <NoticeBox title="Configurations" warning> + {error.message} + </NoticeBox> + )} - return ( - <> - <Loading loadings={[loading, loadingProgramStages]} /> - { - (error !== undefined && error !== null) && ( - <NoticeBox title="Configurations" warning> - {error.message} - </NoticeBox> - ) - } + {noProgramErrorMessage !== undefined && noProgramErrorMessage !== null && ( + <NoticeBox title="Configuration" warning> + {`${noProgramErrorMessage}`} + </NoticeBox> + )} - <div className={style.formContent}> - {(data !== undefined && data !== null) && ( - <div> - <Form - initialValues={{ - programStage: getDataStoreElement({ dataStores: data?.dataStoreValues, elementKey: "socio-economics", key: "student" })?.programStage - }} - onSubmit={async (values: { programStage: string }) => { await submit({ programStage: values?.programStage }, data?.dataStoreValues, data?.dataStoreConfigs, () => { setWizardSetp(3) }) }} - render={ - ({ handleSubmit }: { handleSubmit: any }) => { - return programStagesDatas?.programStages?.length > 0 && ( - <form onSubmit={handleSubmit}> - <GroupForm - disabled={false} - name="socio-economics" - fields={getFormFields(data, programStagesDatas.programStages)} - /> - <div className={style.btnContainer}> - <div><Button type="submit" primary loading={loadingProcessing}>Save</Button></div> - <div className={style.btnCancel}><Button disabled type="button">Cancel</Button></div> - </div> - </form> - ) - } - } - /> - </div> - )} - </div> - </> - ); + <div className={style.formContent}> + {data !== undefined && data !== null && ( + <div> + <Form + onSubmit={async (values: { programStage: string }) => { + await submit( + { programStage: values?.programStage }, + data?.dataStoreValues, + data?.dataStoreConfigs, + () => { + setWizardSetp(3) + } + ) + }} + render={({ handleSubmit }: { handleSubmit: any }) => { + return ( + programStagesDatas?.programStages?.length > 0 && ( + <form onSubmit={handleSubmit}> + <GroupForm + disabled={false} + name="socio-economics" + fields={getFormFields(data, programStagesDatas.programStages).map( + (p) => { + if (p.name === 'programStage') { + return { + ...p, + defaultValue: getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'socio-economics', + key: 'student' + })?.programStage + } + } + return p + } + )} + /> + <div className={style.flexBetween}> + <div className={style.flex}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> + </div> + <div className={style.btnCancel}> + <Button disabled type="button"> + Cancel + </Button> + </div> + </div> + {getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'socio-economics', + key: 'student' + })?.programStage && ( + <div> + <Button + primary + onClick={() => { + setWizardSetp(3) + }} + > + <IoIosArrowRoundForward style={{ fontSize: '20px' }} /> + Next + </Button> + </div> + )} + </div> + </form> + ) + ) + }} + /> + </div> + )} + </div> + </> + ) } diff --git a/src/components/students/WizardTransfer.tsx b/src/components/students/WizardTransfer.tsx index b8b1935..3a85a87 100644 --- a/src/components/students/WizardTransfer.tsx +++ b/src/components/students/WizardTransfer.tsx @@ -1,87 +1,161 @@ -import React, { useState, useEffect } from "react"; -import { Button, NoticeBox } from '@dhis2/ui' -import { getDataStoreElement } from "../../utils/functions"; -import { useGetSocioEconomicsFormFields, useSocioEconomicsSubmit } from "../../hooks/students"; -import useLoadProgramStages from "../../hooks/commons/useLoadProgramStages"; -import { - type UseFetchEnrollmentDatasResponse -} from "../../types/students"; -import Loading from "../appList/Loading"; -import useLoadDataStoreDatas from "../../hooks/commons/useLoadDataStoreDatas"; - +import React, { useState, useEffect } from 'react' +import { NoticeBox, Button } from '@dhis2/ui' +import { getDataStoreElement } from '../../utils/functions' +import useLoadProgramStages from '../../hooks/commons/useLoadProgramStages' +import useLoadDataElements from '../../hooks/commons/useLoadDataElements' +import useLoadDataStoreDatas from '../../hooks/commons/useLoadDataStoreDatas' +import Loading from '../appList/Loading' +import useGetTransferField from '../../hooks/students/useGetTransferField' +import useTransferSubmit from '../../hooks/students/useTransferSubmit' import style from './index.module.css' -import { Form } from "react-final-form" -import { type SubmitEnrollmentValue } from "../../types/students"; -import { GroupForm } from ".."; +import { Form } from 'react-final-form' +import { GroupForm } from '..' +import { type SubmitTransferValue } from '../../types/students' -interface ZizardProgramProps { - setWizardSetp: React.Dispatch<React.SetStateAction<number>> +interface WizardPageProps { + setWizardSetp: React.Dispatch<React.SetStateAction<number>> } -export default function WizardTransfer({ setWizardSetp }: ZizardProgramProps) { - const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() - const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() - const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() - const { getFormFields } = useGetSocioEconomicsFormFields() - const { submit, loadingProcessing } = useSocioEconomicsSubmit() +export default function WizardTransfer({ setWizardSetp }: WizardPageProps) { + const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() + const { getDataElements, dataElementsDatas } = useLoadDataElements() + const { getFormFields } = useGetTransferField() + const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() + const { submit, loadingProcessing } = useTransferSubmit() + const { data, loading, error } = useLoadDataStoreDatas() + + useEffect(() => { + if ( + data?.dataStoreValues !== undefined && + data?.dataStoreValues !== null && + data?.dataStoreConfigs !== null && + data?.dataStoreConfigs !== undefined + ) { + setNoProgramErrorMessage(null) + const programId = getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'program', + key: 'student' + }) + const programStageId = getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.programStage + const studentProgramFilterConfig = getDataStoreElement({ + dataStores: data?.dataStoreConfigs, + elementKey: 'transfer', + key: 'student' + })?.programStage?.filter + + if (programId === undefined) { + setNoProgramErrorMessage('No programs have been configured. Please configure it before continuing !') + } - useEffect(() => { - if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { - setNoProgramErrorMessage(null) - const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "student" }) - const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "socio-economics", key: "student" })?.programStage?.filter + if (programId !== null && programId !== undefined) { + getProgramStages(programId, studentProgramFilterConfig) + } + if (programStageId !== null && programStageId !== undefined) { + getDataElements(programStageId) + } + } + }, [data]) - if (programId === undefined) { - setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") - } - if (programId !== null && programId !== undefined) { - void getProgramStages(programId, studentProgramFilterConfig) - } - } - }, [data]) + return ( + <> + <Loading loadings={[loading, loadingProgramStages]} /> + {error !== undefined && error !== null && ( + <NoticeBox title="Configurations" warning> + {error.message} + </NoticeBox> + )} + {noProgramErrorMessage !== undefined && noProgramErrorMessage !== null && ( + <NoticeBox title="Configuration" warning> + {`${noProgramErrorMessage}`} + </NoticeBox> + )} - return ( - <> - { - console.log(programStagesDatas) - } - <Loading loadings={[loading, loadingProgramStages]} /> - { - (error !== undefined && error !== null) && ( - <NoticeBox title="Configurations" warning> - {error.message} - </NoticeBox> - ) - } + <div className={style.formContent}> + {data !== undefined && data !== null && ( + <div> + <Form + onSubmit={async (value: SubmitTransferValue) => { + await submit(value, data.dataStoreValues, data.dataStoreConfigs, () => { + setWizardSetp(7) + }) + }} + initialValues={{ + programStage: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.programStage, + destinySchool: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.destinySchool, + originSchool: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.originSchool, + status: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.status, + reason: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.reason + }} + render={({ handleSubmit, form }: any) => { + const handleCancel = () => { + // form.change("programStage", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.programStage) + // form.change("destinySchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.destinySchool) + // form.change("originSchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.originSchool) + // form.change("status", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.status) + } - <div className={style.formContent}> - {(data !== undefined && data !== null) && ( - <div> - <Form - onSubmit={async (values: { programStage: string }) => { await submit({ programStage: values?.programStage }, data?.dataStoreValues, data?.dataStoreConfigs, () => { setWizardSetp(3) }) }} - render={ - ({ handleSubmit }: { handleSubmit: any }) => { - return programStagesDatas?.programStages?.length > 0 && ( - <form onSubmit={handleSubmit}> - <GroupForm - disabled={false} - name="socio-economics" - fields={getFormFields(data, programStagesDatas.programStages)} - /> - <div className={style.btnContainer}> - <div><Button type="submit" primary loading={loadingProcessing}>Save</Button></div> - <div className={style.btnCancel}><Button disabled type="button">Cancel</Button></div> - </div> - </form> - ) - } - } - /> - </div> - )} - </div> - </> - ); + return ( + programStagesDatas?.programStages?.length > 0 && ( + <div> + <form onSubmit={handleSubmit}> + <GroupForm + disabled={false} + name="transfer" + fields={getFormFields({ + dataStoreConfigs: data.dataStoreConfigs, + programStages: programStagesDatas.programStages, + getDataElements, + dataElements: dataElementsDatas?.dataElements || [] + })} + /> + <div className={style.btnContainer}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> + </div> + <div className={style.btnCancel}> + <Button disabled onClick={handleCancel} type="button"> + Cancel + </Button> + </div> + </div> + </form> + </div> + ) + ) + }} + /> + </div> + )} + </div> + </> + ) } diff --git a/src/components/students/index.module.css b/src/components/students/index.module.css index 8c9640f..7afb2aa 100644 --- a/src/components/students/index.module.css +++ b/src/components/students/index.module.css @@ -7,19 +7,54 @@ box-shadow: 1px 2px #00000030; } - .btnContainer { - margin-top: 20px; - padding: 0px 10px; - display: flex; + margin-top: 20px; + padding: 0px 10px; + display: flex; } .btnCancel { - margin-left: 20px; + margin-left: 20px; } .loadingContainer { - display: flex; - align-items: center; - margin: 10px 0px; -} \ No newline at end of file + display: flex; + align-items: center; + margin: 10px 0px; +} + +.flex { + display: flex; + align-items: center; +} + +.flexBetween { + margin-top: 20px; + padding: 0px 10px; + display: flex; + justify-content: space-between; +} + +.configDoneContainer { + display: flex; + justify-content: center; + align-items: center; + padding: 40px; + border-radius: 10px; + flex-direction: row; + background-color: #fff; + margin-top: 10px; + border: 1px solid #f0f0f0; + box-shadow: 1px 2px #00000030; +} + +.configDoneIcon { + font-size: 50px; + color: green; +} + +.configDoneSuccessText { + margin-top: 10px; + font-weight: bold; + font-size: 20px; +} diff --git a/src/hooks/commons/useLoadDataElements.ts b/src/hooks/commons/useLoadDataElements.ts index 23bdc3a..6e7e4e7 100644 --- a/src/hooks/commons/useLoadDataElements.ts +++ b/src/hooks/commons/useLoadDataElements.ts @@ -55,7 +55,7 @@ export default function useLoadDataElements() { return { error, - dataElementsDatas: (data !== undefined && data !== null) + dataElementsDatas: data ? { ...data, dataElements: extractDataElements(data.programStages.programStages) diff --git a/src/hooks/staffs/useEnrollmentSubmit.ts b/src/hooks/staffs/useEnrollmentSubmit.ts index baa8f29..1a7d55d 100644 --- a/src/hooks/staffs/useEnrollmentSubmit.ts +++ b/src/hooks/staffs/useEnrollmentSubmit.ts @@ -11,7 +11,7 @@ export default function useEnrollmentSubmit() { const { mutate } = useUpdateConfigValues() const { show, hide } = useShowAlerts() - const submit = async (values: SubmitEnrollmentValue, dataStoreValues: any[], dataStoreConfigs: any[]) => { + const submit = async (values: SubmitEnrollmentValue, dataStoreValues: any[], dataStoreConfigs: any[], gotToNext?: any) => { try { setLoadingProcessing(true) let payload: any[] = [] @@ -78,6 +78,9 @@ export default function useEnrollmentSubmit() { } await mutate({ data: payload }) + if (gotToNext){ + gotToNext() + } setLoadingProcessing(false) show({ message: `Operation success !`, diff --git a/src/hooks/staffs/useSubmitProgramDatas.ts b/src/hooks/staffs/useSubmitProgramDatas.ts index ece0074..ec230dd 100644 --- a/src/hooks/staffs/useSubmitProgramDatas.ts +++ b/src/hooks/staffs/useSubmitProgramDatas.ts @@ -11,7 +11,7 @@ export default function useSubmitProgramDatas() { const { show, hide } = useShowAlerts() const { mutate } = useUpdateConfigValues() - const submit = async ({ data, program }: ProgramSubmitValueProps) => { + const submit = async ({ data, program, goToNext }: ProgramSubmitValueProps) => { try { if (program !== undefined) { setLoadingProcessing(true) @@ -45,6 +45,9 @@ export default function useSubmitProgramDatas() { } await mutate({ data: payload }) + if (goToNext) { + goToNext() + } setLoadingProcessing(false) show({ message: 'Operation Successfull !', diff --git a/src/hooks/students/useAttendanceSubmit.ts b/src/hooks/students/useAttendanceSubmit.ts index 2be8935..79784b6 100644 --- a/src/hooks/students/useAttendanceSubmit.ts +++ b/src/hooks/students/useAttendanceSubmit.ts @@ -22,11 +22,11 @@ export default function useAttendanceSubmit() { try { setLoadingProcessing(true) let payload: any[] = [] - + console.log("values : ", values) + if (values.absenceReason === null || values.absenceReason === undefined) { throw new Error("Absence Reason is required !") } - if (values.programStage === null || values.programStage === undefined) { throw new Error("Program stage is required !") } diff --git a/src/hooks/students/useFinalResultSubmit.ts b/src/hooks/students/useFinalResultSubmit.ts index d2a72e7..dd0398f 100644 --- a/src/hooks/students/useFinalResultSubmit.ts +++ b/src/hooks/students/useFinalResultSubmit.ts @@ -3,12 +3,13 @@ import dayjs from "dayjs"; import { getDataStoreElement } from "../../utils/functions"; import useUpdateConfigValues from '../commons/useUpdateConfigValues'; import useShowAlerts from '../commons/useShowAlert'; -import { SubmitFinalResultValue } from '../../types/students'; +import { type SubmitFinalResultValue } from '../../types/students'; interface SubmitFuctionProps { values: SubmitFinalResultValue dataStoreValues: any[] dataStoreConfigs: any[] + goToNext?: () => void } export default function useFinalResultSubmit() { @@ -16,11 +17,11 @@ export default function useFinalResultSubmit() { const { mutate } = useUpdateConfigValues() const { show, hide } = useShowAlerts() - const submit = async ({ dataStoreConfigs, dataStoreValues, values }: SubmitFuctionProps) => { + const submit = async ({ dataStoreConfigs, dataStoreValues, values, goToNext }: SubmitFuctionProps) => { try { setLoadingProcessing(true) let payload: any[] = [] - + if (values.programStage === null || values.programStage === undefined) { throw new Error("Program stage is required !") } @@ -64,6 +65,9 @@ export default function useFinalResultSubmit() { } await mutate({ data: payload }) + if (goToNext) { + goToNext() + } setLoadingProcessing(false) show({ message: `Operation success !`, diff --git a/src/hooks/students/useGetAttendanceFormFields.ts b/src/hooks/students/useGetAttendanceFormFields.ts index 6cdada0..3eaa68a 100644 --- a/src/hooks/students/useGetAttendanceFormFields.ts +++ b/src/hooks/students/useGetAttendanceFormFields.ts @@ -4,7 +4,7 @@ import { getDataStoreElement } from "../../utils/functions" interface FormFieldProps { programStages: any[] dataStoreConfigs: any[] - dataElements: any[] + dataElements: any[] getDataElements: (programStageId: string) => void } diff --git a/src/hooks/students/useGetFinalResultFormFields.ts b/src/hooks/students/useGetFinalResultFormFields.ts index 643f93b..0eeaef3 100644 --- a/src/hooks/students/useGetFinalResultFormFields.ts +++ b/src/hooks/students/useGetFinalResultFormFields.ts @@ -10,7 +10,7 @@ interface FormFieldProps { export default function useGetFinalResultFormFields() { const onProgramStageSelected = (value: any, getDataElements: (programStageId: string) => void) => { - if (getDataElements !== undefined && getDataElements !== null) { + if (getDataElements) { getDataElements(value.value) } } diff --git a/src/hooks/students/useGetTransferField.ts b/src/hooks/students/useGetTransferField.ts index 88d6c63..64b9a4f 100644 --- a/src/hooks/students/useGetTransferField.ts +++ b/src/hooks/students/useGetTransferField.ts @@ -9,7 +9,6 @@ interface FormFieldProps { } export default function useGetTransferField() { - const onProgramStageSelected = (value: any, getDataElements: (programStageId: string) => void) => { if (getDataElements !== undefined && getDataElements !== null) { getDataElements(value.value) @@ -150,7 +149,7 @@ export default function useGetTransferField() { } ) } - + if (penddingCode !== undefined && penddingCode !== null) { formFieldsList.push( { @@ -168,8 +167,8 @@ export default function useGetTransferField() { optionSet: { id: 'penddingCode', options: dataElements - .filter((dx: any) => dx.optionSetValue === penddingCode.optionSetValue && dx.valueType === penddingCode.valueType) - .flatMap((x: any) => x?.optionSet?.options) || [] + .filter((dx: any) => dx.optionSetValue === penddingCode.optionSetValue && dx.valueType === penddingCode.valueType) + .flatMap((x: any) => x?.optionSet?.options) || [] } } } @@ -193,8 +192,8 @@ export default function useGetTransferField() { optionSet: { id: 'approvedCode', options: dataElements - .filter((dx: any) => dx.optionSetValue === approvedCode.optionSetValue && dx.valueType === approvedCode.valueType) - .flatMap((x: any) => x?.optionSet?.options) || [] + .filter((dx: any) => dx.optionSetValue === approvedCode.optionSetValue && dx.valueType === approvedCode.valueType) + .flatMap((x: any) => x?.optionSet?.options) || [] } } } @@ -218,8 +217,8 @@ export default function useGetTransferField() { optionSet: { id: 'reprovedCode', options: dataElements - .filter((dx: any) => dx.optionSetValue === reprovedCode.optionSetValue && dx.valueType === reprovedCode.valueType) - .flatMap((x: any) => x?.optionSet?.options) || [] + .filter((dx: any) => dx.optionSetValue === reprovedCode.optionSetValue && dx.valueType === reprovedCode.valueType) + .flatMap((x: any) => x?.optionSet?.options) || [] } } } diff --git a/src/hooks/students/usePerformanceSubmit.ts b/src/hooks/students/usePerformanceSubmit.ts index 7b0fde1..23f6bfb 100644 --- a/src/hooks/students/usePerformanceSubmit.ts +++ b/src/hooks/students/usePerformanceSubmit.ts @@ -10,6 +10,7 @@ interface FormFieldProps { values: { programStages: any } dataStoreValues: any[] dataStoreConfigs: any[] + goToNext?: () => void } export default function usePerformanceSubmit() { @@ -17,7 +18,7 @@ export default function usePerformanceSubmit() { const { mutate } = useUpdateConfigValues() const { show, hide } = useShowAlerts() - const submit = async ({ dataStoreConfigs, values, dataStoreValues }: FormFieldProps) => { + const submit = async ({ dataStoreConfigs, values, dataStoreValues, goToNext }: FormFieldProps) => { try { if (values.programStages !== undefined) { setLoadingProcessing(true) @@ -56,7 +57,9 @@ export default function usePerformanceSubmit() { } await mutate({ data: payload }) - // refetch() + if (goToNext !== undefined) { + goToNext() + } setLoadingProcessing(false) show({ message: `Operation success !`, diff --git a/src/hooks/students/useTransferSubmit.ts b/src/hooks/students/useTransferSubmit.ts index 98d55c1..b6b190e 100644 --- a/src/hooks/students/useTransferSubmit.ts +++ b/src/hooks/students/useTransferSubmit.ts @@ -10,7 +10,7 @@ export default function useTransferSubmit() { const { mutate } = useUpdateConfigValues() const { show, hide } = useShowAlerts() - const submit = async (values: SubmitTransferValue, dataStoreValues: any[], dataStoreConfigs: any[]) => { + const submit = async (values: SubmitTransferValue, dataStoreValues: any[], dataStoreConfigs: any[], goToNext?: () => void) => { try { setLoadingProcessing(true) let payload: any[] = [] @@ -91,6 +91,9 @@ export default function useTransferSubmit() { } await mutate({ data: payload }) + if (goToNext) { + goToNext() + } setLoadingProcessing(false) show({ message: `Operation success !`, diff --git a/src/pages/staff/Staff_Wizard.tsx b/src/pages/staff/Staff_Wizard.tsx new file mode 100644 index 0000000..001e161 --- /dev/null +++ b/src/pages/staff/Staff_Wizard.tsx @@ -0,0 +1,12 @@ +import React from "react"; +import { Title, WithPadding } from "../../components"; +import { WizardForm } from "../../components/staffs"; + +export default function StaffWizard() { + return ( + <WithPadding> + <Title label="staff - Wizard" /> + <WizardForm /> + </WithPadding> + ) +} diff --git a/src/pages/staff/index.ts b/src/pages/staff/index.ts index fb08747..aec1b42 100644 --- a/src/pages/staff/index.ts +++ b/src/pages/staff/index.ts @@ -1,4 +1,5 @@ import StaffAttendance from "./Staff_AttendanceConfig"; import StaffEnrollment from "./Staff_EnrollmentConfig"; import StaffProgram from "./Staff_ProgramConfig"; -export { StaffAttendance, StaffEnrollment, StaffProgram} +import StaffWizard from "./Staff_Wizard"; +export { StaffAttendance, StaffEnrollment, StaffProgram, StaffWizard } diff --git a/src/types/table/AttributeColumns.ts b/src/types/table/AttributeColumns.ts index af42abf..1bcc47b 100644 --- a/src/types/table/AttributeColumns.ts +++ b/src/types/table/AttributeColumns.ts @@ -8,6 +8,7 @@ export interface CustomAttributeProps { required: string | boolean name: string labelName: string + defaultValue?: any description?: string valueType: typeof Attribute.valueType multiple?: boolean diff --git a/src/utils/constants/sideBar/sideBarData.ts b/src/utils/constants/sideBar/sideBarData.ts index 4e81d92..bf2c423 100644 --- a/src/utils/constants/sideBar/sideBarData.ts +++ b/src/utils/constants/sideBar/sideBarData.ts @@ -83,6 +83,12 @@ function sideBarData(): SideBarItemProps[] { { title: "Staff", subItems: [ + { + icon: settings, + label: "Wizard", + showBadge: false, + route: "/staffs/wizard" + }, { icon: settings, label: "Program", From d6effbc4e2bf5bdcaa2963049c6443d264d8d4ad Mon Sep 17 00:00:00 2001 From: Ibrahim <ikomna@hispwca.org> Date: Thu, 15 Aug 2024 18:43:24 +0000 Subject: [PATCH 3/4] Wizard staff page implementation continuation --- .../genericFields/fields/SingleSelect.tsx | 11 +- src/components/staffs/TransferForm.tsx | 67 +++-- src/components/staffs/TransferFormContent.tsx | 276 ++++++++++-------- src/components/staffs/WizardAttendance.tsx | 185 ++++-------- src/components/staffs/WizardConfigDone.tsx | 14 + src/components/staffs/WizardForm.tsx | 36 +-- src/components/staffs/WizardProgram.tsx | 23 +- src/components/staffs/WizardTransfer.tsx | 116 +++++--- src/components/students/WizardAttendance.tsx | 118 +++----- src/hooks/staffs/useAttendanceSubmit.ts | 6 +- src/hooks/staffs/useGetTransferField.ts | 21 +- src/hooks/staffs/useTransferSubmit.ts | 19 +- 12 files changed, 422 insertions(+), 470 deletions(-) create mode 100644 src/components/staffs/WizardConfigDone.tsx diff --git a/src/components/genericFields/fields/SingleSelect.tsx b/src/components/genericFields/fields/SingleSelect.tsx index acbab94..f5d4e0e 100644 --- a/src/components/genericFields/fields/SingleSelect.tsx +++ b/src/components/genericFields/fields/SingleSelect.tsx @@ -25,10 +25,6 @@ const OptionSetAutocomplete = (props: AutoCompleteProps) => { })) : [] - if (props?.defaultValue) { - input.onChange(props.defaultValue) - } - return ( <Autocomplete {...props} @@ -43,11 +39,8 @@ const OptionSetAutocomplete = (props: AutoCompleteProps) => { ? input.value.map((val: any) => options.find((element: { value: string }) => element.value === val) ) - : props?.defaultValue?.map((val: any) => - options.find((element: { value: string }) => element.value === val) - ) || [] - : options.find((element: { value: string }) => element.value === input.value) || - options.find((element: { value: string }) => element.value === props?.defaultValue) + : [] + : options.find((element: { value: string }) => element.value === input.value) } renderInput={(params: any) => ( <TextField diff --git a/src/components/staffs/TransferForm.tsx b/src/components/staffs/TransferForm.tsx index 3bfd70f..37484c1 100644 --- a/src/components/staffs/TransferForm.tsx +++ b/src/components/staffs/TransferForm.tsx @@ -1,18 +1,15 @@ -/* eslint-disable*/ - -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect } from 'react' import { NoticeBox } from '@dhis2/ui' -import { getDataStoreElement } from "../../utils/functions"; -import useLoadProgramStages from "../../hooks/commons/useLoadProgramStages"; -import useLoadDataElements from "../../hooks/commons/useLoadDataElements"; -import Loading from "../appList/Loading"; -import useLoadDataStoreDatas from "../../hooks/commons/useLoadDataStoreDatas"; -import EnrollmentFormContent from "./EnrollmentFormContent"; -import useGetTransferField from "../../hooks/staffs/useGetTransferField"; -import useTransferSubmit from "../../hooks/staffs/useTransferSubmit"; +import { getDataStoreElement } from '../../utils/functions' +import useLoadProgramStages from '../../hooks/commons/useLoadProgramStages' +import useLoadDataElements from '../../hooks/commons/useLoadDataElements' +import Loading from '../appList/Loading' +import useLoadDataStoreDatas from '../../hooks/commons/useLoadDataStoreDatas' +import useGetTransferField from '../../hooks/staffs/useGetTransferField' +import useTransferSubmit from '../../hooks/staffs/useTransferSubmit' +import TransferFormContent from './TransferFormContent' export default function TransferForm(): React.JSX.Element { - const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() const { getDataElements, dataElementsDatas } = useLoadDataElements() const { getFormFields } = useGetTransferField() @@ -23,16 +20,28 @@ export default function TransferForm(): React.JSX.Element { useEffect(() => { if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { setNoProgramErrorMessage(null) - const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "staff" }) - const programStageId = getDataStoreElement({ dataStores: data?.dataStoreValues, elementKey: "transfer", key: "staff" })?.programStage - const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "transfer", key: "staff" })?.programStage?.filter + const programId = getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'program', + key: 'staff' + }) + const programStageId = getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'transfer', + key: 'staff' + })?.programStage + const studentProgramFilterConfig = getDataStoreElement({ + dataStores: data?.dataStoreConfigs, + elementKey: 'transfer', + key: 'staff' + })?.programStage?.filter if (programId === undefined) { - setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") + setNoProgramErrorMessage('No programs have been configured. Please configure it before continuing !') } if (programId !== null && programId !== undefined) { - getProgramStages(programId,studentProgramFilterConfig) + getProgramStages(programId, studentProgramFilterConfig) } if (programStageId !== null && programStageId !== undefined) { getDataElements(programStageId) @@ -43,23 +52,17 @@ export default function TransferForm(): React.JSX.Element { return ( <> <Loading loadings={[loading, loadingProgramStages]} /> - { - (error !== undefined && (data === undefined || data === null)) && ( - <NoticeBox error> - {`${error.message}`} - </NoticeBox> - ) - } + {error !== undefined && (data === undefined || data === null) && ( + <NoticeBox error>{`${error.message}`}</NoticeBox> + )} - { - (noProgramErrorMessage !== undefined && noProgramErrorMessage !== null) && ( - <NoticeBox title="Configuration" warning> - {`${noProgramErrorMessage}`} - </NoticeBox> - ) - } + {noProgramErrorMessage !== undefined && noProgramErrorMessage !== null && ( + <NoticeBox title="Configuration" warning> + {`${noProgramErrorMessage}`} + </NoticeBox> + )} - <EnrollmentFormContent + <TransferFormContent data={data} dataElements={dataElementsDatas?.dataElements} programStages={programStagesDatas?.programStages} diff --git a/src/components/staffs/TransferFormContent.tsx b/src/components/staffs/TransferFormContent.tsx index c7e712f..c478124 100644 --- a/src/components/staffs/TransferFormContent.tsx +++ b/src/components/staffs/TransferFormContent.tsx @@ -1,148 +1,186 @@ - -import React from "react"; -import { GroupForm } from ".."; -import { Form } from "react-final-form" +import React from 'react' +import { GroupForm } from '..' +import { Form } from 'react-final-form' import { Button } from '@dhis2/ui' -import { getDataStoreElement } from "../../utils/functions"; +import { getDataStoreElement } from '../../utils/functions' import style from './ProgramForm.module.css' -import {type SubmitTransferValue } from "../../types/students"; - +import { type SubmitTransferValue } from '../../types/students' -export default function TransferFormContent( - { - data, - dataElements, - programStages, - getFormFields, - loadingProcessing, - submit, - getDataElements - }: { - data: { - dataStoreValues: any[] - dataStoreConfigs: any[] - } | undefined - programStages: any[] | undefined - dataElements: any[] | undefined - submit: any - getFormFields: any - loadingProcessing: boolean - getDataElements: any - } -): React.JSX.Element { +export default function TransferFormContent({ + data, + dataElements, + programStages, + getFormFields, + loadingProcessing, + submit, + getDataElements +}: { + data: + | { + dataStoreValues: any[] + dataStoreConfigs: any[] + } + | undefined + programStages: any[] | undefined + dataElements: any[] | undefined + submit: any + getFormFields: any + loadingProcessing: boolean + getDataElements: any +}): React.JSX.Element { return ( <> - { - data !== undefined && data !== null && - getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.programStage !== null && - getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.programStage !== undefined && - (programStages !== undefined && programStages !== null && programStages.length > 0) && - (dataElements !== undefined && dataElements !== null && dataElements.length > 0) && - ( + {data !== undefined && + data !== null && + getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: 'transfer', key: 'staff' }) + ?.programStage !== null && + getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: 'transfer', key: 'staff' }) + ?.programStage !== undefined && + programStages !== undefined && + programStages !== null && + programStages.length > 0 && + dataElements !== undefined && + dataElements !== null && + dataElements.length > 0 && ( <div> <Form onSubmit={async (value: SubmitTransferValue) => { await submit(value, data.dataStoreValues, data.dataStoreConfigs) }} initialValues={{ - programStage: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.programStage, - originSchool: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.originSchool, - destinySchool: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.destinySchool, - status: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.status, - reason: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.reason + programStage: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'staff' + })?.programStage, + originSchool: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'staff' + })?.originSchool, + destinySchool: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'staff' + })?.destinySchool, + status: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'staff' + })?.status, + reason: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'staff' + })?.reason }} - render={ - ({ handleSubmit, form }: any) => { - const handleCancel = () => { - // form.change("programStage", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.programStage) - // form.change("originSchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.originSchool) - // form.change("destinySchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.destinySchool) - // form.change("status", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.status) - } + render={({ handleSubmit, form }: any) => { + const handleCancel = () => { + // form.change("programStage", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.programStage) + // form.change("originSchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.originSchool) + // form.change("destinySchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.destinySchool) + // form.change("status", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.status) + } - return ( - <div> - <form onSubmit={handleSubmit}> - <GroupForm - disabled={false} - name="Enrollment" - fields={ - getFormFields({ - dataStoreConfigs: data.dataStoreConfigs, - programStages: (programStages !== undefined && programStages !== null) - ? programStages - : [], - getDataElements, - dataElements: (dataElements !== undefined && dataElements !== null) - ? dataElements - : [] - })} - /> - <div className={style.btnContainer}> - <div><Button type="submit" primary loading={loadingProcessing}>Save</Button></div> - <div className={style.btnCancel}><Button onClick={handleCancel} disabled type="button">Cancel</Button></div> + return ( + <div> + <form onSubmit={handleSubmit}> + <GroupForm + disabled={false} + name="Enrollment" + fields={getFormFields({ + dataStoreConfigs: data.dataStoreConfigs, + programStages: + programStages !== undefined && programStages !== null + ? programStages + : [], + getDataElements, + dataElements: + dataElements !== undefined && dataElements !== null + ? dataElements + : [] + })} + /> + <div className={style.btnContainer}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> </div> - </form> - </div> - ) - } - } + <div className={style.btnCancel}> + <Button onClick={handleCancel} disabled type="button"> + Cancel + </Button> + </div> + </div> + </form> + </div> + ) + }} /> </div> - ) - } + )} - { - data !== undefined && data !== null && - (getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.programStage === null || - getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.programStage === undefined) && - (programStages !== undefined && programStages !== null && programStages.length > 0) && - ( + {data !== undefined && + data !== null && + (getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: 'transfer', key: 'staff' }) + ?.programStage === null || + getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: 'transfer', key: 'staff' }) + ?.programStage === undefined) && + programStages !== undefined && + programStages !== null && + programStages.length > 0 && ( <div> <Form onSubmit={async (value: SubmitTransferValue) => { await submit(value, data.dataStoreValues, data.dataStoreConfigs) }} - render={ - ({ handleSubmit, form }: any) => { - const handleCancel = () => { - // form.change("programStage", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.programStage) - // form.change("originSchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.originSchool) - // form.change("destinySchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.destinySchool) - // form.change("status", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.status) - } + render={({ handleSubmit, form }: any) => { + const handleCancel = () => { + // form.change("programStage", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.programStage) + // form.change("originSchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.originSchool) + // form.change("destinySchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.destinySchool) + // form.change("status", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "staff" })?.status) + } - return ( - <div> - <form onSubmit={handleSubmit}> - <GroupForm - disabled={false} - name="Enrollment" - fields={ - getFormFields({ - dataStoreConfigs: data.dataStoreConfigs, - programStages: (programStages !== undefined && programStages !== null) - ? programStages - : [], - getDataElements, - dataElements: (dataElements !== undefined && dataElements !== null) - ? dataElements - : [] - })} - /> - <div className={style.btnContainer}> - <div><Button type="submit" primary loading={loadingProcessing}>Save</Button></div> - <div className={style.btnCancel}><Button disabled onClick={handleCancel} type="button">Cancel</Button></div> + return ( + <div> + <form onSubmit={handleSubmit}> + <GroupForm + disabled={false} + name="Enrollment" + fields={getFormFields({ + dataStoreConfigs: data.dataStoreConfigs, + programStages: + programStages !== undefined && programStages !== null + ? programStages + : [], + getDataElements, + dataElements: + dataElements !== undefined && dataElements !== null + ? dataElements + : [] + })} + /> + <div className={style.btnContainer}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> </div> - </form> - </div> - ) - } - } + <div className={style.btnCancel}> + <Button disabled onClick={handleCancel} type="button"> + Cancel + </Button> + </div> + </div> + </form> + </div> + ) + }} /> </div> - ) - } + )} </> ) } diff --git a/src/components/staffs/WizardAttendance.tsx b/src/components/staffs/WizardAttendance.tsx index cce1e45..1e93e0d 100644 --- a/src/components/staffs/WizardAttendance.tsx +++ b/src/components/staffs/WizardAttendance.tsx @@ -1,17 +1,11 @@ import React, { useState, useEffect } from 'react' import { NoticeBox, Button } from '@dhis2/ui' import { getDataStoreElement } from '../../utils/functions' -import { useGetAttendanceFormFields } from '../../hooks/students' import useLoadProgramStages from '../../hooks/commons/useLoadProgramStages' import useLoadDataElements from '../../hooks/commons/useLoadDataElements' -import { - type SubmitAttendanceValue, - type LoadDataElementsResponse, - type UseFetchEnrollmentDatasResponse -} from '../../types/students' import Loading from '../appList/Loading' import useLoadDataStoreDatas from '../../hooks/commons/useLoadDataStoreDatas' -import useAttendanceSubmit from '../../hooks/students/useAttendanceSubmit' +import { useAttendanceSubmit, useGetAttendanceFormFields } from '../../hooks/staffs' import style from './index.module.css' import { Form } from 'react-final-form' @@ -24,10 +18,10 @@ interface WizardPageProps { export default function WizardAttendance({ setWizardSetp }: WizardPageProps) { const [noProgramErrorMessage, setNoProgramErrorMessage] = useState<any>() - const { getDataElements, dataElementsDatas }: LoadDataElementsResponse = useLoadDataElements() + const { getDataElements, dataElementsDatas }: any = useLoadDataElements() const { getFormFields } = useGetAttendanceFormFields() - const { loadingProgramStages, programStagesDatas, getProgramStages } = useLoadProgramStages() - const { data, loading, error }: UseFetchEnrollmentDatasResponse = useLoadDataStoreDatas() + const { loadingProgramStages, programStagesDatas, getProgramStages }: any = useLoadProgramStages() + const { data, loading, error }: any = useLoadDataStoreDatas() const { submit, loadingProcessing } = useAttendanceSubmit() useEffect(() => { @@ -36,24 +30,24 @@ export default function WizardAttendance({ setWizardSetp }: WizardPageProps) { const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: 'program', - key: 'student' + key: 'staff' }) const programStageId = getDataStoreElement({ dataStores: data?.dataStoreValues, elementKey: 'attendance', - key: 'student' + key: 'staff' })?.programStage - const studentProgramFilterConfig = getDataStoreElement({ + const staffProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: 'attendance', - key: 'student' + key: 'staff' })?.programStage?.filter if (programId === undefined) { setNoProgramErrorMessage('No programs have been configured. Please configure it before continuing !') } if (programId !== null && programId !== undefined) { - void getProgramStages(programId, studentProgramFilterConfig) + getProgramStages(programId, staffProgramFilterConfig) } if (programStageId !== null && programStageId !== undefined) { getDataElements(programStageId) @@ -79,16 +73,53 @@ export default function WizardAttendance({ setWizardSetp }: WizardPageProps) { {data && ( <div> <Form - onSubmit={async (values: SubmitAttendanceValue) => { + onSubmit={async (values: any) => { await submit({ values, dataStoreValues: data.dataStoreValues, dataStoreConfigs: data.dataStoreConfigs, goToNext: () => { - setWizardSetp(4) + setWizardSetp(3) } }) }} + initialValues={{ + programStage: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'staff' + })?.programStage, + absenceReason: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'staff' + })?.absenceReason, + status: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'staff' + })?.status, + absentCode: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'staff' + })?.statusOptions?.find((x: any) => x.key === 'absent')?.code, + presentCode: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'staff' + })?.statusOptions?.find((x: any) => x.key === 'present')?.code, + lateCode: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'staff' + })?.statusOptions?.find((x: any) => x.key === 'late')?.code, + leaveCode: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'staff' + })?.statusOptions?.find((x: any) => x.key === 'leave')?.code + }} render={({ handleSubmit }: any) => { return ( programStagesDatas?.programStages?.length > 0 && ( @@ -98,95 +129,9 @@ export default function WizardAttendance({ setWizardSetp }: WizardPageProps) { name="Attendance" fields={getFormFields({ dataStoreConfigs: data.dataStoreConfigs, - programStages: programStagesDatas.programStages, + programStages: programStagesDatas?.programStages || [], getDataElements, - dataElements: - dataElementsDatas?.dataElements !== undefined && - dataElementsDatas?.dataElements !== null && - dataElementsDatas?.dataElements?.length > 0 - ? dataElementsDatas?.dataElements - : [] - }).map((p) => { - if (p.name === 'programStage') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.programStage - } - } - - if (p.name === 'absenceReason') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.absenceReason - } - } - - if (p.name === 'status') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.status - } - } - - if (p.name === 'absentCode') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.statusOptions?.find((x: any) => x.key === 'absent') - ?.code - } - } - - if (p.name === 'presentCode') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.statusOptions?.find((x: any) => x.key === 'present') - ?.code - } - } - - if (p.name === 'lateCode') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.statusOptions?.find((x: any) => x.key === 'late')?.code - } - } - - if (p.name === 'leaveCode') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.statusOptions?.find((x: any) => x.key === 'leave')?.code - } - } - - return p + dataElements: dataElementsDatas?.dataElements || [] })} /> <div className={style.flexBetween}> @@ -205,43 +150,23 @@ export default function WizardAttendance({ setWizardSetp }: WizardPageProps) { {getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: 'attendance', - key: 'student' + key: 'staff' })?.programStage && getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: 'attendance', - key: 'student' + key: 'staff' })?.absenceReason && getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: 'attendance', - key: 'student' - })?.status && - getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.statusOptions?.find((x: any) => x.key === 'absent')?.code && - getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.statusOptions?.find((x: any) => x.key === 'present')?.code && - getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.statusOptions?.find((x: any) => x.key === 'late')?.code && - getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.statusOptions?.find((x: any) => x.key === 'leave')?.code && ( + key: 'staff' + })?.status && ( <div> <Button primary onClick={() => { - setWizardSetp(4) + setWizardSetp(3) }} > <IoIosArrowRoundForward style={{ fontSize: '20px' }} /> diff --git a/src/components/staffs/WizardConfigDone.tsx b/src/components/staffs/WizardConfigDone.tsx new file mode 100644 index 0000000..b76de0c --- /dev/null +++ b/src/components/staffs/WizardConfigDone.tsx @@ -0,0 +1,14 @@ +import React from 'react' +import { IoCheckmarkDoneCircle } from 'react-icons/io5' +import style from './index.module.css' + +export default function WizardConfigDone() { + return ( + <> + <div className={style.configDoneContainer}> + <IoCheckmarkDoneCircle className={style.configDoneIcon} /> + <div className={style.configDoneSuccessText}>Configuration Done with Success</div> + </div> + </> + ) +} diff --git a/src/components/staffs/WizardForm.tsx b/src/components/staffs/WizardForm.tsx index 4e9f4ad..4987c64 100644 --- a/src/components/staffs/WizardForm.tsx +++ b/src/components/staffs/WizardForm.tsx @@ -1,21 +1,12 @@ import React, { useState } from 'react' import { Stepper, Step } from 'react-form-stepper' -// import WizardProgram from "./WizardProgram"; import WizardEnrollment from './WizardEnrollment' import WizardProgram from './WizardProgram' -// import WizardSocioEconomics from "./WizardSocioEconomics"; -// import WizardAttendance from "./WizardAttendance"; -// import WizardPerformance from "./WizardPerformance"; -// import WizardFinalResult from "./WizardFinalResult"; -// import WizardTransfer from "./WizardTransfer"; -// import WizardConfigDone from "./WizardConfigDone"; +import WizardAttendance from './WizardAttendance' +import WizardTransfer from './WizardTransfer' +import WizardConfigDone from './WizardConfigDone' -const steps = [ - { label: 'Program' }, - { label: 'Staff registry' }, - { label: 'Attendance' }, - { label: 'Transfer' } -] +const steps = [{ label: 'Program' }, { label: 'Staff registry' }, { label: 'Attendance' }, { label: 'Transfer' }] export default function WizardForm() { const [wizardStep, setWizardSetp] = useState(0) @@ -26,18 +17,13 @@ export default function WizardForm() { return <WizardProgram setWizardSetp={setWizardSetp} /> case 1: return <WizardEnrollment setWizardSetp={setWizardSetp} /> - // case 2: - // return <WizardSocioEconomics setWizardSetp={setWizardSetp} /> - // case 3: - // return <WizardAttendance setWizardSetp={setWizardSetp} /> - // case 4: - // return <WizardPerformance setWizardSetp={setWizardSetp} /> - // case 5: - // return <WizardFinalResult setWizardSetp={setWizardSetp} /> - // case 6: - // return <WizardTransfer setWizardSetp={setWizardSetp} /> - // case 7: - // return <WizardConfigDone /> + case 2: + return <WizardAttendance setWizardSetp={setWizardSetp} /> + case 3: + return <WizardTransfer setWizardSetp={setWizardSetp} /> + case 4: + return <WizardConfigDone /> + default: return <></> } diff --git a/src/components/staffs/WizardProgram.tsx b/src/components/staffs/WizardProgram.tsx index 2af8754..65769c4 100644 --- a/src/components/staffs/WizardProgram.tsx +++ b/src/components/staffs/WizardProgram.tsx @@ -31,6 +31,13 @@ export default function WizardProgram({ setWizardSetp }: WizardPageProps) { {data !== undefined && data !== null && ( <div> <Form + initialValues={{ + program: getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'program', + key: 'staff' + }) + }} onSubmit={(values: { program: string }) => { submit({ data, @@ -50,15 +57,6 @@ export default function WizardProgram({ setWizardSetp }: WizardPageProps) { fields={getFormFields({ programs: data.programs, data - }).map((p) => { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data?.dataStoreValues, - elementKey: 'program', - key: 'staff' - }) - } })} /> <div className={style.flexBetween}> @@ -74,9 +72,10 @@ export default function WizardProgram({ setWizardSetp }: WizardPageProps) { </Button> </div> </div> - {getFormFields({ - programs: data.programs, - data + {getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'program', + key: 'staff' })?.length > 0 && ( <div> <Button diff --git a/src/components/staffs/WizardTransfer.tsx b/src/components/staffs/WizardTransfer.tsx index 3a85a87..421b257 100644 --- a/src/components/staffs/WizardTransfer.tsx +++ b/src/components/staffs/WizardTransfer.tsx @@ -3,15 +3,16 @@ import { NoticeBox, Button } from '@dhis2/ui' import { getDataStoreElement } from '../../utils/functions' import useLoadProgramStages from '../../hooks/commons/useLoadProgramStages' import useLoadDataElements from '../../hooks/commons/useLoadDataElements' -import useLoadDataStoreDatas from '../../hooks/commons/useLoadDataStoreDatas' import Loading from '../appList/Loading' -import useGetTransferField from '../../hooks/students/useGetTransferField' -import useTransferSubmit from '../../hooks/students/useTransferSubmit' +import useLoadDataStoreDatas from '../../hooks/commons/useLoadDataStoreDatas' +import useGetTransferField from '../../hooks/staffs/useGetTransferField' +import useTransferSubmit from '../../hooks/staffs/useTransferSubmit' import style from './index.module.css' import { Form } from 'react-final-form' import { GroupForm } from '..' import { type SubmitTransferValue } from '../../types/students' +import { IoIosArrowRoundForward } from 'react-icons/io' interface WizardPageProps { setWizardSetp: React.Dispatch<React.SetStateAction<number>> @@ -26,27 +27,23 @@ export default function WizardTransfer({ setWizardSetp }: WizardPageProps) { const { data, loading, error } = useLoadDataStoreDatas() useEffect(() => { - if ( - data?.dataStoreValues !== undefined && - data?.dataStoreValues !== null && - data?.dataStoreConfigs !== null && - data?.dataStoreConfigs !== undefined - ) { + if (data?.dataStoreValues !== undefined && data?.dataStoreValues !== null) { setNoProgramErrorMessage(null) const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: 'program', - key: 'student' + key: 'staff' }) const programStageId = getDataStoreElement({ dataStores: data?.dataStoreValues, elementKey: 'transfer', - key: 'student' + key: 'staff' })?.programStage + const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: 'transfer', - key: 'student' + key: 'staff' })?.programStage?.filter if (programId === undefined) { @@ -56,6 +53,7 @@ export default function WizardTransfer({ setWizardSetp }: WizardPageProps) { if (programId !== null && programId !== undefined) { getProgramStages(programId, studentProgramFilterConfig) } + console.log('programStageId', programStageId) if (programStageId !== null && programStageId !== undefined) { getDataElements(programStageId) } @@ -83,69 +81,103 @@ export default function WizardTransfer({ setWizardSetp }: WizardPageProps) { <Form onSubmit={async (value: SubmitTransferValue) => { await submit(value, data.dataStoreValues, data.dataStoreConfigs, () => { - setWizardSetp(7) + setWizardSetp(4) }) }} initialValues={{ programStage: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: 'transfer', - key: 'student' + key: 'staff' })?.programStage, - destinySchool: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'transfer', - key: 'student' - })?.destinySchool, originSchool: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: 'transfer', - key: 'student' + key: 'staff' })?.originSchool, + destinySchool: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'staff' + })?.destinySchool, status: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: 'transfer', - key: 'student' + key: 'staff' })?.status, reason: getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: 'transfer', - key: 'student' + key: 'staff' })?.reason }} - render={({ handleSubmit, form }: any) => { - const handleCancel = () => { - // form.change("programStage", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.programStage) - // form.change("destinySchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.destinySchool) - // form.change("originSchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.originSchool) - // form.change("status", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.status) - } - + render={({ handleSubmit }: any) => { return ( programStagesDatas?.programStages?.length > 0 && ( <div> <form onSubmit={handleSubmit}> <GroupForm disabled={false} - name="transfer" + name="Enrollment" fields={getFormFields({ dataStoreConfigs: data.dataStoreConfigs, - programStages: programStagesDatas.programStages, + programStages: programStagesDatas?.programStages || [], getDataElements, dataElements: dataElementsDatas?.dataElements || [] })} /> - <div className={style.btnContainer}> - <div> - <Button type="submit" primary loading={loadingProcessing}> - Save - </Button> - </div> - <div className={style.btnCancel}> - <Button disabled onClick={handleCancel} type="button"> - Cancel - </Button> + <div className={style.flexBetween}> + <div className={style.flex}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> + </div> + <div className={style.btnCancel}> + <Button disabled type="button"> + Cancel + </Button> + </div> </div> + {getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'staff' + })?.programStage && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'staff' + })?.originSchool && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'staff' + })?.destinySchool && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'staff' + })?.status && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'staff' + })?.reason && ( + <div> + <Button + primary + onClick={() => { + setWizardSetp(4) + }} + > + <IoIosArrowRoundForward + style={{ fontSize: '20px' }} + /> + Next + </Button> + </div> + )} </div> </form> </div> diff --git a/src/components/students/WizardAttendance.tsx b/src/components/students/WizardAttendance.tsx index cce1e45..d16222a 100644 --- a/src/components/students/WizardAttendance.tsx +++ b/src/components/students/WizardAttendance.tsx @@ -79,6 +79,43 @@ export default function WizardAttendance({ setWizardSetp }: WizardPageProps) { {data && ( <div> <Form + initialValues={{ + programStage: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.programStage, + absenceReason: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.absenceReason, + status: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.status, + absentCode: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'absent')?.code, + presentCode: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'present')?.code, + lateCode: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'late')?.code, + leaveCode: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'attendance', + key: 'student' + })?.statusOptions?.find((x: any) => x.key === 'leave')?.code + }} onSubmit={async (values: SubmitAttendanceValue) => { await submit({ values, @@ -106,87 +143,6 @@ export default function WizardAttendance({ setWizardSetp }: WizardPageProps) { dataElementsDatas?.dataElements?.length > 0 ? dataElementsDatas?.dataElements : [] - }).map((p) => { - if (p.name === 'programStage') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.programStage - } - } - - if (p.name === 'absenceReason') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.absenceReason - } - } - - if (p.name === 'status') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.status - } - } - - if (p.name === 'absentCode') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.statusOptions?.find((x: any) => x.key === 'absent') - ?.code - } - } - - if (p.name === 'presentCode') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.statusOptions?.find((x: any) => x.key === 'present') - ?.code - } - } - - if (p.name === 'lateCode') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.statusOptions?.find((x: any) => x.key === 'late')?.code - } - } - - if (p.name === 'leaveCode') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'attendance', - key: 'student' - })?.statusOptions?.find((x: any) => x.key === 'leave')?.code - } - } - - return p })} /> <div className={style.flexBetween}> diff --git a/src/hooks/staffs/useAttendanceSubmit.ts b/src/hooks/staffs/useAttendanceSubmit.ts index 3ac387f..9d2d645 100644 --- a/src/hooks/staffs/useAttendanceSubmit.ts +++ b/src/hooks/staffs/useAttendanceSubmit.ts @@ -10,6 +10,7 @@ interface SubmitFuctionProps { values: SubmitAttendanceValue dataStoreValues: any[] dataStoreConfigs: any[] + goToNext?: () => void } export default function useAttendanceSubmit() { @@ -17,7 +18,7 @@ export default function useAttendanceSubmit() { const { mutate } = useUpdateConfigValues() const { show, hide } = useShowAlerts() - const submit = async ({ dataStoreConfigs, dataStoreValues, values }: SubmitFuctionProps) => { + const submit = async ({ dataStoreConfigs, dataStoreValues, values, goToNext }: SubmitFuctionProps) => { try { setLoadingProcessing(true) let payload: any[] = [] @@ -99,6 +100,9 @@ export default function useAttendanceSubmit() { } await mutate({ data: payload }) + if (goToNext) { + goToNext() + } setLoadingProcessing(false) show({ message: `Operation success !`, diff --git a/src/hooks/staffs/useGetTransferField.ts b/src/hooks/staffs/useGetTransferField.ts index c3807e2..ff6e262 100644 --- a/src/hooks/staffs/useGetTransferField.ts +++ b/src/hooks/staffs/useGetTransferField.ts @@ -8,9 +8,7 @@ interface FormFieldProps { getDataElements: (programStageId: string) => void } - export default function useGetTransferField() { - const onProgramStageSelected = (value: any, getDataElements: (programStageId: string) => void) => { if (getDataElements !== undefined && getDataElements !== null) { getDataElements(value.value) @@ -28,6 +26,10 @@ export default function useGetTransferField() { const approvedCode = getDataStoreElement({ dataStores: dataStoreConfigs, key: "staff", elementKey: "transfer" })?.approvedCode const reprovedCode = getDataStoreElement({ dataStores: dataStoreConfigs, key: "staff", elementKey: "transfer" })?.reprovedCode + console.log("dataElements: ", dataElements) + console.log("programStages: ", programStages) + console.log("foundProgramStage: ", foundProgramStage) + if (foundProgramStage !== undefined && foundProgramStage !== null) { formFieldsList.push( { @@ -152,7 +154,6 @@ export default function useGetTransferField() { ) } - if (penddingCode !== undefined && penddingCode !== null) { formFieldsList.push( { @@ -170,8 +171,8 @@ export default function useGetTransferField() { optionSet: { id: 'penddingCode', options: dataElements - .filter((dx: any) => dx.optionSetValue === penddingCode.optionSetValue && dx.valueType === penddingCode.valueType) - .flatMap((x: any) => x?.optionSet?.options) || [] + .filter((dx: any) => dx.optionSetValue === penddingCode.optionSetValue && dx.valueType === penddingCode.valueType) + .flatMap((x: any) => x?.optionSet?.options) || [] } } } @@ -195,8 +196,8 @@ export default function useGetTransferField() { optionSet: { id: 'approvedCode', options: dataElements - .filter((dx: any) => dx.optionSetValue === approvedCode.optionSetValue && dx.valueType === approvedCode.valueType) - .flatMap((x: any) => x?.optionSet?.options) || [] + .filter((dx: any) => dx.optionSetValue === approvedCode.optionSetValue && dx.valueType === approvedCode.valueType) + .flatMap((x: any) => x?.optionSet?.options) || [] } } } @@ -220,8 +221,8 @@ export default function useGetTransferField() { optionSet: { id: 'reprovedCode', options: dataElements - .filter((dx: any) => dx.optionSetValue === reprovedCode.optionSetValue && dx.valueType === reprovedCode.valueType) - .flatMap((x: any) => x?.optionSet?.options) || [] + .filter((dx: any) => dx.optionSetValue === reprovedCode.optionSetValue && dx.valueType === reprovedCode.valueType) + .flatMap((x: any) => x?.optionSet?.options) || [] } } } @@ -230,7 +231,5 @@ export default function useGetTransferField() { return formFieldsList } - return { getFormFields } - } diff --git a/src/hooks/staffs/useTransferSubmit.ts b/src/hooks/staffs/useTransferSubmit.ts index c6dabd7..6e7d216 100644 --- a/src/hooks/staffs/useTransferSubmit.ts +++ b/src/hooks/staffs/useTransferSubmit.ts @@ -1,7 +1,7 @@ import { useState } from 'react' import dayjs from "dayjs"; import { getDataStoreElement } from "../../utils/functions"; -import {type SubmitTransferValue } from "../../types/students"; +import { type SubmitTransferValue } from "../../types/students"; import useUpdateConfigValues from '../commons/useUpdateConfigValues'; import useShowAlerts from '../commons/useShowAlert'; @@ -10,7 +10,7 @@ export default function useTransferSubmit() { const { mutate } = useUpdateConfigValues() const { show, hide } = useShowAlerts() - const submit = async (values: SubmitTransferValue, dataStoreValues: any[], dataStoreConfigs: any[]) => { + const submit = async (values: SubmitTransferValue, dataStoreValues: any[], dataStoreConfigs: any[], goToNext: any) => { try { setLoadingProcessing(true) let payload: any[] = [] @@ -39,16 +39,16 @@ export default function useTransferSubmit() { const statusValues = [ { - "code": values.penddingCode, - "key": "pending" + code: values.penddingCode, + key: "pending" }, { - "code": values.approvedCode, - "key": "approved" + code: values.approvedCode, + key: "approved" }, { - "code": values.reprovedCode, - "key": "reproved" + code: values.reprovedCode, + key: "reproved" } ] @@ -91,6 +91,9 @@ export default function useTransferSubmit() { } await mutate({ data: payload }) + if (goToNext) { + goToNext() + } setLoadingProcessing(false) show({ message: `Operation success !`, From 251c0d1ce5c2f55b4567794b1ba1a1e128366b5a Mon Sep 17 00:00:00 2001 From: Ibrahim <ikomna@hispwca.org> Date: Fri, 16 Aug 2024 09:22:24 +0000 Subject: [PATCH 4/4] Update on Student and Staff wizard page --- .../genericFields/fields/SingleSelect.tsx | 3 +- src/components/staffs/AttendanceForm.tsx | 4 +- src/components/staffs/EnrollmentForm.tsx | 4 +- src/components/staffs/TransferForm.tsx | 4 +- src/components/students/WizardEnrollment.tsx | 64 ++++++----------- src/components/students/WizardFinalResult.tsx | 47 +++++++++---- src/components/students/WizardProgram.tsx | 16 ++--- .../students/WizardSocioEconomics.tsx | 23 +++---- src/components/students/WizardTransfer.tsx | 69 ++++++++++++++----- 9 files changed, 131 insertions(+), 103 deletions(-) diff --git a/src/components/genericFields/fields/SingleSelect.tsx b/src/components/genericFields/fields/SingleSelect.tsx index f5d4e0e..562aedb 100644 --- a/src/components/genericFields/fields/SingleSelect.tsx +++ b/src/components/genericFields/fields/SingleSelect.tsx @@ -19,7 +19,7 @@ const OptionSetAutocomplete = (props: AutoCompleteProps) => { const options = props?.options?.optionSet?.options != null - ? props?.options.optionSet?.options.map((option: { value: string; label: string }) => ({ + ? props?.options.optionSet?.options.map((option: { value: string, label: string }) => ({ value: option?.value, label: option?.label })) @@ -59,7 +59,6 @@ const OptionSetAutocomplete = (props: AutoCompleteProps) => { /> )} onChange={(_, value: any) => { - console.log('onchange value: ', value) input.onChange( props.multiple !== undefined && props.multiple !== null && Boolean(props.multiple) ? value?.length > 0 diff --git a/src/components/staffs/AttendanceForm.tsx b/src/components/staffs/AttendanceForm.tsx index 4417146..e2a2807 100644 --- a/src/components/staffs/AttendanceForm.tsx +++ b/src/components/staffs/AttendanceForm.tsx @@ -22,13 +22,13 @@ export default function AttendanceForm(): React.JSX.Element { setNoProgramErrorMessage(null) const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "staff" }) const programStageId = getDataStoreElement({ dataStores: data?.dataStoreValues, elementKey: "attendance", key: "staff" })?.programStage - const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "attendance", key: "staff" })?.programStage?.filter + const staffProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "attendance", key: "staff" })?.programStage?.filter if (programId === undefined) { setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") } if (programId !== null && programId !== undefined) { - getProgramStages(programId, studentProgramFilterConfig) + getProgramStages(programId, staffProgramFilterConfig) } if (programStageId !== null && programStageId !== undefined) { getDataElements(programStageId) diff --git a/src/components/staffs/EnrollmentForm.tsx b/src/components/staffs/EnrollmentForm.tsx index 4d6197b..3d0e36c 100644 --- a/src/components/staffs/EnrollmentForm.tsx +++ b/src/components/staffs/EnrollmentForm.tsx @@ -23,14 +23,14 @@ export default function EnrollmentForm(): React.JSX.Element { setNoProgramErrorMessage(null) const programId = getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "program", key: "staff" }) const programStageId = getDataStoreElement({ dataStores: data?.dataStoreValues, elementKey: "registration", key: "staff" })?.programStage - const studentProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "registration", key: "staff" })?.programStage?.filter + const staffProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: "registration", key: "staff" })?.programStage?.filter if (programId === undefined) { setNoProgramErrorMessage("No programs have been configured. Please configure it before continuing !") } if (programId !== null && programId !== undefined) { - getProgramStages(programId,studentProgramFilterConfig) + getProgramStages(programId,staffProgramFilterConfig) } if (programStageId !== null && programStageId !== undefined) { getDataElements(programStageId) diff --git a/src/components/staffs/TransferForm.tsx b/src/components/staffs/TransferForm.tsx index 37484c1..bd3a74b 100644 --- a/src/components/staffs/TransferForm.tsx +++ b/src/components/staffs/TransferForm.tsx @@ -30,7 +30,7 @@ export default function TransferForm(): React.JSX.Element { elementKey: 'transfer', key: 'staff' })?.programStage - const studentProgramFilterConfig = getDataStoreElement({ + const staffProgramFilterConfig = getDataStoreElement({ dataStores: data?.dataStoreConfigs, elementKey: 'transfer', key: 'staff' @@ -41,7 +41,7 @@ export default function TransferForm(): React.JSX.Element { } if (programId !== null && programId !== undefined) { - getProgramStages(programId, studentProgramFilterConfig) + getProgramStages(programId, staffProgramFilterConfig) } if (programStageId !== null && programStageId !== undefined) { getDataElements(programStageId) diff --git a/src/components/students/WizardEnrollment.tsx b/src/components/students/WizardEnrollment.tsx index 56dd399..0e0e136 100644 --- a/src/components/students/WizardEnrollment.tsx +++ b/src/components/students/WizardEnrollment.tsx @@ -76,6 +76,28 @@ export default function WizardEnrollment({ setWizardSetp }: WizardPageProps) { {data !== undefined && data !== null && ( <div> <Form + initialValues={{ + programStage: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'student' + })?.programStage, + grade: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'student' + })?.grade, + section: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'student' + })?.section, + academicYear: getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'registration', + key: 'student' + })?.academicYear + }} onSubmit={async (value: SubmitEnrollmentValue) => { await submit(value, data.dataStoreValues, data.dataStoreConfigs, () => { setWizardSetp(2) @@ -97,48 +119,6 @@ export default function WizardEnrollment({ setWizardSetp }: WizardPageProps) { dataElementsDatas?.dataElements !== null ? dataElementsDatas?.dataElements : [] - }).map((p) => { - if (p.name === 'programStage') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'registration', - key: 'student' - })?.programStage - } - } - if (p.name === 'grade') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'registration', - key: 'student' - })?.grade - } - } - if (p.name === 'section') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'registration', - key: 'student' - })?.section - } - } - if (p.name === 'academicYear') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data.dataStoreValues, - elementKey: 'registration', - key: 'student' - })?.academicYear - } - } - return p })} /> <div className={style.flexBetween}> diff --git a/src/components/students/WizardFinalResult.tsx b/src/components/students/WizardFinalResult.tsx index edcf4a4..01d27d6 100644 --- a/src/components/students/WizardFinalResult.tsx +++ b/src/components/students/WizardFinalResult.tsx @@ -12,6 +12,7 @@ import useFinalResultSubmit from '../../hooks/students/useFinalResultSubmit' import style from './index.module.css' import { Form } from 'react-final-form' import { GroupForm } from '..' +import { IoIosArrowRoundForward } from 'react-icons/io' interface WizardPageProps { setWizardSetp: React.Dispatch<React.SetStateAction<number>> @@ -98,8 +99,6 @@ export default function WizardFinalResult({ setWizardSetp }: WizardPageProps) { })?.status }} render={({ handleSubmit, form }: any) => { - const cancelBtn = () => {} - return ( programStagesDatas?.programStages?.length > 0 && ( <form onSubmit={handleSubmit}> @@ -113,17 +112,41 @@ export default function WizardFinalResult({ setWizardSetp }: WizardPageProps) { dataElements: dataElementsDatas?.dataElements || [] })} /> - <div className={style.btnContainer}> - <div> - <Button type="submit" primary loading={loadingProcessing}> - Save - </Button> - </div> - <div className={style.btnCancel}> - <Button type="button" disabled onClick={cancelBtn}> - Cancel - </Button> + <div className={style.flexBetween}> + <div className={style.flex}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> + </div> + <div className={style.btnCancel}> + <Button disabled type="button"> + Cancel + </Button> + </div> </div> + {getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'final-result', + key: 'student' + })?.programStage && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'final-result', + key: 'student' + })?.status && ( + <div> + <Button + primary + onClick={() => { + setWizardSetp(6) + }} + > + <IoIosArrowRoundForward style={{ fontSize: '20px' }} /> + Next + </Button> + </div> + )} </div> </form> ) diff --git a/src/components/students/WizardProgram.tsx b/src/components/students/WizardProgram.tsx index f364bc9..d054301 100644 --- a/src/components/students/WizardProgram.tsx +++ b/src/components/students/WizardProgram.tsx @@ -31,6 +31,13 @@ export default function WizardProgram({ setWizardSetp }: WizardPageProps) { {data !== undefined && data !== null && ( <div> <Form + initialValues={{ + program: getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'program', + key: 'student' + }) + }} onSubmit={async (values: { program: string }) => { await submit({ data, @@ -50,15 +57,6 @@ export default function WizardProgram({ setWizardSetp }: WizardPageProps) { fields={getFormFields({ programs: data.programs, data - }).map((p) => { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data?.dataStoreValues, - elementKey: 'program', - key: 'student' - }) - } })} /> <div className={style.flexBetween}> diff --git a/src/components/students/WizardSocioEconomics.tsx b/src/components/students/WizardSocioEconomics.tsx index 7cc85f4..de51f1c 100644 --- a/src/components/students/WizardSocioEconomics.tsx +++ b/src/components/students/WizardSocioEconomics.tsx @@ -65,6 +65,13 @@ export default function WizardSocioEconomics({ setWizardSetp }: WizardPageProps) {data !== undefined && data !== null && ( <div> <Form + initialValues={{ + programStage: getDataStoreElement({ + dataStores: data?.dataStoreValues, + elementKey: 'socio-economics', + key: 'student' + })?.programStage + }} onSubmit={async (values: { programStage: string }) => { await submit( { programStage: values?.programStage }, @@ -82,21 +89,7 @@ export default function WizardSocioEconomics({ setWizardSetp }: WizardPageProps) <GroupForm disabled={false} name="socio-economics" - fields={getFormFields(data, programStagesDatas.programStages).map( - (p) => { - if (p.name === 'programStage') { - return { - ...p, - defaultValue: getDataStoreElement({ - dataStores: data?.dataStoreValues, - elementKey: 'socio-economics', - key: 'student' - })?.programStage - } - } - return p - } - )} + fields={getFormFields(data, programStagesDatas.programStages)} /> <div className={style.flexBetween}> <div className={style.flex}> diff --git a/src/components/students/WizardTransfer.tsx b/src/components/students/WizardTransfer.tsx index 3a85a87..a7fe024 100644 --- a/src/components/students/WizardTransfer.tsx +++ b/src/components/students/WizardTransfer.tsx @@ -12,6 +12,7 @@ import style from './index.module.css' import { Form } from 'react-final-form' import { GroupForm } from '..' import { type SubmitTransferValue } from '../../types/students' +import { IoIosArrowRoundForward } from 'react-icons/io' interface WizardPageProps { setWizardSetp: React.Dispatch<React.SetStateAction<number>> @@ -114,13 +115,6 @@ export default function WizardTransfer({ setWizardSetp }: WizardPageProps) { })?.reason }} render={({ handleSubmit, form }: any) => { - const handleCancel = () => { - // form.change("programStage", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.programStage) - // form.change("destinySchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.destinySchool) - // form.change("originSchool", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.originSchool) - // form.change("status", getDataStoreElement({ dataStores: data.dataStoreValues, elementKey: "transfer", key: "student" })?.status) - } - return ( programStagesDatas?.programStages?.length > 0 && ( <div> @@ -135,17 +129,58 @@ export default function WizardTransfer({ setWizardSetp }: WizardPageProps) { dataElements: dataElementsDatas?.dataElements || [] })} /> - <div className={style.btnContainer}> - <div> - <Button type="submit" primary loading={loadingProcessing}> - Save - </Button> - </div> - <div className={style.btnCancel}> - <Button disabled onClick={handleCancel} type="button"> - Cancel - </Button> + <div className={style.flexBetween}> + <div className={style.flex}> + <div> + <Button type="submit" primary loading={loadingProcessing}> + Save + </Button> + </div> + <div className={style.btnCancel}> + <Button disabled type="button"> + Cancel + </Button> + </div> </div> + {getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.programStage && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.originSchool && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.destinySchool && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.status && + getDataStoreElement({ + dataStores: data.dataStoreValues, + elementKey: 'transfer', + key: 'student' + })?.reason && ( + <div> + <Button + primary + onClick={() => { + setWizardSetp(7) + }} + > + <IoIosArrowRoundForward + style={{ fontSize: '20px' }} + /> + Next + </Button> + </div> + )} </div> </form> </div>