Skip to content

Commit

Permalink
Merge pull request #3534 from LiteFarmOrg/LF-4384/End-to-End_Animal_D…
Browse files Browse the repository at this point in the history
…etails

LF-4384: End to end animal details
  • Loading branch information
antsgar authored Nov 28, 2024
2 parents 1d99efc + 2325f80 commit bd04b17
Show file tree
Hide file tree
Showing 17 changed files with 299 additions and 143 deletions.
5 changes: 5 additions & 0 deletions packages/api/src/controllers/animalBatchController.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ const animalBatchController = {
'origin_id',
'group_ids',
'animal_batch_use_relationships',
'birth_date',
'dam',
'sire',
'brought_in_date',
'weaning_date',
];

// select only allowed properties to edit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ const getRecordIfExists = async (animalOrBatch, animalOrBatchKey, farm_id) => {
return await AnimalOrBatchModel[animalOrBatchKey]
.query()
.findById(animalOrBatch.id)
.where({ farm_id })
.where({ farm_id, animal_removal_reason_id: null })
.whereNotDeleted()
.withGraphFetched(relations);
};
Expand Down
4 changes: 2 additions & 2 deletions packages/webapp/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ import { NotistackSnackbar } from './containers/Snackbar/NotistackSnackbar';
import { OfflineDetector } from './containers/hooks/useOfflineDetector/OfflineDetector';
import styles from './styles.module.scss';
import Routes from './routes';
import { ANIMALS_INVENTORY_URL } from './util/siteMapConstants';
import { ANIMALS_INVENTORY_URL, ANIMALS_URL } from './util/siteMapConstants';

