Skip to content

Commit

Permalink
Add confirmation modal
Browse files Browse the repository at this point in the history
  • Loading branch information
serjonya-trili committed Sep 5, 2023
1 parent 20069e6 commit 44c23a7
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 6 deletions.
38 changes: 38 additions & 0 deletions src/components/ConfirmationModal.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { fireEvent, render, screen } from "../mocks/testUtils";
import { ConfirmationModal } from "./ConfirmationModal";

describe("<ConfirmationModal />", () => {
it("shows title", () => {
render(<ConfirmationModal title="Some title" buttonLabel="test" onSubmit={jest.fn()} />);
expect(screen.getByRole("heading")).toHaveTextContent("Some title");
});

it("shows description", () => {
render(
<ConfirmationModal
title="Some title"
description="Some description"
buttonLabel="test"
onSubmit={jest.fn()}
/>
);
expect(screen.getByTestId("description")).toHaveTextContent("Some description");
});

it("doesn't render body if no description is provided", () => {
render(<ConfirmationModal title="Some title" buttonLabel="test" onSubmit={jest.fn()} />);
expect(screen.queryByTestId("description")).not.toBeInTheDocument();
});

it("executes the passed in onSubmit callback", () => {
const onSubmit = jest.fn();
render(
<ConfirmationModal title="Some title" buttonLabel="Do dangerous things" onSubmit={onSubmit} />
);
const submitButton = screen.getByRole("button", { name: "Do dangerous things" });
expect(submitButton).toBeInTheDocument();

fireEvent.click(submitButton);
expect(onSubmit).toHaveBeenCalledTimes(1);
});
});
52 changes: 52 additions & 0 deletions src/components/ConfirmationModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
Box,
Button,
Heading,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
Text,
} from "@chakra-ui/react";
import { useContext } from "react";
import { DynamicModalContext } from "./DynamicModal";
import WarningIcon from "../assets/icons/Warning";
import colors from "../style/colors";

export const ConfirmationModal: React.FC<{
title: string;
buttonLabel: string;
description?: string;
onSubmit: () => void;
}> = ({ title, description, buttonLabel, onSubmit }) => {
const { onClose } = useContext(DynamicModalContext);
const onClick = () => {
onSubmit();
onClose();
};

return (
<ModalContent>
<ModalHeader textAlign="center">
<Box>
<WarningIcon w="40px" h="40px" mb="16px" />
</Box>
<Heading>{title}</Heading>
<ModalCloseButton />
</ModalHeader>
{description && (
<ModalBody>
<Text align="center" color={colors.gray[400]} data-testid="description">
{description}
</Text>
</ModalBody>
)}
<ModalFooter>
<Button w="100%" onClick={onClick} variant="warning">
{buttonLabel}
</Button>
</ModalFooter>
</ModalContent>
);
};
9 changes: 6 additions & 3 deletions src/components/DynamicModal.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Modal, ModalOverlay, useDisclosure } from "@chakra-ui/react";
import { Modal, ModalOverlay, ModalProps, useDisclosure } from "@chakra-ui/react";
import { createContext, ReactElement, useState } from "react";

// this should be used in components as useContext(DynamicModalContext);
export const DynamicModalContext = createContext<{
openWith: (content: ReactElement) => Promise<void>;
openWith: (content: ReactElement, size?: ModalProps["size"]) => Promise<void>;
onClose: () => void;
isOpen: boolean;
}>({
Expand All @@ -24,8 +24,10 @@ export const DynamicModalContext = createContext<{
export const useDynamicModal = () => {
const { isOpen, onClose, onOpen } = useDisclosure();
const [modalContent, setModalContent] = useState<ReactElement | null>(null);
const [size, setSize] = useState<ModalProps["size"]>("md");

const openWith = async (content: ReactElement) => {
const openWith = async (content: ReactElement, size: ModalProps["size"] = "md") => {
setSize(size);
setModalContent(content);
onOpen();
};
Expand All @@ -40,6 +42,7 @@ export const useDynamicModal = () => {
onClose={onClose}
closeOnOverlayClick={false}
autoFocus={false}
size={size}
isCentered
>
<ModalOverlay />
Expand Down
1 change: 1 addition & 0 deletions src/utils/hooks/confirmModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from "@chakra-ui/react";
import { useRef } from "react";

// TODO: replace with ConfirmationModal
export const useConfirmation = () => {
const { isOpen, onOpen, onClose } = useDisclosure();

Expand Down
22 changes: 19 additions & 3 deletions src/views/batch/BatchView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
Tooltip,
Image,
} from "@chakra-ui/react";
import React from "react";
import React, { useContext } from "react";
import { AccountOperations } from "../../components/sendForm/types";
import { Operation } from "../../types/Operation";
import { prettyTezAmount } from "../../utils/format";
Expand Down Expand Up @@ -40,13 +40,16 @@ import {
} from "../../types/Token";
import { getIPFSurl } from "../../utils/token/nftUtils";
import { compact } from "lodash";
import { DynamicModalContext } from "../../components/DynamicModal";
import { ConfirmationModal } from "../../components/ConfirmationModal";
import { Account } from "../../types/Account";

const RightHeader = ({
operations: { type: operationsType, sender, operations },
}: {
operations: AccountOperations;
}) => {
const clearBatch = useClearBatch();
const { openWith } = useContext(DynamicModalContext);
return (
<Box justifyContent="space-between" alignItems="center">
<Text color={colors.gray[400]} size="sm" display="inline-block">
Expand All @@ -56,7 +59,7 @@ const RightHeader = ({
{headerText(operationsType, "batch")}
</Button>
<IconButton
onClick={() => clearBatch(sender)} // TODO: add a confirmation modal
onClick={() => openWith(<ClearBatchConfirmationModal sender={sender} />, "sm")}
aria-label="remove-batch"
ml="18px"
variant="circle"
Expand All @@ -83,6 +86,19 @@ const prettyOperationType = (operation: Operation) => {
}
};

const ClearBatchConfirmationModal = ({ sender }: { sender: Account }) => {
const clearBatch = useClearBatch();

return (
<ConfirmationModal
title="Are you sure?"
description="It will remove all the transactions from the batch."
onSubmit={() => clearBatch(sender)}
buttonLabel="Clear"
/>
);
};

export const tokenTitle = (token: Token | undefined, amount: string) => {
const name = token ? tokenName(token) : undefined;

Expand Down

0 comments on commit 44c23a7

Please sign in to comment.