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() ?
+
+
+
+
+ {/* 확인 모달 */}
+ handleSubmit('registConfirm')}
+ handleCancel={() => handleModalClose('registConfirm')}
+ />
+ {/* 완료 모달 */}
+ handleSubmit('registComplete')}
+ />
+ {/* 취소 모달 */}
+ handleModalClose('cancel')}
+ handleSubmit={() => handleSubmit('cancelConfirm')}
+ />
+ {/* 경고 모달 */}
+ handleSubmit('warning')}
+ />
+ {loading && }
+ >
+ );
+};
+
+export const initData = {
+ group_id: '',
+ event_name: '',
+ repeat_type: 'NONE',
+ config_id: 1,
+ round_time: 0,
+ reward_group_id: 1,
+ round_count: 1,
+ hot_time: 1,
+ event_start_dt: '',
+ event_end_dt: ''
+}
+
+export default MenuBannerModal;
+