function App() {
const [isCompactSideMenu, setIsCompactSideMenu] = useState(false);
const [isFeedbackSurveyOpen, setFeedbackSurveyOpen] = useState(false);
const FULL_WIDTH_ROUTES = ['/map', ANIMALS_INVENTORY_URL];
const FULL_WIDTH_ROUTES = ['/map', ANIMALS_INVENTORY_URL, ANIMALS_URL];
const isFullWidth = FULL_WIDTH_ROUTES.some((path) => matchPath(history.location.pathname, path));

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export function AnimalBreedSelect<T extends FieldValues>({
placeholder={isTypeSelected ? undefined : t('ADD_ANIMAL.BREED_PLACEHOLDER_DISABLED')}
isDisabled={!isTypeSelected || isDisabled}
onChange={(option) => onChange(option)}
value={value}
value={value || null}
/>
)}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ type ContainerWithButtonsProps = {
children: ReactNode;
contentClassName?: string;
isCompactView?: boolean;
showMenu: boolean;
isEditing?: boolean;
options: { label: ReactNode; onClick: () => void }[];
onBack: () => void;
Expand All @@ -93,6 +94,7 @@ const ContainerWithButtons = ({
children,
contentClassName,
isCompactView,
showMenu = true,
isEditing,
options,
onBack,
Expand All @@ -106,16 +108,20 @@ const ContainerWithButtons = ({
<div className={clsx(styles.content, contentClassName)}>{children}</div>
<div className={styles.statusAndButton}>
{!isCompactView && isEditing ? <div>{t('common:EDITING')}</div> : null}
<MeatballsMenu
options={options}
classes={{ button: isEditing ? styles.editingStatusButton : '' }}
/>
{showMenu && (
<MeatballsMenu
disabled={!!isEditing}
options={options}
classes={{ button: isEditing ? styles.editingStatusButton : '' }}
/>
)}
</div>
</div>
);
};

export type AnimalSingleViewHeaderProps = {
showMenu: boolean;
isEditing?: boolean;
onEdit: () => void;
onRemove: () => void;
Expand All @@ -128,6 +134,7 @@ export type AnimalSingleViewHeaderProps = {
};

const AnimalSingleViewHeader = ({
showMenu = true,
isEditing,
onEdit,
onRemove,
Expand Down Expand Up @@ -163,7 +170,7 @@ const AnimalSingleViewHeader = ({
{ label: <MenuItem iconName="TRASH" text={t('common:REMOVE')} />, onClick: onRemove },
];

const commonProp = { t, isEditing, isCompactView, options: menuOptions, onBack };
const commonProp = { t, showMenu, isEditing, isCompactView, options: menuOptions, onBack };

const renderCompactHeader = () => (
<div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@
padding-left: 16px;
}

.editingStatusButton {
.editingStatusButton,
.editingStatusButton:disabled {
background: var(--Btn-primary-hover);
box-shadow: 1px 1px 0px 0px var(--Colors-Primary-Primary-teal-300);

Expand Down Expand Up @@ -152,6 +153,8 @@
bottom: 8px;

height: 24px;
min-width: 20px;
max-width: 44px;
padding: 4px;
border-radius: 2px;
background: var(--Colors-Accent---singles-Purple-light);
Expand All @@ -160,6 +163,10 @@
color: var(--Colors-Accent---singles-Purple-full);
font-size: 12px;
font-weight: 600;
text-align: center;

/* Counts with more than five digits will be visually cut off */
overflow: hidden;
}

.desktopBasicInfo {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

import { ReactNode, useEffect, useRef, useState } from 'react';
import { UseFormHandleSubmit, FieldValues, FormState, UseFormReset } from 'react-hook-form';
import { ReactNode, useEffect, useState } from 'react';
import {
UseFormHandleSubmit,
FieldValues,
FormState,
UseFormReset,
UseFormGetValues,
} from 'react-hook-form';
import { History } from 'history';
import StepperProgressBar from '../../StepperProgressBar';
import StepperProgressBar, { StepperProgressBarProps } from '../../StepperProgressBar';
import FloatingContainer from '../../FloatingContainer';
import FormNavigationButtons from '../FormNavigationButtons';
import FixedHeaderContainer from '../../Animals/FixedHeaderContainer';
Expand All @@ -38,13 +44,14 @@ interface WithStepperProgressBarProps {
stepperProgressBarTitle?: ReactNode;
onSave: (
data: FieldValues,
onGoForward: () => void,
onSuccess: () => void,
setFormResultData?: (data: any) => void,
) => void;
onGoBack: () => void;
onCancel: () => void;
onGoForward: () => void;
reset: UseFormReset<FieldValues>;
getValues: UseFormGetValues<FieldValues>;
formState: FormState<FieldValues>;
handleSubmit: UseFormHandleSubmit<FieldValues>;
setFormResultData: (data: any) => void;
Expand All @@ -70,6 +77,7 @@ export const WithStepperProgressBar = ({
onGoForward,
handleSubmit,
reset,
getValues,
formState: { isValid, isDirty },
setFormResultData,
isEditing,
Expand Down Expand Up @@ -105,12 +113,20 @@ export const WithStepperProgressBar = ({

const shouldShowFormNavigationButtons = !isSummaryPage && isEditing;

const onSuccess = () => {
reset(getValues());
setIsEditing?.(false);

if (hasSummaryWithinForm) {
onGoForward();
}
};

const onContinue = async () => {
if (isFinalStep) {
setIsSaving(true);
await handleSubmit((data: FieldValues) => onSave(data, onGoForward, setFormResultData))();
await handleSubmit((data: FieldValues) => onSave(data, onSuccess, setFormResultData))();
setIsSaving(false);
setIsEditing?.(false);
return;
}
onGoForward();
Expand All @@ -134,17 +150,12 @@ export const WithStepperProgressBar = ({
};

return (
<FixedHeaderContainer
header={
isSingleStep ? null : (
<StepperProgressBar
{...stepperProgressBarConfig}
title={stepperProgressBarTitle}
steps={steps.map(({ title }) => title)}
activeStep={activeStepIndex}
/>
)
}
<StepperProgressBarWrapper
isSingleStep={isSingleStep}
{...stepperProgressBarConfig}
title={stepperProgressBarTitle}
steps={steps.map(({ title }) => title)}
activeStep={activeStepIndex}
>
<div className={styles.contentWrapper}>{children}</div>
{shouldShowFormNavigationButtons && (
Expand All @@ -166,6 +177,27 @@ export const WithStepperProgressBar = ({
handleCancel={handleCancel}
/>
)}
</StepperProgressBarWrapper>
);
};

type StepperProgressBarWrapperProps = StepperProgressBarProps & {
children: ReactNode;
isSingleStep: boolean;
};

const StepperProgressBarWrapper = ({
children,
isSingleStep,
...stepperProgressBarProps
}: StepperProgressBarWrapperProps) => {
if (isSingleStep) {
return <>{children}</>;
}

return (
<FixedHeaderContainer header={<StepperProgressBar {...stepperProgressBarProps} />}>
{children}
</FixedHeaderContainer>
);
};
5 changes: 0 additions & 5 deletions packages/webapp/src/components/Form/ContextForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ export const ContextForm = ({
variant = Variant.PAGE_TITLE,
isEditing = true,
setIsEditing,
onSave,
...props
}: ContextFormProps) => {
const [activeStepIndex, setActiveStepIndex] = useState(0);
Expand Down Expand Up @@ -108,10 +107,6 @@ export const ContextForm = ({
setIsEditing={setIsEditing}
showCancelFlow={showCancelFlow}
setShowCancelFlow={setShowCancelFlow}
onSave={(...args: any) => {
setActiveStepIndex(0);
onSave?.(...args);
}}
{...form}
{...props}
>
Expand Down
2 changes: 2 additions & 0 deletions packages/webapp/src/components/Form/DropDownButton/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export default function DropdownButton({
type,
classes: propClasses = {},
menuPositionOffset,
disabled = false,
}) {
const classes = useStyles();
const [isOpen, setOpen] = useState(defaultOpen);
Expand Down Expand Up @@ -68,6 +69,7 @@ export default function DropdownButton({
aria-controls={isOpen ? 'composition-menu' : undefined}
aria-expanded={isOpen ? 'true' : undefined}
aria-haspopup="true"
disabled={disabled}
>
{children}
{!noIcon && (
Expand Down
4 changes: 3 additions & 1 deletion packages/webapp/src/components/Menu/MeatballsMenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ import styles from './styles.module.scss';
export type MeatballsMenuProps = {
classes?: { button?: string };
options: { label: ReactNode; onClick: () => void }[];
disabled: boolean;
};

const MeatballsMenu = ({ options, classes }: MeatballsMenuProps) => {
const MeatballsMenu = ({ options, classes, disabled = false }: MeatballsMenuProps) => {
return (
<DropdownButton
type={'v2'}
Expand All @@ -39,6 +40,7 @@ const MeatballsMenu = ({ options, classes }: MeatballsMenuProps) => {
/>
))}
menuPositionOffset={[0, 1]}
disabled={disabled}
>
<BsThreeDots className={styles.menuIcon} />
</DropdownButton>
Expand Down
4 changes: 2 additions & 2 deletions packages/webapp/src/containers/Animals/AddAnimals/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function AddAnimals({ isCompactSideMenu, history }: AddAnimalsProps) {

const onSave = async (
data: any,
onGoForward: () => void,
onSuccess: () => void,
setFormResultData: (data: any) => void,
) => {
const details = data[STEPS.DETAILS] as AnimalDetailsFormFields[];
Expand Down Expand Up @@ -99,7 +99,7 @@ function AddAnimals({ isCompactSideMenu, history }: AddAnimalsProps) {
}

setFormResultData({ animals: animalsResult, batches: batchesResult });
onGoForward();
onSuccess();
};

const getFormSteps = () => [
Expand Down
Loading

0 comments on commit bd04b17

Please sign in to comment.