Skip to content

Commit

Permalink
Merge pull request #760 from wri/feat/TM-1578-duplicate-species-names
Browse files Browse the repository at this point in the history
[TM-1578] Prevent adding a species that is already on the list.
  • Loading branch information
roguenet authored Dec 18, 2024
2 parents 94605d6 + f5766aa commit 8f5ac93
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { useT } from "@transifex/react";

import Button from "@/components/elements/Button/Button";
import TreeSpeciesModal from "@/components/elements/Inputs/TreeSpeciesInput/TreeSpeciesModal";
import { ModalId } from "@/components/extensive/Modal/ModalConst";
import { useModalContext } from "@/context/modal.provider";

const NonScientificConfirmationModal = ({ onConfirm }: { onConfirm: () => void }) => {
const t = useT();
const { closeModal } = useModalContext();

return (
<TreeSpeciesModal
title={t("Your input is a not a scientific name")}
content={t("You can add this species, but it will be pending review from Admin.")}
buttons={
<>
<Button variant="secondary" onClick={() => closeModal(ModalId.ERROR_MODAL)}>
{t("CANCEL")}
</Button>
<Button
variant="primary"
onClick={() => {
closeModal(ModalId.ERROR_MODAL);
onConfirm();
}}
>
{t("CONFIRM")}
</Button>
</>
}
/>
);
};

export default NonScientificConfirmationModal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useT } from "@transifex/react";

import Button from "@/components/elements/Button/Button";
import TreeSpeciesModal from "@/components/elements/Inputs/TreeSpeciesInput/TreeSpeciesModal";
import { ModalId } from "@/components/extensive/Modal/ModalConst";
import { useModalContext } from "@/context/modal.provider";

const SpeciesAlreadyExistsModal = ({ speciesName }: { speciesName: string }) => {
const { closeModal } = useModalContext();
const t = useT();

return (
<TreeSpeciesModal
title={t("Species {name} already included", { name: speciesName })}
content={t("Please find species below to enter reported value.")}
buttons={
<>
<Button variant="secondary" onClick={() => closeModal(ModalId.ERROR_MODAL)}>
{t("CONTINUE")}
</Button>
</>
}
/>
);
};

export default SpeciesAlreadyExistsModal;
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { FieldError, FieldErrors } from "react-hook-form";
import { Else, If, Then, When } from "react-if";
import { v4 as uuidv4 } from "uuid";

import NonScientificConfirmationModal from "@/components/elements/Inputs/TreeSpeciesInput/NonScientificConfirmationModal";
import SpeciesAlreadyExistsModal from "@/components/elements/Inputs/TreeSpeciesInput/SpeciesAlreadyExistsModal";
import { useAutocompleteSearch } from "@/components/elements/Inputs/TreeSpeciesInput/useAutocompleteSearch";
import Icon, { IconNames } from "@/components/extensive/Icon/Icon";
import List from "@/components/extensive/List/List";
Expand Down Expand Up @@ -43,45 +45,6 @@ export interface TreeSpeciesInputProps extends Omit<InputWrapperProps, "error">

export type TreeSpeciesValue = { uuid?: string; name?: string; taxon_id?: string; amount?: number };

const NonScientificConfirmationModal = ({ onConfirm }: { onConfirm: () => void }) => {
const t = useT();
const { closeModal } = useModalContext();

return (
<div className="margin-4 z-50 m-auto flex max-h-full flex-col items-center justify-start overflow-y-auto rounded-lg border-2 border-neutral-100 bg-white">
<div className="flex w-full items-center justify-center gap-1 border-b-2 border-neutral-100 py-1">
<Icon name={IconNames.EXCLAMATION_CIRCLE_FILL} className="min-h-4 min-w-4 mb-1 h-4 w-4 text-tertiary-600" />
<Text variant="text-16-semibold" className="mb-1 text-blueCustom-700">
{t("Your input is a not a scientific name")}
</Text>
</div>
<div className="w-full p-4">
<div className="w-full rounded-lg border border-dashed bg-neutral-250 p-2">
<div className="flex items-center gap-1">
<Text variant="text-14-light" className="text-blueCustom-700">
{t("You can add this species, but it will be pending review from Admin.")}
</Text>
</div>
</div>
<div className="mt-4 flex w-full justify-end gap-3">
<Button variant="secondary" onClick={() => closeModal(ModalId.ERROR_MODAL)}>
{t("CANCEL")}
</Button>
<Button
variant="primary"
onClick={() => {
closeModal(ModalId.ERROR_MODAL);
onConfirm();
}}
>
{t("CONFIRM")}
</Button>
</div>
</div>
</div>
);
};

const TreeSpeciesInput = (props: TreeSpeciesInputProps) => {
const id = useId();
const t = useT();
Expand Down Expand Up @@ -183,8 +146,11 @@ const TreeSpeciesInput = (props: TreeSpeciesInputProps) => {
lastInputRef.current?.focus();
};

if (!isEmpty(searchResult) && taxonId == null) {
// In this case the use had valid values to choose from, but decided to add a value that isn't
if (value.find(({ name }) => name === valueAutoComplete) != null) {
openModal(ModalId.ERROR_MODAL, <SpeciesAlreadyExistsModal speciesName={valueAutoComplete} />);
setValueAutoComplete("");
} else if (!isEmpty(searchResult) && taxonId == null) {
// In this case the user had valid values to choose from, but decided to add a value that isn't
// on the list, so they haven't been shown the warning yet.
openModal(ModalId.ERROR_MODAL, <NonScientificConfirmationModal onConfirm={doAdd} />);
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ReactNode } from "react";

import Text from "@/components/elements/Text/Text";
import Icon, { IconNames } from "@/components/extensive/Icon/Icon";

type TreeSpeciesModalProps = {
title: string;
content: string;
buttons: ReactNode;
};

const TreeSpeciesModal = ({ title, content, buttons }: TreeSpeciesModalProps) => (
<div className="margin-4 z-50 m-auto flex max-h-full flex-col items-center justify-start overflow-y-auto rounded-lg border-2 border-neutral-100 bg-white">
<div className="flex w-full items-center justify-center gap-1 border-b-2 border-neutral-100 py-1">
<Icon name={IconNames.EXCLAMATION_CIRCLE_FILL} className="min-h-4 min-w-4 mb-1 h-4 w-4 text-tertiary-600" />
<Text variant="text-16-semibold" className="mb-1 text-blueCustom-700">
{title}
</Text>
</div>
<div className="w-full p-4">
<div className="w-full rounded-lg border border-dashed bg-neutral-250 p-2">
<div className="flex items-center gap-1">
<Text variant="text-14-light" className="text-blueCustom-700">
{content}
</Text>
</div>
</div>
<div className="mt-4 flex w-full justify-end gap-3">{buttons}</div>
</div>
</div>
);

export default TreeSpeciesModal;

0 comments on commit 8f5ac93

Please sign in to comment.