From 67c048a11d0e17c926a825ee92756afb765fc703 Mon Sep 17 00:00:00 2001 From: bcjang Date: Fri, 27 Jun 2025 09:28:13 +0900 Subject: [PATCH] =?UTF-8?q?=EB=A9=94=EB=89=B4=EB=B0=B0=EB=84=88=20detailGr?= =?UTF-8?q?id=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/modal/MenuBannerModal.js | 473 ++++++++++++++++++++++++ 1 file changed, 473 insertions(+) create mode 100644 src/components/modal/MenuBannerModal.js diff --git a/src/components/modal/MenuBannerModal.js b/src/components/modal/MenuBannerModal.js new file mode 100644 index 0000000..8bf43bf --- /dev/null +++ b/src/components/modal/MenuBannerModal.js @@ -0,0 +1,473 @@ +import React, { useState, Fragment, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; +import Button from '../common/button/Button'; +import Loading from '../common/Loading'; + +import { + Title, + BtnWrapper, + SearchBarAlert, SelectInput, +} from '../../styles/Components'; + +import { + FormInput, + FormLabel, + MessageWrapper, + FormRowGroup, + FormStatusBar, + FormStatusLabel, + FormStatusWarning, + FormButtonContainer, +} from '../../styles/ModuleComponents'; +import { modalTypes } from '../../assets/data'; +import { DynamicModal, Modal, SingleDatePicker, SingleTimePicker } from '../common'; +import { NONE, TYPE_MODIFY, TYPE_REGISTRY } from '../../assets/data/adminConstants'; +import { useModal } from '../../hooks/hook'; +import { convertKTCDate } from '../../utils'; +import { + battleEventHotTime, + battleEventRoundCount, + battleEventStatus, + battleRepeatType, +} from '../../assets/data/options'; +import { BattleEventModify, BattleEventSingleRegist } from '../../apis/Battle'; +import { battleEventStatusType } from '../../assets/data/types'; +import { isValidDayRange } from '../../utils/date'; + +const MenuBannerModal = ({ modalType, detailView, handleDetailView, content, setDetailData, configData, rewardData }) => { + const { t } = useTranslation(); + const token = sessionStorage.getItem('token'); + + const [loading, setLoading] = useState(false); // 로딩 창 + const { + modalState, + handleModalView, + handleModalClose + } = useModal({ + cancel: 'hidden', + registConfirm: 'hidden', + registComplete: 'hidden' + }); + + const [isNullValue, setIsNullValue] = useState(false); // 데이터 값 체크 + const [alertMsg, setAlertMsg] = useState(''); + const [resultData, setResultData] = useState(initData); //데이터 정보 + + useEffect(() => { + if(modalType === TYPE_MODIFY && content && Object.keys(content).length > 0){ + setResultData({ + group_id: content.group_id, + event_id: content.event_id, + event_name: content.event_name, + repeat_type: content.repeat_type, + config_id: content.config_id, + reward_group_id: content.reward_group_id, + round_count: content.round_count, + hot_time: content.hot_time, + round_time: content.round_time, + status: content.status, + event_start_dt: convertKTCDate(content.event_start_dt), + event_end_dt: content.event_end_dt, + event_operation_time: content.event_operation_time, + }); + } + }, [modalType, content]); + + useEffect(() => { + if(modalType === TYPE_REGISTRY && configData?.length > 0){ + setResultData(prev => ({ + ...prev, + round_count: configData[0].default_round_count + })); + } + }, [modalType, configData]); + + useEffect(() => { + if (checkCondition()) { + setIsNullValue(false); + } else { + setIsNullValue(true); + } + }, [resultData]); + + // 시작 날짜 변경 핸들러 + const handleStartDateChange = (date) => { + if (!date) return; + + const newDate = new Date(date); + + if(resultData.repeat_type !== NONE && resultData.event_end_dt){ + const endDate = new Date(resultData.event_end_dt); + const startDay = new Date(newDate.getFullYear(), newDate.getMonth(), newDate.getDate()); + const endDay = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate()); + + if (endDay <= startDay) { + setAlertMsg(t('DATE_START_DIFF_END_WARNING')); + return; + } + } + + setResultData(prev => ({ + ...prev, + event_start_dt: newDate + })); + }; + + // 시작 시간 변경 핸들러 + const handleStartTimeChange = (time) => { + if (!time) return; + + const newDateTime = resultData.event_start_dt + ? new Date(resultData.event_start_dt) + : new Date(); + + newDateTime.setHours( + time.getHours(), + time.getMinutes(), + 0, + 0 + ); + + setResultData(prev => ({ + ...prev, + event_start_dt: newDateTime + })); + }; + + // 종료 날짜 변경 핸들러 + const handleEndDateChange = (date) => { + if (!date || !resultData.event_start_dt) return; + + const startDate = new Date(resultData.event_start_dt); + const endDate = new Date(date); + + // 일자만 비교하기 위해 년/월/일만 추출 + const startDay = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate()); + const endDay = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate()); + + if (endDay <= startDay) { + setAlertMsg(t('DATE_START_DIFF_END_WARNING')); + return; + } + + setResultData(prev => ({ + ...prev, + event_end_dt: endDate + })); + }; + + const handleConfigChange = (e) => { + const config = configData.find(data => String(data.id) === String(e.target.value)); + if (config) { + setResultData({ + ...resultData, + config_id: config.id, + round_time: config.round_time + }); + } else { + console.warn('Config not found for value:', e.target.value); + } + } + + const handleReset = () => { + setDetailData({}); + setResultData(initData); + handleDetailView(); + } + + const handleSubmit = async (type, param = null) => { + switch (type) { + case "submit": + if (!checkCondition()) return; + + const minAllowedTime = new Date(new Date().getTime() + 10 * 60000); + const startDt = resultData.event_start_dt; + const endDt = resultData.event_end_dt; + if (modalType === TYPE_REGISTRY && startDt < minAllowedTime) { + setAlertMsg(t('BATTLE_EVENT_MODAL_START_DT_WARNING')); + return; + } + if(resultData.repeat_type !== 'NONE' && !isValidDayRange(startDt, endDt)) { + setAlertMsg(t('DATE_START_DIFF_END_WARNING')) + return; + } + + //화면에 머물면서 상태는 안바꼈을 경우가 있기에 시작시간 지났을경우 차단 + if (modalType === TYPE_REGISTRY && startDt < new Date()) { + setAlertMsg(t('BATTLE_EVENT_MODAL_START_DT_WARNING')); + return; + } + + if(resultData.round_time === 0){ + const config = configData.find(data => data.id === resultData.config_id); + setResultData({ ...resultData, round_time: config.round_time }); + } + + handleModalView('registConfirm'); + break; + case "cancel": + handleModalView('cancel'); + break; + case "cancelConfirm": + handleModalClose('cancel'); + handleReset(); + break; + case "registConfirm": + setLoading(true); + + if(isView('modify')){ + await BattleEventModify(token, content?.id, resultData).then(data => { + setLoading(false); + handleModalClose('registConfirm'); + if(data.result === "SUCCESS") { + handleModalView('registComplete'); + }else if(data.result === "ERROR_BATTLE_EVENT_TIME_OVER"){ + setAlertMsg(t('BATTLE_EVENT_MODAL_TIME_CHECK_WARNING')); + }else{ + setAlertMsg(t('UPDATE_FAIL')); + } + }).catch(reason => { + setAlertMsg(t('API_FAIL')); + }); + } + else{ + await BattleEventSingleRegist(token, resultData).then(data => { + setLoading(false); + handleModalClose('registConfirm'); + if(data.result === "SUCCESS") { + handleModalView('registComplete'); + }else if(data.result === "ERROR_BATTLE_EVENT_TIME_OVER"){ + setAlertMsg(t('BATTLE_EVENT_MODAL_TIME_CHECK_WARNING')); + }else{ + setAlertMsg(t('REGIST_FAIL')); + } + }).catch(reason => { + setAlertMsg(t('API_FAIL')); + }); + } + break; + case "registComplete": + handleModalClose('registComplete'); + handleReset(); + window.location.reload(); + break; + case "warning": + setAlertMsg(''); + break; + } + } + + const checkCondition = () => { + return ( + resultData.event_start_dt !== '' + && resultData.group_id !== '' + && resultData.event_name !== '' + && (resultData.repeat_type === 'NONE' || (resultData.repeat_type !== 'NONE' && resultData.event_end_dt !== '')) + ); + }; + + const isView = (label) => { + switch (label) { + case "modify": + return modalType === TYPE_MODIFY && (content?.status === battleEventStatusType.stop); + case "start_dt": + case "repeat": + case "registry": + return modalType === TYPE_REGISTRY + case "end_dt": + case "group": + case "name": + case "config": + case "reward": + case "round": + case "hot": + return modalType === TYPE_REGISTRY || (modalType === TYPE_MODIFY &&(content?.status === battleEventStatusType.stop)); + default: + return modalType === TYPE_MODIFY && (content?.status !== battleEventStatusType.stop); + } + } + + return ( + <> + + {isView('registry') ? "전투시스템 이벤트 등록" : isView('modify') ? "전투시스템 이벤트 수정" : "전투시스템 이벤트 상세"} + + + 그룹 ID + setResultData({ ...resultData, group_id: e.target.value })} + /> + 이벤트명 + setResultData({ ...resultData, event_name: e.target.value })} + /> + + + + + + + 반복 + setResultData({ ...resultData, repeat_type: e.target.value })} disabled={!isView('repeat')} width="150px"> + {battleRepeatType.map((data, index) => ( + + ))} + + {resultData?.repeat_type !== 'NONE' && + + } + + + 라운드 시간 + + {configData && configData?.map((data, index) => ( + + ))} + + 라운드 수 + setResultData({ ...resultData, round_count: e.target.value })} disabled={!isView('round')} width="100px"> + {battleEventRoundCount.map((data, index) => ( + + ))} + + + + 배정 포드 + setResultData({ ...resultData, reward_group_id: e.target.value })} disabled={!isView('reward')} width="200px"> + {rewardData && rewardData?.map((data, index) => ( + + ))} + + 핫타임 + setResultData({ ...resultData, hot_time: e.target.value })} disabled={!isView('hot')} width="100px"> + {battleEventHotTime.map((data, index) => ( + + ))} + + + + {!isView() && isNullValue && {t('REQUIRED_VALUE_CHECK')}} + + + + + + 현재상태: {battleEventStatus.find(data => data.value === content?.status)?.name || "등록"} + + + {isView('registry') ? '' : t('BATTLE_EVENT_MODAL_STATUS_WARNING')} + + + + {isView() ? +