Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LF-4165: Create animal creation summary container #3382

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/webapp/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@
"ADD_MORE_BODY_TEXT": "Do you have another animal type or a different breed?",
"ADD_MORE_BUTTON": "Add more animals",
"ANIMAL_BREED": "Breed",
"ANIMAL_COUNT_one": "{{count}} animal",
"ANIMAL_COUNT_other": "{{count}} animals",
"ANIMAL_GROUPS": "Group",
"ANIMAL_ID": "ID",
"ANIMAL_IDENTIFICATION": "Identification",
Expand Down
2 changes: 2 additions & 0 deletions packages/webapp/public/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@
"ADD_MORE_BODY_TEXT": "MISSING",
"ADD_MORE_BUTTON": "MISSING",
"ANIMAL_BREED": "MISSING",
"ANIMAL_COUNT_one": "MISSING",
"ANIMAL_COUNT_other": "MISSING",
"ANIMAL_GROUPS": "MISSING",
"ANIMAL_ID": "MISSING",
"ANIMAL_IDENTIFICATION": "MISSING",
Expand Down
2 changes: 2 additions & 0 deletions packages/webapp/public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@
"ADD_MORE_BODY_TEXT": "MISSING",
"ADD_MORE_BUTTON": "MISSING",
"ANIMAL_BREED": "MISSING",
"ANIMAL_COUNT_one": "MISSING",
"ANIMAL_COUNT_other": "MISSING",
"ANIMAL_GROUPS": "MISSING",
"ANIMAL_ID": "MISSING",
"ANIMAL_IDENTIFICATION": "MISSING",
Expand Down
2 changes: 2 additions & 0 deletions packages/webapp/public/locales/pt/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@
"ADD_MORE_BODY_TEXT": "MISSING",
"ADD_MORE_BUTTON": "MISSING",
"ANIMAL_BREED": "MISSING",
"ANIMAL_COUNT_one": "MISSING",
"ANIMAL_COUNT_other": "MISSING",
"ANIMAL_GROUPS": "MISSING",
"ANIMAL_ID": "MISSING",
"ANIMAL_IDENTIFICATION": "MISSING",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ export const IconSummary = ({
{!isBatch && ':'}
</Main>
<div className={styles.details}>
{isBatch ? <BatchDetails count={count} /> : <AnimalDetails sexDetails={sexDetails} />}
{isBatch ? (
<BatchDetails count={count} />
) : (
<AnimalDetails sexDetails={sexDetails} animalCount={count} />
)}
</div>
</div>
</div>
Expand All @@ -65,17 +69,25 @@ const BatchDetails = ({ count }: { count: number }) => {
);
};

const AnimalDetails = ({ sexDetails }: { sexDetails: AnimalSexCountSummary }) => {
const AnimalDetails = ({
sexDetails,
animalCount,
}: {
sexDetails: AnimalSexCountSummary;
animalCount: number;
}) => {
const { t } = useTranslation();
const sexCountEntries = Object.entries(sexDetails);

const renderSexCountEntries = () => {
return sexCountEntries.length
? `(${sexCountEntries.map(([sex, count]) => `${count} ${sex}`).join(' / ')})`
: '';
};

return (
<Main className={styles.detailText}>
{sexCountEntries.map(([sex, count], index) => {
return (
<span key={sex}>
{count} {sex} {index < sexCountEntries.length - 1 ? '/ ' : ''}
</span>
);
})}
{t('ANIMAL.ANIMAL_COUNT', { count: animalCount })} {renderSexCountEntries()}
</Main>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { Title, Main } from '../../Typography';
import { ReactComponent as RelaxedFarmer } from '../../../assets/images/animals/relaxed-farmer.svg';
import { ReactComponent as ChevronRight } from '../../../assets/images/buttons/chevron-right.svg';
import Button from '../../Form/Button';
import { sumObjectValues } from '../../../util';
import { IconSummary } from './IconSummary';
import { iconNames } from '../../../containers/Animals/constants';
import { AnimalSummary, BatchSummary } from './types';
Expand All @@ -41,7 +40,7 @@ export const AddAnimalsSummaryCard = ({
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));

const numberOfAnimals = animalsInfo.reduce((acc, animal) => {
return acc + sumObjectValues(animal.sexDetails);
return acc + animal.count;
}, 0);
const numberOfBatches = batchInfo.length;

Expand Down Expand Up @@ -112,6 +111,7 @@ const IconSummaryAndButton = ({
iconKey={animalIconKey}
type={animal.type}
breed={animal.breed}
count={animal.count}
/>
);
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface AnimalSummary {
breed?: string;
sexDetails: AnimalSexCountSummary;
iconKey: string;
count?: never;
count: number;
}

export interface BatchSummary {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,12 @@ export const MultiStepForm = ({
{...props}
>
<FormProvider {...form}>
<FormContent onGoForward={onGoForward} form={form} formResultData={formResultData} />
<FormContent
onGoForward={onGoForward}
form={form}
formResultData={formResultData}
history={history}
/>
</FormProvider>
</Component>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,41 @@
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

import { History } from 'history';
import { AddAnimalsSummaryCard } from '../../../../components/Animals/AddAnimalsSummaryCard';
import { ANIMALS_INVENTORY_URL } from '../../../../util/siteMapConstants';
import {
useGetAnimalSexesQuery,
useGetCustomAnimalBreedsQuery,
useGetCustomAnimalTypesQuery,
useGetDefaultAnimalBreedsQuery,
useGetDefaultAnimalTypesQuery,
} from '../../../../store/api/apiSlice';
import useQueries from '../../../../hooks/api/useQueries';
import { formatDBAnimalsToSummary, formatDBBatchesToSummary } from '../../AddAnimals/utils';
import { Animal, AnimalBatch } from '../../../../store/api/types';

type AddAnimalSummaryProps = {
history: History;
formResultData: { animals: Animal[]; batches: AnimalBatch[] };
};

const AddAnimalSummary = ({ formResultData }: AddAnimalSummaryProps) => {
return <div>Add animal summary</div>;
const AddAnimalSummary = ({ formResultData, history }: AddAnimalSummaryProps) => {
const { data: config, isLoading } = useQueries([
{ label: 'defaultTypes', hook: useGetDefaultAnimalTypesQuery },
{ label: 'customTypes', hook: useGetCustomAnimalTypesQuery },
{ label: 'defaultBreeds', hook: useGetDefaultAnimalBreedsQuery },
{ label: 'customBreeds', hook: useGetCustomAnimalBreedsQuery },
{ label: 'sexes', hook: useGetAnimalSexesQuery },
]);

return (
<AddAnimalsSummaryCard
animalsInfo={isLoading ? [] : formatDBAnimalsToSummary(formResultData.animals, config)}
batchInfo={isLoading ? [] : formatDBBatchesToSummary(formResultData.batches, config)}
onContinue={() => history.push(ANIMALS_INVENTORY_URL)}
/>
);
};

export default AddAnimalSummary;
109 changes: 109 additions & 0 deletions packages/webapp/src/containers/Animals/AddAnimals/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,23 @@
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

import i18n from '../../../locales/i18n';

import {
AnimalSummary,
BatchSummary,
} from '../../../components/Animals/AddAnimalsSummaryCard/types';
import {
Animal,
AnimalBatch,
AnimalSex,
CustomAnimalBreed,
CustomAnimalType,
DefaultAnimalBreed,
DefaultAnimalType,
} from '../../../store/api/types';
import { chooseAnimalBreedLabel, chooseAnimalTypeLabel } from '../Inventory/useAnimalInventory';

// TODO
export const formatAnimalDetailsToDBStructure = (data: any) => {
return data;
Expand All @@ -21,3 +38,95 @@ export const formatAnimalDetailsToDBStructure = (data: any) => {
export const formatBatchDetailsToDBStructure = (data: any) => {
return data;
};

export const getSexMap = (
sexConfig: AnimalSex[],
translateKey?: boolean,
): { [key: number]: string } => {
return sexConfig.reduce(
(acc, { id, key }) => ({ ...acc, [id]: translateKey ? i18n.t(`animal:SEX.${key}`) : key }),
{},
);
};

export const getSexLabelById = (sexId: number, sexMap: { [key: number]: string }): string => {
return sexMap[sexId];
};

const getTypeBreedKey = (animalOrBatch: Animal | AnimalBatch): string => {
const { default_type_id, custom_type_id, default_breed_id, custom_breed_id } = animalOrBatch;
const typeKey = `${default_type_id ? 'D' : 'C'}-${default_type_id || custom_type_id}`;
let breedKey = '';
if (default_breed_id || custom_breed_id) {
breedKey = `_${default_breed_id ? 'D' : 'C'}-${default_breed_id || custom_breed_id}`;
}

return `${typeKey}_${breedKey}`;
};

interface Config {
defaultTypes: DefaultAnimalType[];
customTypes: CustomAnimalType[];
defaultBreeds: DefaultAnimalBreed[];
customBreeds: CustomAnimalBreed[];
sexes: AnimalSex[];
}

export const formatDBAnimalsToSummary = (data: Animal[], config: Config): AnimalSummary[] => {
const animalsPerTypeAndBreed = {} as { [key: string]: AnimalSummary };
const { defaultTypes, customTypes, defaultBreeds, customBreeds, sexes } = config;
const sexMap = getSexMap(sexes, true);

data.forEach((animal) => {
const typeBreedkey = getTypeBreedKey(animal);

if (!animalsPerTypeAndBreed[typeBreedkey]) {
const typeString = chooseAnimalTypeLabel(animal, defaultTypes, customTypes);
const breedString = chooseAnimalBreedLabel(animal, defaultBreeds, customBreeds);
animalsPerTypeAndBreed[typeBreedkey] = {
type: typeString,
breed: breedString,
sexDetails: {},
iconKey: typeString.toUpperCase(),
count: 0,
} as AnimalSummary;
}

const typeBreedSummary = animalsPerTypeAndBreed[typeBreedkey];

typeBreedSummary.count += 1;

const sexLabel = sexMap[animal.sex_id];

if (sexLabel) {
if (!typeBreedSummary.sexDetails[sexLabel]) {
typeBreedSummary.sexDetails[sexLabel] = 0;
}

typeBreedSummary.sexDetails[sexLabel]! += 1;
}
});

return Object.values(animalsPerTypeAndBreed);
};

export const formatDBBatchesToSummary = (data: AnimalBatch[], config: Config): BatchSummary[] => {
const batchesPerTypeAndBreed = {} as { [key: string]: BatchSummary };
const { defaultTypes, customTypes, defaultBreeds, customBreeds } = config;

data.forEach((batch) => {
const typeBreedkey = getTypeBreedKey(batch);

if (!batchesPerTypeAndBreed[typeBreedkey]) {
batchesPerTypeAndBreed[typeBreedkey] = {
type: chooseAnimalTypeLabel(batch, defaultTypes, customTypes),
breed: chooseAnimalBreedLabel(batch, defaultBreeds, customBreeds),
count: 0,
};
}

batchesPerTypeAndBreed[typeBreedkey].count += batch.count;
});

return Object.values(batchesPerTypeAndBreed);
};
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const chooseIdentification = (animalOrBatch: Animal | AnimalBatch) => {
return `${t('ANIMAL.ANIMAL_ID')}${animalOrBatch.internal_identifier}`;
};

const chooseAnimalTypeLabel = (
export const chooseAnimalTypeLabel = (
animalOrBatch: Animal | AnimalBatch,
defaultAnimalTypes: DefaultAnimalType[],
customAnimalTypes: CustomAnimalType[],
Expand All @@ -123,7 +123,7 @@ const chooseAnimalTypeLabel = (
}
};

const chooseAnimalBreedLabel = (
export const chooseAnimalBreedLabel = (
animalOrBatch: Animal | AnimalBatch,
defaultAnimalBreeds: DefaultAnimalBreed[],
customAnimalBreeds: CustomAnimalBreed[],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,25 @@ const animalsInfo = [
breed: 'Aberdeen',
sexDetails: { Male: 3, Female: 4 },
iconKey: 'CATTLE',
count: 7,
},
{
type: 'Chicken',
sexDetails: { Male: 3, Female: 3 },
iconKey: 'CHICKEN',
count: 6,
},
{
type: 'Guinea Pig',
sexDetails: { Male: 4 },
iconKey: 'GUINEA_PIG', // non-existent keys will default to CUSTOM_ANIMAL icon
count: 4,
},
{
type: 'Dog',
sexDetails: {},
iconKey: 'DOG',
count: 2,
},
];
const batchInfo = [{ type: 'Chicken', breed: 'Plymouth Rock', count: 1238 }];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const Animal: Story = {
Male: 3,
Female: 7,
},
count: 10,
},
};

Expand All @@ -49,6 +50,18 @@ export const AnimalNoBreed: Story = {
Male: 1,
Female: 2,
},
count: 3,
},
};

export const AnimalNoSexDetails: Story = {
args: {
type: 'Cattle',
breed: 'Aberdeen',
iconKey: 'CATTLE',
isBatch: false,
sexDetails: {},
count: 10,
},
};

Expand Down Expand Up @@ -77,5 +90,6 @@ export const CustomType: Story = {
sexDetails: {
Male: 3,
},
count: 3,
},
};
Loading
Loading