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

Hotfix: 예약현황 모달창 바깥 클릭시 닫히는 기능 추가 #330

Merged
merged 1 commit into from
Apr 4, 2024
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
46 changes: 31 additions & 15 deletions src/components/calendar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useEffect, useRef, useState } from 'react';

import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import classNames from 'classnames/bind';
Expand Down Expand Up @@ -47,6 +47,8 @@ const Calendar = ({ gameId }: CalendarProps) => {
const { multiState, toggleClick } = useMultiState(['scheduleModal', 'confirmModal', 'errorModal']);
const currentDeviceType = useDeviceType();

const modalRef = useRef<HTMLDivElement>(null);

const yearString = currentYear.toString();
const monthString = currentMonth.toString().padStart(2, '0');

Expand Down Expand Up @@ -75,7 +77,7 @@ const Calendar = ({ gameId }: CalendarProps) => {
queryKey: QUERY_KEYS.myActivities.getDetailReservationList(gameId, scheduleId!, 'pending'),
});
},
onError: () => toggleClick('errorModal'),
onError: () => handleToggleErrorModal(),
});

const dropdownOptions = getScheduleDropdownOption(dailySchedules);
Expand All @@ -98,39 +100,52 @@ const Calendar = ({ gameId }: CalendarProps) => {
const handleScheduleClick = (date: string) => {
setActiveDate(date);

toggleClick('scheduleModal');
handleToggleScheduleModal();
};

const handleConfirmClick = (scheduleId: number, reservationId: number, status: ReservationStatus) => {
setScheduleId(scheduleId);
setReservationId(reservationId);
setReservationStatus(status);

toggleClick('scheduleModal');
toggleClick('confirmModal');
handleToggleScheduleModal();
handleToggleConfirmModal();
};

const handleChangeReservationStatus = () => {
changeStatusMutation({ activityId: gameId, reservationId: reservationId!, status: { status: reservationStatus } });
toggleClick('confirmModal');
handleToggleConfirmModal();
};

const handleCloseScheduleModal = () => {
const handleToggleScheduleModal = () => {
toggleClick('scheduleModal');
};

const handleCloseConfirmModal = () => {
const handleToggleConfirmModal = () => {
toggleClick('confirmModal');
};

const handleCloseErrorModal = () => {
const handleToggleErrorModal = () => {
toggleClick('errorModal');
};

useEffect(() => {
if (currentDeviceType !== 'PC') setIsCalendar(false);
}, [currentDeviceType]);

useEffect(() => {
const listener = (event: MouseEvent) => {
if (!modalRef.current || modalRef.current.contains(event.target as Node)) return;
handleToggleScheduleModal();
};

document.addEventListener('mousedown', listener);

return () => {
document.removeEventListener('mousedown', listener);
};
}, [modalRef, handleToggleScheduleModal]);

return (
<>
<div className={cx('calendar-container')}>
Expand All @@ -155,16 +170,17 @@ const Calendar = ({ gameId }: CalendarProps) => {
{isSuccess && dropdownOptions.length !== 0 && (
<CustomCommonModal
openModal={multiState.scheduleModal}
onClose={handleCloseScheduleModal}
onClose={handleToggleScheduleModal}
title={'예약 정보'}
isCalendar={isCalendar}
modalRef={modalRef}
renderContent={
<ModalContents
gameId={gameId}
activeDate={activeDate}
dropdownOptions={dropdownOptions}
statusCountByScheduleId={statusCountByScheduleId}
onClickCloseButton={handleCloseScheduleModal}
onClickCloseButton={handleToggleScheduleModal}
onClickCardButton={handleConfirmClick}
/>
}
Expand All @@ -174,7 +190,7 @@ const Calendar = ({ gameId }: CalendarProps) => {
<ConfirmModal
warning
openModal={multiState.confirmModal}
onClose={handleCloseConfirmModal}
onClose={handleToggleConfirmModal}
state='CONFIRM'
title={`예약 신청을 ${MY_RESERVATIONS_STATUS[reservationStatus]}하시겠습니까?`}
desc={`한번 ${MY_RESERVATIONS_STATUS[reservationStatus]}한 예약은 되돌릴 수 없습니다`}
Expand All @@ -183,17 +199,17 @@ const Calendar = ({ gameId }: CalendarProps) => {
<ModalButton variant='warning' onClick={handleChangeReservationStatus}>
확인
</ModalButton>
<ModalButton onClick={handleCloseConfirmModal}>취소</ModalButton>
<ModalButton onClick={handleToggleConfirmModal}>취소</ModalButton>
</>
}
/>
<ConfirmModal
warning
openModal={multiState.errorModal}
onClose={handleCloseErrorModal}
onClose={handleToggleErrorModal}
state='ERROR'
title={`예약 ${MY_RESERVATIONS_STATUS[reservationStatus]}에 실패하였습니다.`}
renderButton={<ModalButton onClick={handleCloseErrorModal}>닫기</ModalButton>}
renderButton={<ModalButton onClick={handleToggleErrorModal}>닫기</ModalButton>}
></ConfirmModal>
</>
);
Expand Down
18 changes: 15 additions & 3 deletions src/components/commons/modals/CustomCommonModal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Image from 'next/image';

import { ReactNode, MouseEventHandler, useState, useEffect } from 'react';
import { ReactNode, MouseEventHandler, useState, useEffect, RefObject } from 'react';

import classNames from 'classnames/bind';

Expand All @@ -18,9 +18,17 @@ type CustomCommonModalProps = {
title: string;
renderContent: ReactNode;
isCalendar: boolean;
modalRef: RefObject<HTMLDivElement>;
};

export const CustomCommonModal = ({ openModal, onClose, title, renderContent, isCalendar }: CustomCommonModalProps) => {
export const CustomCommonModal = ({
openModal,
onClose,
title,
renderContent,
isCalendar,
modalRef,
}: CustomCommonModalProps) => {
const [isOpen, setIsOpen] = useState(false);

useEffect(() => {
Expand All @@ -38,7 +46,11 @@ export const CustomCommonModal = ({ openModal, onClose, title, renderContent, is
return (
isOpen && (
<div className={cx('overlay', { calendar: isCalendar })}>
<div className={cx('modal', 'calendar', { open: openModal })} onAnimationEnd={handleAnimationEnd}>
<div
ref={modalRef}
className={cx('modal', 'calendar', { open: openModal })}
onAnimationEnd={handleAnimationEnd}
>
<div className={cx('modal-inner')}>
<header className={cx('modal-header')}>
<div className={cx('lg-hidden')}>
Expand Down