Skip to content

Commit

Permalink
Merge pull request #3370 from LiteFarmOrg/LF-4166/Implement_End-to-En…
Browse files Browse the repository at this point in the history
…d_animal_creation_flow

LF-4166 (1): Implement end to end animal creation flow
  • Loading branch information
kathyavini committed Aug 7, 2024
2 parents bd4d956 + 3738924 commit 1ff4372
Show file tree
Hide file tree
Showing 20 changed files with 417 additions and 14 deletions.
1 change: 1 addition & 0 deletions packages/webapp/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"DELETE": "Delete",
"DO_NOT_KNOW": "I don't know",
"DO_NOT_SHOW": "Don’t show this message again.",
"DONE": "Done",
"EDIT": "Edit",
"EDIT_DATE": "Edit date",
"EDITING": "Editing...",
Expand Down
3 changes: 3 additions & 0 deletions packages/webapp/public/locales/en/translation.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{
"ADD_ANIMAL": {
"ADD_ANIMALS": "Add animals",
"ADD_TO_INVENTORY": "Add animal to your inventory",
"ANIMAL_BASICS": "Animal basics",
"ANIMAL_DETAILS": "Animal details",
"ANIMALS_TOTAL_one": "{{count}} animal total",
"ANIMALS_TOTAL_other": "{{count}} animals total",
"ANIMALS_UNSPECIFIED_one": "{{count}} unspecified",
Expand Down
1 change: 1 addition & 0 deletions packages/webapp/public/locales/es/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"DELETE": "Borrar",
"DO_NOT_KNOW": "MISSING",
"DO_NOT_SHOW": "No vuelva a mostrar este mensaje.",
"DONE": "MISSING",
"EDIT": "Editar",
"EDIT_DATE": "Editar fecha",
"EDITING": "Editando...",
Expand Down
3 changes: 3 additions & 0 deletions packages/webapp/public/locales/es/translation.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{
"ADD_ANIMAL": {
"ADD_ANIMALS": "MISSING",
"ADD_TO_INVENTORY": "MISSING",
"ANIMAL_BASICS": "MISSING",
"ANIMAL_DETAILS": "MISSING",
"ANIMALS_TOTAL_one": "MISSING",
"ANIMALS_TOTAL_many": "MISSING",
"ANIMALS_TOTAL_other": "MISSING",
Expand Down
1 change: 1 addition & 0 deletions packages/webapp/public/locales/fr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"DELETE": "Effacer",
"DO_NOT_KNOW": "MISSING",
"DO_NOT_SHOW": "Ne plus afficher ce message",
"DONE": "MISSING",
"EDIT": "Modifier",
"EDIT_DATE": "Modifier la Date",
"EDITING": "Édition...",
Expand Down
3 changes: 3 additions & 0 deletions packages/webapp/public/locales/fr/translation.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{
"ADD_ANIMAL": {
"ADD_ANIMALS": "MISSING",
"ADD_TO_INVENTORY": "MISSING",
"ANIMAL_BASICS": "MISSING",
"ANIMAL_DETAILS": "MISSING",
"ANIMALS_TOTAL_one": "MISSING",
"ANIMALS_TOTAL_many": "MISSING",
"ANIMALS_TOTAL_other": "MISSING",
Expand Down
1 change: 1 addition & 0 deletions packages/webapp/public/locales/pt/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"DELETE": "Excluir",
"DO_NOT_KNOW": "MISSING",
"DO_NOT_SHOW": "Não mostrar esta mensagem novamente",
"DONE": "MISSING",
"EDIT": "Editar",
"EDIT_DATE": "Editar data",
"EDITING": "Editando...",
Expand Down
3 changes: 3 additions & 0 deletions packages/webapp/public/locales/pt/translation.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{
"ADD_ANIMAL": {
"ADD_ANIMALS": "MISSING",
"ADD_TO_INVENTORY": "MISSING",
"ANIMAL_BASICS": "MISSING",
"ANIMAL_DETAILS": "MISSING",
"ANIMALS_TOTAL_one": "MISSING",
"ANIMALS_TOTAL_many": "MISSING",
"ANIMALS_TOTAL_other": "MISSING",
Expand Down
17 changes: 17 additions & 0 deletions packages/webapp/src/components/Animals/Inventory/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/
import { ChangeEvent } from 'react';
import { History } from 'history';
import Table from '../../../components/Table';
import PureSearchBarWithBackdrop from '../../PopupFilter/PureSearchWithBackdrop';
import NoSearchResults from '../../../components/Card/NoSearchResults';
Expand All @@ -21,11 +22,14 @@ import ClearFiltersButton, {
} from '../../../components/Button/ClearFiltersButton';
import type { AnimalInventory } from '../../../containers/Animals/Inventory/useAnimalInventory';
import AnimalsFilter from '../../../containers/Animals/AnimalsFilter';
import FloatingButtonMenu from '../../Menu/FloatingButtonMenu';
import { TableV2Column, TableKind } from '../../Table/types';
import type { Dispatch, SetStateAction } from 'react';
import styles from './styles.module.scss';
import clsx from 'clsx';
import { sumObjectValues } from '../../../util';
import { useTranslation } from 'react-i18next';
import { ADD_ANIMALS_URL } from '../../../util/siteMapConstants';

const HEIGHTS = {
filterAndSearch: 64,
Expand Down Expand Up @@ -54,6 +58,7 @@ const PureAnimalInventory = ({
clearFilters,
isLoading,
containerHeight,
history,
}: {
filteredInventory: AnimalInventory[];
animalsColumns: TableV2Column[];
Expand All @@ -68,7 +73,10 @@ const PureAnimalInventory = ({
clearFilters: () => void;
isLoading: boolean;
containerHeight?: number;
history: History;
}) => {
const { t } = useTranslation();

if (isLoading) {
return null;
}
Expand Down Expand Up @@ -140,6 +148,15 @@ const PureAnimalInventory = ({
/>
)}
</div>
<FloatingButtonMenu
type={'add'}
options={[
{
label: t('ADD_ANIMAL.ADD_ANIMALS'),
onClick: () => history.push(ADD_ANIMALS_URL),
},
]}
/>
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import styles from './styles.module.scss';
import { ReactComponent as ChevronRight } from '../../../assets/images/buttons/chevron-right.svg';

export interface FormNavigationButtonsProps {
isFirstStep?: boolean;
isFinalStep?: boolean;
isDisabled?: boolean;
contextualContent?: React.ReactNode | string;
Expand All @@ -31,6 +32,7 @@ export interface FormNavigationButtonsProps {
}

const FormNavigationButtons = ({
isFirstStep = false,
isFinalStep = false,
isDisabled = false,
contextualContent,
Expand All @@ -49,7 +51,14 @@ const FormNavigationButtons = ({
{t('common:CANCEL')}
</Button>
{onPrevious && (
<Button color="secondary" onClick={onPrevious} className={styles.button} sm fullLength>
<Button
color="secondary"
disabled={isFirstStep}
onClick={onPrevious}
className={styles.button}
sm
fullLength
>
{t('common:PREVIOUS')}
</Button>
)}
Expand Down
134 changes: 122 additions & 12 deletions packages/webapp/src/components/Form/MultiStepForm/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,39 @@
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

import { useState, useMemo } from 'react';

import { useState, useMemo, useEffect, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import PropTypes from 'prop-types';
import MultiStepPageTitle from '../../PageTitle/MultiStepPageTitle';
import Layout from '../../Layout';
import { ClickAwayListener } from '@mui/material';
import { FormProvider, useForm } from 'react-hook-form';
import StepperProgressBar from '../../StepperProgressBar';
import FloatingContainer from '../../FloatingContainer';
import FormNavigationButtons from '../FormNavigationButtons';

export const VARIANT = {
PAGE_TITLE: 'page_title',
STEPPER_PROGRESS_BAR: 'stepper_progress_bar',
};

export const MultiStepForm = ({ history, getSteps, cancelModalTitle, defaultFormValues }) => {
export const MultiStepForm = ({
history,
getSteps,
cancelModalTitle,
defaultFormValues,
variant = VARIANT.PAGE_TITLE,
isCompactSideMenu,
hasSummaryWithinForm,
onSave,
stepperProgressBarConfig = {},
}) => {
const [activeStepIndex, setActiveStepIndex] = useState(0);
const [showConfirmCancelModal, setShowConfirmCancelModal] = useState(false);
const [formData, setFormData] = useState();

const { t } = useTranslation();

const form = useForm({
mode: 'onBlur',
defaultValues: defaultFormValues,
Expand All @@ -36,6 +57,36 @@ export const MultiStepForm = ({ history, getSteps, cancelModalTitle, defaultForm
[steps],
);

const isSummaryPage =
variant === VARIANT.STEPPER_PROGRESS_BAR &&
hasSummaryWithinForm &&
activeStepIndex === steps.length - 1;

const isSummaryPageRef = useRef(isSummaryPage);

useEffect(() => {
isSummaryPageRef.current = isSummaryPage;
}, [isSummaryPage]);

// Block the page transition
// https://github.com/remix-run/history/blob/dev/docs/blocking-transitions.md
useEffect(() => {
if (variant !== VARIANT.STEPPER_PROGRESS_BAR || isSummaryPage) {
return;
}
const unblock = history.block((tx) => {
if (window.confirm(`TODO: ${t('CANCEL_FLOW_MODAL.BODY')}`)) {
// Unblock the navigation.
unblock();

// Retry the transition.
tx.retry();
}
});

return () => unblock();
}, [variant, isSummaryPage]);

const storeFormData = () => {
const values = form.getValues();
setFormData({ ...formData, ...values });
Expand All @@ -59,30 +110,89 @@ export const MultiStepForm = ({ history, getSteps, cancelModalTitle, defaultForm
history.back();
};

const onPrevious = () => {
if (!activeStepIndex) {
return;
}
storeFormData();
setActiveStepIndex(activeStepIndex - 1);
};

const onClickAway = () => {
setShowConfirmCancelModal(true);
};

const activeStep = steps[activeStepIndex];

const isFinalStep =
(!hasSummaryWithinForm && activeStepIndex === steps.length - 1) ||
(hasSummaryWithinForm && activeStepIndex === steps.length - 2);

const shouldShowFormNavigationButtons =
variant === VARIANT.STEPPER_PROGRESS_BAR && !isSummaryPage;

const onContinue = () => {
if (isFinalStep) {
form.handleSubmit((data) => onSave(data, onGoForward))();
return;
}
onGoForward();
};

return (
<ClickAwayListener onClickAway={onClickAway} mouseEvent="onMouseDown" touchEvent="onTouchStart">
<div>
<Layout>
<MultiStepPageTitle
title={activeStep.title}
onGoBack={onGoBack}
onCancel={onCancel}
cancelModalTitle={cancelModalTitle}
value={progressBarValue}
showConfirmCancelModal={showConfirmCancelModal}
setShowConfirmCancelModal={setShowConfirmCancelModal}
{variant === VARIANT.STEPPER_PROGRESS_BAR && (
<StepperProgressBar
{...stepperProgressBarConfig}
steps={steps.map(({ title }) => title)}
activeStep={activeStepIndex}
/>
)}
<Layout>
{variant === VARIANT.PAGE_TITLE && (
<MultiStepPageTitle
title={activeStep.title}
onGoBack={onGoBack}
onCancel={onCancel}
cancelModalTitle={cancelModalTitle}
value={progressBarValue}
showConfirmCancelModal={showConfirmCancelModal}
setShowConfirmCancelModal={setShowConfirmCancelModal}
/>
)}
<FormProvider {...form}>
<activeStep.FormContent onGoForward={onGoForward} form={form} />
</FormProvider>
</Layout>
{shouldShowFormNavigationButtons && (
<FloatingContainer isCompactSideMenu={isCompactSideMenu}>
<FormNavigationButtons
onContinue={onContinue}
onCancel={onCancel}
onGoBack={onGoBack}
onPrevious={onPrevious}
isFirstStep={!activeStepIndex}
isFinalStep={isFinalStep}
/>
</FloatingContainer>
)}
</div>
</ClickAwayListener>
);
};

MultiStepForm.propTypes = {
history: PropTypes.object,
getSteps: PropTypes.func,
cancelModalTitle: PropTypes.string,
defaultFormValues: PropTypes.object,
variant: PropTypes.oneOf(Object.values(VARIANT)),
isCompactSideMenu: PropTypes.bool,
hasSummaryWithinForm: PropTypes.bool,
onSave: PropTypes.func,
stepperProgressBarConfig: PropTypes.shape({
isMobile: PropTypes.bool,
isDarkMode: PropTypes.bool,
}),
};
20 changes: 20 additions & 0 deletions packages/webapp/src/containers/Animals/AddAnimalBasics/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright 2024 LiteFarm.org
* This file is part of LiteFarm.
*
* LiteFarm is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LiteFarm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

const AddAnimalBasics = () => {
return <div>Add animals basics</div>;
};

export default AddAnimalBasics;
20 changes: 20 additions & 0 deletions packages/webapp/src/containers/Animals/AddAnimalDetails/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright 2024 LiteFarm.org
* This file is part of LiteFarm.
*
* LiteFarm is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LiteFarm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

const AddAnimalDetails = () => {
return <div>Add animal details</div>;
};

export default AddAnimalDetails;
Loading

0 comments on commit 1ff4372

Please sign in to comment.