Skip to content

Commit

Permalink
🌱 update to new wizard for assessment-wizard and custom-wizard-footer (
Browse files Browse the repository at this point in the history
…#1473)

Would like some thorough testing on this.

#1244

---------

Signed-off-by: gitdallas <[email protected]>
  • Loading branch information
gitdallas authored Oct 18, 2023
1 parent 357a54c commit a7d5d84
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 143 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import React, { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { useHistory } from "react-router-dom";
import { FieldErrors, FormProvider, useForm } from "react-hook-form";
import { ButtonVariant } from "@patternfly/react-core";
import { Wizard, WizardStep } from "@patternfly/react-core/deprecated";
import { ButtonVariant, Wizard, WizardStep } from "@patternfly/react-core";

import {
Assessment,
Expand All @@ -16,7 +15,6 @@ import {
import { CustomWizardFooter } from "../custom-wizard-footer";
import { getApplicationById, getArchetypeById } from "@app/api/rest";
import { NotificationsContext } from "@app/components/NotificationsContext";
import { WizardStepNavDescription } from "../wizard-step-nav-description";
import { QuestionnaireForm } from "../questionnaire-form";
import { ConfirmDialog } from "@app/components/ConfirmDialog";
import {
Expand All @@ -38,6 +36,7 @@ import { AssessmentStakeholdersForm } from "../assessment-stakeholders-form/asse
import useIsArchetype from "@app/hooks/useIsArchetype";
import { useFetchStakeholderGroups } from "@app/queries/stakeholdergoups";
import { useFetchStakeholders } from "@app/queries/stakeholders";
import { WizardStepNavDescription } from "../wizard-step-nav-description";

export const SAVE_ACTION_KEY = "saveAction";

Expand Down Expand Up @@ -98,11 +97,9 @@ export const AssessmentWizard: React.FC<AssessmentWizardProps> = ({

const { pushNotification } = React.useContext(NotificationsContext);

const sortedSections = useMemo(() => {
return (assessment ? assessment.sections : []).sort(
const sortedSections = (!isLoadingAssessment && assessment ? assessment.sections : []).sort(
(a, b) => a.order - b.order
);
}, [assessment]);
);

//TODO: Add comments to the sections when/if available from api
// const initialComments = useMemo(() => {
Expand All @@ -121,7 +118,7 @@ export const AssessmentWizard: React.FC<AssessmentWizardProps> = ({
assessment.sections
.flatMap((f) => f.questions)
.forEach((question) => {
const existingAnswer = assessment.sections
const existingAnswer = assessment?.sections
?.flatMap((section) => section.questions)
.find((q) => q.text === question.text)
?.answers.find((a) => a.selected === true);
Expand Down Expand Up @@ -217,19 +214,14 @@ export const AssessmentWizard: React.FC<AssessmentWizardProps> = ({
const allQuestionsValid = section?.questions.every((question) =>
isQuestionValid(question)
);

const allQuestionsAnswered = areAllQuestionsAnswered(section);

return allQuestionsAnswered && allQuestionsValid;
};

const maxCategoryWithData = [...sortedSections].reverse().find((section) => {
return section.questions.some((question) => questionHasValue(question));
// ||commentMinLenghtIs1(category)
});
const canJumpTo = maxCategoryWithData
? sortedSections.findIndex((f) => f.name === maxCategoryWithData.name) + 1
: 0;

const onInvalid = (errors: FieldErrors<AssessmentWizardValues>) =>
console.error("form errors", errors);
Expand Down Expand Up @@ -506,62 +498,6 @@ export const AssessmentWizard: React.FC<AssessmentWizardProps> = ({
}
};

const wizardSteps: WizardStep[] = [
{
id: 0,
name: t("composed.selectMany", {
what: t("terms.stakeholders").toLowerCase(),
}),
component: <AssessmentStakeholdersForm />,
canJumpTo: 0 === currentStep || !disableNavigation,
enableNext: isFirstStepValid(),
},
...sortedSections.map((section, index) => {
const stepIndex = index + 1;

return {
id: stepIndex,
name: section.name,
stepNavItemProps: {
children: <WizardStepNavDescription section={section} />,
},
component: <QuestionnaireForm key={section.name} section={section} />,
canJumpTo:
stepIndex === currentStep ||
(stepIndex <= canJumpTo && !disableNavigation),
enableNext: shouldNextBtnBeEnabled(section),
} as WizardStep;
}),
];

const wizardFooter = (
<CustomWizardFooter
isFirstStep={currentStep === 0}
isLastStep={currentStep === sortedSections.length}
isDisabled={
isSubmitting ||
isValidating ||
(currentStep === sortedSections.length &&
!shouldNextBtnBeEnabled(sortedSections[currentStep - 1]))
}
hasAnswers={hasPartialAnswers(sortedSections[currentStep - 1])}
isFormInvalid={!isValid}
onSave={(review) => {
const saveActionValue = review
? SAVE_ACTION_VALUE.SAVE_AND_REVIEW
: SAVE_ACTION_VALUE.SAVE;

methods.setValue(SAVE_ACTION_KEY, saveActionValue);

methods.handleSubmit(onSubmit, onInvalid)();
}}
onSaveAsDraft={() => {
methods.setValue(SAVE_ACTION_KEY, SAVE_ACTION_VALUE.SAVE_AS_DRAFT);
methods.handleSubmit(onSubmit)();
}}
/>
);

useEffect(() => {
const unlisten = history.listen((newLocation, action) => {
if (action === "PUSH" && assessment) {
Expand Down Expand Up @@ -610,22 +546,81 @@ export const AssessmentWizard: React.FC<AssessmentWizardProps> = ({
}
};

const getWizardFooter = (step: number, section?: Section) => {
return (
<CustomWizardFooter
enableNext={
section ? shouldNextBtnBeEnabled(section) : isFirstStepValid()
}
isFirstStep={step === 0}
isLastStep={step === sortedSections.length}
onNext={() => setCurrentStep(step + 1)}
onBack={() => setCurrentStep(step - 1)}
isDisabled={
isSubmitting ||
isValidating ||
(step === sortedSections.length &&
!shouldNextBtnBeEnabled(sortedSections[step - 1]))
}
hasAnswers={hasPartialAnswers(sortedSections[step - 1])}
isFormInvalid={!isValid}
onSave={(review) => {
const saveActionValue = review
? SAVE_ACTION_VALUE.SAVE_AND_REVIEW
: SAVE_ACTION_VALUE.SAVE;

methods.setValue(SAVE_ACTION_KEY, saveActionValue);

methods.handleSubmit(onSubmit, onInvalid)();
}}
onSaveAsDraft={() => {
methods.setValue(SAVE_ACTION_KEY, SAVE_ACTION_VALUE.SAVE_AS_DRAFT);
methods.handleSubmit(onSubmit)();
}}
/>
);
};

return (
<>
{isOpen && (
{isOpen && !!sortedSections.length && (
<FormProvider {...methods}>
<Wizard
navAriaLabel="assessment-wizard"
mainAriaLabel="assesment-wizard"
steps={wizardSteps}
footer={wizardFooter}
onNext={() => setCurrentStep((current) => current + 1)}
onBack={() => setCurrentStep((current) => current - 1)}
isVisitRequired
onStepChange={(_e, curr) => {
setCurrentStep(curr.index);
}}
onClose={() => {
assessment && setAssessmentToCancel(assessment);
}}
onGoToStep={(step) => setCurrentStep(step.id as number)}
/>
>
<WizardStep
id={0}
footer={getWizardFooter(0)}
name={t("composed.selectMany", {
what: t("terms.stakeholders").toLowerCase(),
})}
isDisabled={currentStep !== 0 && disableNavigation}
>
<AssessmentStakeholdersForm />
</WizardStep>
{...sortedSections.map((section, index) => {
const stepIndex = index + 1;
return (
<WizardStep
id={stepIndex}
name={section.name}
isDisabled={stepIndex !== currentStep && disableNavigation}
navItem={{
children: <WizardStepNavDescription section={section} />,
}}
footer={getWizardFooter(stepIndex, section)}
>
<QuestionnaireForm key={section.name} section={section} />
</WizardStep>
);
})}
</Wizard>
{assessmentToCancel && (
<ConfirmDialog
title={t("dialog.title.leavePage")}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import React from "react";
import { useTranslation } from "react-i18next";

import { Button } from "@patternfly/react-core";

import {
WizardContextConsumer,
WizardFooter,
} from "@patternfly/react-core/deprecated";
Button,
WizardFooterWrapper,
useWizardContext,
} from "@patternfly/react-core";

export interface CustomWizardFooterProps {
isFirstStep: boolean;
isLastStep: boolean;
isDisabled: boolean;
isFormInvalid: boolean;
hasAnswers?: boolean;
enableNext?: boolean;
onNext?: () => void;
onBack?: () => void;
onSave: (review: boolean) => void;
onClose?: () => {};
onSaveAsDraft: () => void;
}

Expand All @@ -23,76 +27,84 @@ export const CustomWizardFooter: React.FC<CustomWizardFooterProps> = ({
isDisabled,
isFormInvalid,
hasAnswers,
enableNext,
onNext,
onBack,
onSave,
onClose,
onSaveAsDraft,
}) => {
const { t } = useTranslation();

const { goToNextStep, goToPrevStep, close, activeStep } = useWizardContext();
return (
<WizardFooter>
<WizardContextConsumer>
{({ onNext, onBack, onClose, activeStep }) => {
const enableNext =
activeStep && activeStep.enableNext !== undefined
? activeStep.enableNext
: true;

return (
<>
<WizardFooterWrapper>
<>
{isLastStep ? (
<>
{isLastStep ? (
<>
<Button
variant="primary"
onClick={() => onSave(false)}
isDisabled={!enableNext || isDisabled || isFormInvalid}
cy-data="next"
>
{t("actions.save")}
</Button>
<Button
variant="primary"
onClick={() => onSave(true)}
isDisabled={!enableNext || isDisabled || isFormInvalid}
cy-data="save-and-review"
>
{t("actions.saveAndReview")}
</Button>
</>
) : (
<Button
variant="primary"
onClick={onNext}
isDisabled={!enableNext || isDisabled || isFormInvalid}
cy-data="next"
>
{t("actions.next")}
</Button>
)}
<Button
variant="secondary"
onClick={onBack}
isDisabled={isFirstStep || isFormInvalid}
cy-data="back"
variant="primary"
onClick={() => onSave(false)}
isDisabled={!enableNext || isDisabled || isFormInvalid}
cy-data="next"
>
{t("actions.back")}
{t("actions.save")}
</Button>
<Button variant="link" onClick={onClose} cy-data="cancel">
{t("actions.cancel")}
<Button
variant="primary"
onClick={() => onSave(true)}
isDisabled={!enableNext || isDisabled || isFormInvalid}
cy-data="save-and-review"
>
{t("actions.saveAndReview")}
</Button>
{!isFirstStep && (
<Button
variant="link"
onClick={onSaveAsDraft}
isDisabled={isFormInvalid || isFirstStep || !hasAnswers}
cy-data="save-as-draft"
>
{t("actions.saveAsDraft")}
</Button>
)}
</>
);
}}
</WizardContextConsumer>
</WizardFooter>
) : (
<Button
variant="primary"
onClick={() => {
goToNextStep();
onNext && onNext();
}}
isDisabled={!enableNext || isDisabled || isFormInvalid}
cy-data="next"
>
{t("actions.next")}
</Button>
)}
<Button
variant="secondary"
onClick={() => {
goToPrevStep();
onBack && onBack();
}}
isDisabled={isFirstStep || isFormInvalid}
cy-data="back"
>
{t("actions.back")}
</Button>
<Button
variant="link"
onClick={() => {
close();
onClose && onClose();
}}
cy-data="cancel"
>
{t("actions.cancel")}
</Button>
{!isFirstStep && (
<Button
variant="link"
onClick={onSaveAsDraft}
isDisabled={isFormInvalid || isFirstStep || !hasAnswers}
cy-data="save-as-draft"
>
{t("actions.saveAsDraft")}
</Button>
)}
</>
</WizardFooterWrapper>
</>
);
};
Loading

0 comments on commit a7d5d84

Please sign in to comment.