diff --git a/src/components/common/ModalWindow.jsx b/src/components/common/ModalWindow.jsx
index e6aeb84..22418fe 100644
--- a/src/components/common/ModalWindow.jsx
+++ b/src/components/common/ModalWindow.jsx
@@ -4,6 +4,7 @@ import styled from '@emotion/styled';
import { css } from '@emotion/react';
import Button from '../../styles/Button';
+import palette from '../../styles/palette';
const ModalWindowWrapper = styled.div`
position: fixed;
@@ -57,10 +58,13 @@ const ModalBoxWrapper = styled.div`
`;
const StyledButton = styled(Button)`
- height: 2rem;
- & + & {
- margin-left: 0.75rem;
+ &:last-of-type {
+ margin-left: .7rem;
}
+
+ ${(props) => props.cancel && css`
+ border: 2px solid ${palette.gray[7]};
+ `}
`;
const ModalWindow = ({
@@ -82,7 +86,7 @@ const ModalWindow = ({
-
{cancelText}
+
{cancelText}
{onConfirm && (
{confirmText}
)}
diff --git a/src/components/introduce/IntroduceHeader.jsx b/src/components/introduce/IntroduceHeader.jsx
index 940303a..53808ae 100644
--- a/src/components/introduce/IntroduceHeader.jsx
+++ b/src/components/introduce/IntroduceHeader.jsx
@@ -7,6 +7,7 @@ import { changeDateToTime, isCheckedTimeStatus } from '../../util/utils';
import ApplyStatusButton from './ApplyStatusButton';
import AskLoginModal from './modals/AskLoginModal';
+import AskApplyCancelModal from './modals/AskApplyCancelModal';
const IntroduceHeaderWrapper = styled.div`
border-bottom: 2px solid ${palette.gray[4]};
@@ -24,7 +25,8 @@ const IntroduceHeaderWrapper = styled.div`
const IntroduceHeader = ({
group, onApply, user, realTime, onApplyCancel,
}) => {
- const [modal, setModal] = useState(false);
+ const [loginCheckModal, setLoginCheckModal] = useState(false);
+ const [applyCancelModal, setApplyCancelModal] = useState(false);
const {
title, moderatorId, participants, applyEndDate,
@@ -32,17 +34,26 @@ const IntroduceHeader = ({
const applyEndTime = changeDateToTime(applyEndDate);
- const onApplyClick = () => {
- setModal(true);
+ const handleApplyCancelConfirmClick = () => {
+ setApplyCancelModal(true);
};
- const handleCancel = () => {
- setModal(false);
+ const handleLoginCheckCancel = () => {
+ setLoginCheckModal(false);
+ };
+
+ const handleApplyCancel = () => {
+ setApplyCancelModal(false);
+ };
+
+ const handleApplyCancelConfirm = () => {
+ setApplyCancelModal(false);
+ onApplyCancel();
};
const handleApply = () => {
if (!user) {
- onApplyClick();
+ setLoginCheckModal(true);
return;
}
@@ -56,12 +67,20 @@ const IntroduceHeader = ({
<>
-
+
+
>
)}
diff --git a/src/components/introduce/IntroduceHeader.test.jsx b/src/components/introduce/IntroduceHeader.test.jsx
index e6d9678..e6b3dc5 100644
--- a/src/components/introduce/IntroduceHeader.test.jsx
+++ b/src/components/introduce/IntroduceHeader.test.jsx
@@ -47,16 +47,36 @@ describe('IntroduceHeader', () => {
personnel: 3,
};
- it('Call the cancel application button.', () => {
- const { getByText } = renderIntroduceHeader({ group, user: 'user', time });
+ context('click confirm', () => {
+ it('Call the cancel application button.', () => {
+ const { getByText } = renderIntroduceHeader({ group, user: 'user', time });
- const button = getByText('신청 취소');
+ const button = getByText('신청 취소');
- expect(button).not.toBeNull();
+ expect(button).not.toBeNull();
+
+ fireEvent.click(button);
+
+ fireEvent.click(getByText('확인'));
+
+ expect(handleApplyCancel).toBeCalled();
+ });
+ });
- fireEvent.click(button);
+ context('click cancel', () => {
+ it("doesn't call the cancel application button.", () => {
+ const { getByText } = renderIntroduceHeader({ group, user: 'user', time });
- expect(handleApplyCancel).toBeCalled();
+ const button = getByText('신청 취소');
+
+ expect(button).not.toBeNull();
+
+ fireEvent.click(button);
+
+ fireEvent.click(getByText('취소'));
+
+ expect(handleApplyCancel).not.toBeCalled();
+ });
});
});
diff --git a/src/components/introduce/modals/AskApplyCancelModal.jsx b/src/components/introduce/modals/AskApplyCancelModal.jsx
new file mode 100644
index 0000000..455b656
--- /dev/null
+++ b/src/components/introduce/modals/AskApplyCancelModal.jsx
@@ -0,0 +1,15 @@
+import React from 'react';
+
+import ModalWindow from '../../common/ModalWindow';
+
+const AskApplyCancelModal = ({ visible, onCancel, onConfirm }) => (
+
+);
+
+export default AskApplyCancelModal;
diff --git a/src/components/introduce/modals/AskApplyCancelModal.test.jsx b/src/components/introduce/modals/AskApplyCancelModal.test.jsx
new file mode 100644
index 0000000..75d8f78
--- /dev/null
+++ b/src/components/introduce/modals/AskApplyCancelModal.test.jsx
@@ -0,0 +1,63 @@
+import React from 'react';
+
+import { fireEvent, render } from '@testing-library/react';
+
+import AskApplyCancelModal from './AskApplyCancelModal';
+
+describe('AskApplyCancelModal', () => {
+ const handleCancel = jest.fn();
+ const handleConfirm = jest.fn();
+
+ const renderAskApplyCancelModal = ({ visible }) => render((
+
+ ));
+
+ context('with visible', () => {
+ const modal = {
+ visible: true,
+ };
+
+ it('renders Modal text', () => {
+ const { container } = renderAskApplyCancelModal(modal);
+
+ expect(container).toHaveTextContent('신청 취소');
+ expect(container).toHaveTextContent('스터디 그룹 신청을 취소하시겠습니까?');
+ });
+
+ it('calls confirm event action', () => {
+ const { getByText } = renderAskApplyCancelModal(modal);
+
+ const button = getByText('확인');
+
+ fireEvent.click(button);
+
+ expect(handleConfirm).toBeCalled();
+ });
+
+ it('calls cancel event action', () => {
+ const { getByText } = renderAskApplyCancelModal(modal);
+
+ const button = getByText('취소');
+
+ fireEvent.click(button);
+
+ expect(handleCancel).toBeCalled();
+ });
+ });
+
+ context('without visible', () => {
+ const modal = {
+ visible: false,
+ };
+
+ it("doesn't renders Modal text", () => {
+ const { container } = renderAskApplyCancelModal(modal);
+
+ expect(container).toBeEmptyDOMElement();
+ });
+ });
+});
diff --git a/src/containers/introduce/IntroduceContainer.test.jsx b/src/containers/introduce/IntroduceContainer.test.jsx
index 6e3e9c9..334b521 100644
--- a/src/containers/introduce/IntroduceContainer.test.jsx
+++ b/src/containers/introduce/IntroduceContainer.test.jsx
@@ -110,18 +110,40 @@ describe('IntroduceContainer', () => {
given('group', () => (group));
given('user', () => ('user'));
- it('click event dispatches action call deleteParticipant', () => {
- const { getByText } = renderIntroduceContainer(1);
+ context('click confirm', () => {
+ it('click event dispatches action call deleteParticipant', () => {
+ const { getByText } = renderIntroduceContainer(1);
- expect(dispatch).toBeCalledTimes(1);
+ expect(dispatch).toBeCalledTimes(1);
- const button = getByText('신청 취소');
+ const button = getByText('신청 취소');
- expect(button).not.toBeNull();
+ expect(button).not.toBeNull();
- fireEvent.click(button);
+ fireEvent.click(button);
- expect(dispatch).toBeCalledTimes(2);
+ fireEvent.click(getByText('확인'));
+
+ expect(dispatch).toBeCalledTimes(2);
+ });
+ });
+
+ context('click cancel', () => {
+ it("doesn't click event dispatches action call deleteParticipant", () => {
+ const { getByText } = renderIntroduceContainer(1);
+
+ expect(dispatch).toBeCalledTimes(1);
+
+ const button = getByText('신청 취소');
+
+ expect(button).not.toBeNull();
+
+ fireEvent.click(button);
+
+ fireEvent.click(getByText('취소'));
+
+ expect(dispatch).toBeCalledTimes(1);
+ });
});
});
});