메뉴배너 detailGrid 적용
This commit is contained in:
473
src/components/modal/MenuBannerModal.js
Normal file
473
src/components/modal/MenuBannerModal.js
Normal file
@@ -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 (
|
||||||
|
<>
|
||||||
|
<Modal min="760px" $view={detailView}>
|
||||||
|
<Title $align="center">{isView('registry') ? "전투시스템 이벤트 등록" : isView('modify') ? "전투시스템 이벤트 수정" : "전투시스템 이벤트 상세"}</Title>
|
||||||
|
<MessageWrapper>
|
||||||
|
<FormRowGroup>
|
||||||
|
<FormLabel>그룹 ID</FormLabel>
|
||||||
|
<FormInput
|
||||||
|
type="text"
|
||||||
|
disabled={!isView('group')}
|
||||||
|
width='150px'
|
||||||
|
value={resultData?.group_id}
|
||||||
|
onChange={e => setResultData({ ...resultData, group_id: e.target.value })}
|
||||||
|
/>
|
||||||
|
<FormLabel>이벤트명</FormLabel>
|
||||||
|
<FormInput
|
||||||
|
type="text"
|
||||||
|
disabled={!isView('name')}
|
||||||
|
width='300px'
|
||||||
|
value={resultData?.event_name}
|
||||||
|
onChange={e => setResultData({ ...resultData, event_name: e.target.value })}
|
||||||
|
/>
|
||||||
|
</FormRowGroup>
|
||||||
|
<FormRowGroup>
|
||||||
|
<SingleDatePicker
|
||||||
|
label="시작일자"
|
||||||
|
disabled={!isView('start_dt')}
|
||||||
|
dateLabel="시작 일자"
|
||||||
|
onDateChange={handleStartDateChange}
|
||||||
|
selectedDate={resultData?.event_start_dt}
|
||||||
|
/>
|
||||||
|
<SingleTimePicker
|
||||||
|
label="시작시간"
|
||||||
|
disabled={!isView('start_dt')}
|
||||||
|
selectedTime={resultData?.event_start_dt}
|
||||||
|
onTimeChange={handleStartTimeChange}
|
||||||
|
/>
|
||||||
|
</FormRowGroup>
|
||||||
|
<FormRowGroup>
|
||||||
|
<FormLabel>반복</FormLabel>
|
||||||
|
<SelectInput value={resultData?.repeat_type} onChange={e => setResultData({ ...resultData, repeat_type: e.target.value })} disabled={!isView('repeat')} width="150px">
|
||||||
|
{battleRepeatType.map((data, index) => (
|
||||||
|
<option key={index} value={data.value}>
|
||||||
|
{data.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</SelectInput>
|
||||||
|
{resultData?.repeat_type !== 'NONE' &&
|
||||||
|
<SingleDatePicker
|
||||||
|
label="종료일자"
|
||||||
|
disabled={!isView('end_dt')}
|
||||||
|
dateLabel="종료 일자"
|
||||||
|
onDateChange={handleEndDateChange}
|
||||||
|
selectedDate={resultData?.event_end_dt}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</FormRowGroup>
|
||||||
|
<FormRowGroup>
|
||||||
|
<FormLabel>라운드 시간</FormLabel>
|
||||||
|
<SelectInput value={resultData.config_id} onChange={handleConfigChange} disabled={!isView('config')} width="200px">
|
||||||
|
{configData && configData?.map((data, index) => (
|
||||||
|
<option key={index} value={data.id}>
|
||||||
|
{data.desc}({data.id})
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</SelectInput>
|
||||||
|
<FormLabel>라운드 수</FormLabel>
|
||||||
|
<SelectInput value={resultData.round_count} onChange={e => setResultData({ ...resultData, round_count: e.target.value })} disabled={!isView('round')} width="100px">
|
||||||
|
{battleEventRoundCount.map((data, index) => (
|
||||||
|
<option key={index} value={data}>
|
||||||
|
{data}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</SelectInput>
|
||||||
|
</FormRowGroup>
|
||||||
|
<FormRowGroup>
|
||||||
|
<FormLabel>배정 포드</FormLabel>
|
||||||
|
<SelectInput value={resultData.reward_group_id} onChange={e => setResultData({ ...resultData, reward_group_id: e.target.value })} disabled={!isView('reward')} width="200px">
|
||||||
|
{rewardData && rewardData?.map((data, index) => (
|
||||||
|
<option key={index} value={data.group_id}>
|
||||||
|
{data.desc}({data.group_id})
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</SelectInput>
|
||||||
|
<FormLabel>핫타임</FormLabel>
|
||||||
|
<SelectInput value={resultData.hot_time} onChange={e => setResultData({ ...resultData, hot_time: e.target.value })} disabled={!isView('hot')} width="100px">
|
||||||
|
{battleEventHotTime.map((data, index) => (
|
||||||
|
<option key={index} value={data}>
|
||||||
|
{data}배
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</SelectInput>
|
||||||
|
</FormRowGroup>
|
||||||
|
|
||||||
|
{!isView() && isNullValue && <SearchBarAlert $marginTop="25px" $align="right">{t('REQUIRED_VALUE_CHECK')}</SearchBarAlert>}
|
||||||
|
</MessageWrapper>
|
||||||
|
|
||||||
|
<BtnWrapper $gap="10px" $marginTop="10px">
|
||||||
|
<FormStatusBar>
|
||||||
|
<FormStatusLabel>
|
||||||
|
현재상태: {battleEventStatus.find(data => data.value === content?.status)?.name || "등록"}
|
||||||
|
</FormStatusLabel>
|
||||||
|
<FormStatusWarning>
|
||||||
|
{isView('registry') ? '' : t('BATTLE_EVENT_MODAL_STATUS_WARNING')}
|
||||||
|
</FormStatusWarning>
|
||||||
|
</FormStatusBar>
|
||||||
|
<FormButtonContainer $gap="5px">
|
||||||
|
{isView() ?
|
||||||
|
<Button
|
||||||
|
text="확인"
|
||||||
|
name="확인버튼"
|
||||||
|
theme="line"
|
||||||
|
handleClick={() => handleReset()}
|
||||||
|
/>
|
||||||
|
:
|
||||||
|
<>
|
||||||
|
<Button text="취소" theme="line" handleClick={() => handleSubmit('cancel')} />
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
text={isView('modify') ? "수정" : "등록"}
|
||||||
|
name="등록버튼"
|
||||||
|
theme={
|
||||||
|
checkCondition()
|
||||||
|
? 'primary'
|
||||||
|
: 'disable'
|
||||||
|
}
|
||||||
|
handleClick={() => handleSubmit('submit')}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</FormButtonContainer>
|
||||||
|
</BtnWrapper>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
{/* 확인 모달 */}
|
||||||
|
<DynamicModal
|
||||||
|
modalType={modalTypes.confirmOkCancel}
|
||||||
|
view={modalState.registConfirmModal}
|
||||||
|
modalText={isView('modify') ? t('BATTLE_EVENT_UPDATE_CONFIRM') : t('BATTLE_EVENT_REGIST_CONFIRM')}
|
||||||
|
handleSubmit={() => handleSubmit('registConfirm')}
|
||||||
|
handleCancel={() => handleModalClose('registConfirm')}
|
||||||
|
/>
|
||||||
|
{/* 완료 모달 */}
|
||||||
|
<DynamicModal
|
||||||
|
modalType={modalTypes.completed}
|
||||||
|
view={modalState.registCompleteModal}
|
||||||
|
modalText={isView('modify') ? t('UPDATE_COMPLETED') : t('REGIST_COMPLTE')}
|
||||||
|
handleSubmit={() => handleSubmit('registComplete')}
|
||||||
|
/>
|
||||||
|
{/* 취소 모달 */}
|
||||||
|
<DynamicModal
|
||||||
|
modalType={modalTypes.confirmOkCancel}
|
||||||
|
view={modalState.cancelModal}
|
||||||
|
modalText={t('CANCEL_CONFIRM')}
|
||||||
|
handleCancel={() => handleModalClose('cancel')}
|
||||||
|
handleSubmit={() => handleSubmit('cancelConfirm')}
|
||||||
|
/>
|
||||||
|
{/* 경고 모달 */}
|
||||||
|
<DynamicModal
|
||||||
|
modalType={modalTypes.completed}
|
||||||
|
view={alertMsg ? 'view' : 'hidden'}
|
||||||
|
modalText={alertMsg}
|
||||||
|
handleSubmit={() => handleSubmit('warning')}
|
||||||
|
/>
|
||||||
|
{loading && <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;
|
||||||
|
|
||||||
Reference in New Issue
Block a user