Compare commits
12 Commits
513ea114cc
...
4bc8b34c26
| Author | SHA1 | Date | |
|---|---|---|---|
| 4bc8b34c26 | |||
| 68c44cbf09 | |||
| c6dac677f6 | |||
| 6760219734 | |||
| f2369773a0 | |||
| c375bc1164 | |||
| 30ec5eabe5 | |||
| f1d3a67eed | |||
| d0a3b880df | |||
| 95d5cad3bc | |||
| b70b2e8f2c | |||
| ffaaa5be14 |
@@ -3,10 +3,10 @@
|
|||||||
import { Axios } from '../utils';
|
import { Axios } from '../utils';
|
||||||
|
|
||||||
// 전투시스템 리스트 조회
|
// 전투시스템 리스트 조회
|
||||||
export const BattleEventView = async (token, landType, landData, userType, userData, landSize, status, startDate, endDate, order, size, currentPage) => {
|
export const BattleEventView = async (token, searchType, searchData, configId, rewardId, repeatType, status, roundCount, hotTime, startDate, endDate, order, size, currentPage) => {
|
||||||
try {
|
try {
|
||||||
const res = await Axios.get(
|
const res = await Axios.get(
|
||||||
`/api/v1/battle/event/list?land_type=${landType}&land_data=${landData}&user_type=${userType}&user_data=${userData}&land_size=${landSize}&status=${status}&start_dt=${startDate}&end_dt=${endDate}&orderby=${order}&page_no=${currentPage}
|
`/api/v1/battle/event/list?search_type=${searchType}&search_data=${searchData}&config_id=${configId}&reward_id=${rewardId}&repeat_type=${repeatType}&status=${status}&round_count=${roundCount}&hot_time=${hotTime}&start_dt=${startDate}&end_dt=${endDate}&orderby=${order}&page_no=${currentPage}
|
||||||
&page_size=${size}`,
|
&page_size=${size}`,
|
||||||
{
|
{
|
||||||
headers: { Authorization: `Bearer ${token}` },
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
@@ -66,8 +66,23 @@ export const BattleEventModify = async (token, id, params) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//전투시스템 중단
|
||||||
|
export const BattleEventStop = async (token, id, params) => {
|
||||||
|
try {
|
||||||
|
const res = await Axios.put(`/api/v1/battle/event/stop/${id}`, {},{
|
||||||
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.data;
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof Error) {
|
||||||
|
throw new Error('BattleEventStop Error', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 전투시스템 삭제
|
// 전투시스템 삭제
|
||||||
export const BattleEventDelete = async (token, params, id) => {
|
export const BattleEventDelete = async (token, params) => {
|
||||||
try {
|
try {
|
||||||
const res = await Axios.delete(`/api/v1/battle/event/delete`, {
|
const res = await Axios.delete(`/api/v1/battle/event/delete`, {
|
||||||
headers: { Authorization: `Bearer ${token}` },
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
|||||||
@@ -36,6 +36,20 @@ export const MailDetailView = async (token, id) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const MailCaliumTotalView = async (token) => {
|
||||||
|
try {
|
||||||
|
const res = await Axios.get(`/api/v1/mail/calium`, {
|
||||||
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.data.data.stock_calium;
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof Error) {
|
||||||
|
throw new Error('MailCaliumTotalView Error', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 우편 단일 등록
|
// 우편 단일 등록
|
||||||
export const MailSingleRegist = async (token, params) => {
|
export const MailSingleRegist = async (token, params) => {
|
||||||
try {
|
try {
|
||||||
@@ -43,7 +57,7 @@ export const MailSingleRegist = async (token, params) => {
|
|||||||
headers: { Authorization: `Bearer ${token}` },
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
});
|
});
|
||||||
|
|
||||||
return res;
|
return res.data;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) {
|
if (e instanceof Error) {
|
||||||
throw new Error('MailRegist Error', e);
|
throw new Error('MailRegist Error', e);
|
||||||
|
|||||||
@@ -4,5 +4,8 @@ const INITIAL_PAGE_LIMIT = 10;
|
|||||||
export const TYPE_REGISTRY = 'regist';
|
export const TYPE_REGISTRY = 'regist';
|
||||||
export const TYPE_MODIFY = 'modify';
|
export const TYPE_MODIFY = 'modify';
|
||||||
export const NONE = 'NONE';
|
export const NONE = 'NONE';
|
||||||
|
export const ONE_MINUTE_MS = 60000;
|
||||||
|
export const ONE_MINUTE_SECOND = 60;
|
||||||
|
export const AUCTION_MIN_MINUTE_TIME = 15; // 15분
|
||||||
|
|
||||||
export { INITIAL_PAGE_SIZE, INITIAL_CURRENT_PAGE, INITIAL_PAGE_LIMIT };
|
export { INITIAL_PAGE_SIZE, INITIAL_CURRENT_PAGE, INITIAL_PAGE_LIMIT };
|
||||||
|
|||||||
@@ -61,4 +61,20 @@ export const STATUS_STYLES = {
|
|||||||
background: '#A37FB8',
|
background: '#A37FB8',
|
||||||
color: 'white'
|
color: 'white'
|
||||||
},
|
},
|
||||||
|
END: {
|
||||||
|
background: '#A37FB8',
|
||||||
|
color: 'white'
|
||||||
|
},
|
||||||
|
REGISTER: {
|
||||||
|
background: '#DEBB46',
|
||||||
|
color: 'black'
|
||||||
|
},
|
||||||
|
STOP: {
|
||||||
|
background: '#FFB59B',
|
||||||
|
color: 'white'
|
||||||
|
},
|
||||||
|
RUNNING: {
|
||||||
|
background: '#4287f5',
|
||||||
|
color: 'white'
|
||||||
|
},
|
||||||
};
|
};
|
||||||
@@ -73,6 +73,7 @@ export const wellType = [
|
|||||||
{ value: '19010001', name: '골드' },
|
{ value: '19010001', name: '골드' },
|
||||||
{ value: '19010002', name: '사파이어' },
|
{ value: '19010002', name: '사파이어' },
|
||||||
{ value: '19010005', name: '루비' },
|
{ value: '19010005', name: '루비' },
|
||||||
|
{ value: '19010003', name: '칼리움' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const logOption = [
|
export const logOption = [
|
||||||
@@ -177,9 +178,10 @@ export const CurrencyType = [
|
|||||||
|
|
||||||
export const battleEventStatus = [
|
export const battleEventStatus = [
|
||||||
{ value: 'ALL', name: '전체' },
|
{ value: 'ALL', name: '전체' },
|
||||||
{ value: 'WAIT', name: '중단' },
|
{ value: 'WAIT', name: '대기' },
|
||||||
{ value: 'REGISTER', name: '예약완료' },
|
{ value: 'REGISTER', name: '예약완료' },
|
||||||
{ value: 'CANCEL', name: '예약취소' },
|
{ value: 'CANCEL', name: '예약취소' },
|
||||||
|
{ value: 'STOP', name: '중단' },
|
||||||
{ value: 'END', name: '종료' },
|
{ value: 'END', name: '종료' },
|
||||||
{ value: 'RUNNING', name: '진행중' },
|
{ value: 'RUNNING', name: '진행중' },
|
||||||
{ value: 'FAIL', name: '실패' },
|
{ value: 'FAIL', name: '실패' },
|
||||||
@@ -196,3 +198,11 @@ export const battleRepeatType = [
|
|||||||
{ value: 'FRIDAY', name: 'Week-금' },
|
{ value: 'FRIDAY', name: 'Week-금' },
|
||||||
{ value: 'SATURDAY', name: 'Week-토' },
|
{ value: 'SATURDAY', name: 'Week-토' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const eventSearchType = [
|
||||||
|
{ value: 'ID', name: '이벤트 ID' },
|
||||||
|
{ value: 'NAME', name: '이벤트명' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const battleEventRoundCount = [1,2,3,4,8,12,16];
|
||||||
|
export const battleEventHotTime = [1,2,3,4,5,6,7,8];
|
||||||
@@ -114,6 +114,15 @@ export const battleEventStatusType = {
|
|||||||
wait: "WAIT",
|
wait: "WAIT",
|
||||||
register: "REGISTER",
|
register: "REGISTER",
|
||||||
end: "END",
|
end: "END",
|
||||||
|
stop: "STOP",
|
||||||
fail: "FAIL",
|
fail: "FAIL",
|
||||||
cancel: "CANCEL",
|
cancel: "CANCEL",
|
||||||
|
running: "RUNNING",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const currencyCodeTypes = {
|
||||||
|
gold: "19010001",
|
||||||
|
sapphire: "19010002",
|
||||||
|
ruby: "19010005",
|
||||||
|
calium: "19010003"
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,620 +0,0 @@
|
|||||||
import { styled } from 'styled-components';
|
|
||||||
import { useState, useRef, Fragment, useEffect } from 'react';
|
|
||||||
|
|
||||||
import Button from '../common/button/Button';
|
|
||||||
import CheckBox from '../common/input/CheckBox';
|
|
||||||
import Modal from '../common/modal/Modal';
|
|
||||||
|
|
||||||
import { Title, BtnWrapper, SelectInput, TextInput, DatePickerWrapper, InputLabel, Textarea, ModalText, SearchBarAlert } from '../../styles/Components';
|
|
||||||
import CloseIcon from '../../assets/img/icon/icon-close.png';
|
|
||||||
import DatePickerComponent from '../common/Date/DatePickerComponent';
|
|
||||||
import { HourList, MinuteList, modalTypes } from '../../assets/data';
|
|
||||||
import { NoticeRegist } from '../../apis';
|
|
||||||
import { convertKTC, convertKTCDate } from '../../utils';
|
|
||||||
import DynamicModal from '../common/modal/DynamicModal';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import {
|
|
||||||
BoxWrapper, InputGroup2,
|
|
||||||
MessageBox, MessageWrapper,
|
|
||||||
NoticeInputGroup, NoticeInputItem, NoticeInputItem2,
|
|
||||||
NoticeInputRow, NoticeInputRow2,
|
|
||||||
NoticeRegistGroup,
|
|
||||||
RegistInputItem, RepeatTime, SubText, SubTextRow, TitleLang,
|
|
||||||
} from '../../styles/ModuleComponents';
|
|
||||||
import { languageType } from '../../assets/data/options';
|
|
||||||
|
|
||||||
const BoardRegistModal = ({ registView, setRegistView, copyData, setIsCopyData }) => {
|
|
||||||
const [doubleSubmitFlag, setDoubleSubmitFlag] = useState(false);
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const [sendHour, setSendHour] = useState('00');
|
|
||||||
const [sendMin, setSendMin] = useState('00');
|
|
||||||
const [endHour, setEndHour] = useState('00');
|
|
||||||
const [endMin, setEndMin] = useState('00');
|
|
||||||
const [repeatHour, setRepeatHour] = useState('00');
|
|
||||||
const [repeatMin, setRepeatMin] = useState('00');
|
|
||||||
|
|
||||||
const [confirmModal, setConfirmModal] = useState('hidden');
|
|
||||||
const [completeModal, setCompleteModal] = useState('hidden');
|
|
||||||
const [errorModal, setErrorModal] = useState('hidden');
|
|
||||||
|
|
||||||
const [confirmText, setConfirmText] = useState('');
|
|
||||||
const [completeText, setCompleteText] = useState('');
|
|
||||||
const [isNullValue, setIsNullValue] = useState(false);
|
|
||||||
const [btnValidation, setBtnValidation] = useState(false);
|
|
||||||
|
|
||||||
const [message_lang, setMessage_lang] = useState('KO');
|
|
||||||
|
|
||||||
const itemId = useRef(1);
|
|
||||||
|
|
||||||
const resetData = {
|
|
||||||
send_dt: '',
|
|
||||||
message_type: 'CHATTING',
|
|
||||||
is_repeat: false,
|
|
||||||
repeat_type: 'COUNT',
|
|
||||||
repeat_dt: '00:00:00',
|
|
||||||
repeat_cnt: '1',
|
|
||||||
game_message: [
|
|
||||||
{ language: 'KO', content: '' },
|
|
||||||
{ language: 'EN', content: '' },
|
|
||||||
{ language: 'JA', content: '' },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const [resultData, setResultData] = useState({
|
|
||||||
send_dt: '',
|
|
||||||
end_dt: '',
|
|
||||||
message_type: 'CHATTING',
|
|
||||||
is_repeat: false,
|
|
||||||
repeat_type: 'COUNT',
|
|
||||||
repeat_dt: '00:00:00',
|
|
||||||
repeat_cnt: '1',
|
|
||||||
game_message: [
|
|
||||||
{ language: 'KO', content: '' },
|
|
||||||
{ language: 'EN', content: '' },
|
|
||||||
{ language: 'JA', content: '' },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const KOREAN_TIME = copyData && convertKTCDate(copyData.detail.send_dt);
|
|
||||||
|
|
||||||
// console.log(resultData);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setResultData({
|
|
||||||
send_dt: copyData && '',
|
|
||||||
end_dt: copyData && '',
|
|
||||||
message_type: copyData ? copyData.detail.message_type : 'CHATTING',
|
|
||||||
is_repeat: copyData ? copyData.detail.is_repeat : false,
|
|
||||||
repeat_type: copyData ? copyData.detail.repeat_type : 'COUNT',
|
|
||||||
repeat_dt: copyData ? copyData.detail.repeat_dt : '00:00:00',
|
|
||||||
repeat_cnt: copyData ? copyData.detail.repeat_cnt : '1',
|
|
||||||
game_message: copyData
|
|
||||||
? copyData.game_message
|
|
||||||
: [
|
|
||||||
{ language: 'KO', content: '' },
|
|
||||||
{ language: 'EN', content: '' },
|
|
||||||
{ language: 'JA', content: '' },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (copyData && copyData.game_message.length <= 1) {
|
|
||||||
setBtnValidation(true);
|
|
||||||
}
|
|
||||||
}, [copyData]);
|
|
||||||
|
|
||||||
const handleRepeatTime = e => {
|
|
||||||
if (e.target.id === 'hour') setRepeatHour(e.target.value);
|
|
||||||
else if (e.target.id === 'min') setRepeatMin(e.target.value);
|
|
||||||
|
|
||||||
setResultData({ ...resultData, repeat_dt: (e.target.id === 'hour' ? e.target.value : repeatHour) + ':' + (e.target.id === 'min' ? e.target.value : repeatMin) + ':00' });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 날짜 설정
|
|
||||||
const handleSelectedDate = data => {
|
|
||||||
const sendDate = new Date(data);
|
|
||||||
|
|
||||||
if (resultData.send_dt.length === 0 || typeof resultData.send_dt.length != 'undefined') {
|
|
||||||
setSendHour('00');
|
|
||||||
setSendMin('00');
|
|
||||||
}
|
|
||||||
|
|
||||||
const resultSendData = new Date(sendDate.getFullYear(), sendDate.getMonth(), sendDate.getDate(), sendHour, sendMin);
|
|
||||||
|
|
||||||
setResultData({ ...resultData, send_dt: resultSendData });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 시간 설정
|
|
||||||
const handleSendTime = e => {
|
|
||||||
let sendDate = '';
|
|
||||||
|
|
||||||
if (resultData.send_dt.length === 0 || typeof resultData.send_dt.length != 'undefined') {
|
|
||||||
sendDate = new Date();
|
|
||||||
} else {
|
|
||||||
sendDate = new Date(resultData.send_dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.target.id === 'hour') setSendHour(e.target.value);
|
|
||||||
else if (e.target.id === 'min') setSendMin(e.target.value);
|
|
||||||
|
|
||||||
// console.log(sendDate);
|
|
||||||
|
|
||||||
const result = new Date(sendDate.getFullYear(), sendDate.getMonth(), sendDate.getDate(), e.target.id === 'hour' ? e.target.value : sendHour, e.target.id === 'min' ? e.target.value : sendMin);
|
|
||||||
|
|
||||||
setResultData({ ...resultData, send_dt: result });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 종료 날짜 설정
|
|
||||||
const handleSelectedEndDate = data => {
|
|
||||||
const endDate = new Date(data);
|
|
||||||
|
|
||||||
if (resultData.end_dt.length === 0 || typeof resultData.end_dt.length != 'undefined') {
|
|
||||||
setEndHour('00');
|
|
||||||
setEndMin('00');
|
|
||||||
}
|
|
||||||
|
|
||||||
let resultEndData = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate(), endHour, endMin);
|
|
||||||
|
|
||||||
if (resultData.send_dt > resultEndData){
|
|
||||||
alert("송출 일자보다 작을 수 없습니다.");
|
|
||||||
resultEndData = new Date(resultData.send_dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
setResultData({ ...resultData, end_dt: resultEndData });
|
|
||||||
};
|
|
||||||
|
|
||||||
//종료 시간 설정
|
|
||||||
const handleEndTime = e => {
|
|
||||||
let endDate = '';
|
|
||||||
|
|
||||||
if (resultData.end_dt.length === 0 || typeof resultData.end_dt.length != 'undefined') {
|
|
||||||
endDate = new Date();
|
|
||||||
} else {
|
|
||||||
endDate = new Date(resultData.end_dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.target.id === 'hour') setEndHour(e.target.value);
|
|
||||||
else if (e.target.id === 'min') setEndMin(e.target.value);
|
|
||||||
|
|
||||||
// console.log(sendDate);
|
|
||||||
|
|
||||||
let result = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate(), e.target.id === 'hour' ? e.target.value : endHour, e.target.id === 'min' ? e.target.value : endMin);
|
|
||||||
|
|
||||||
if (resultData.send_dt > result){
|
|
||||||
alert("송출 일자보다 작을 수 없습니다.");
|
|
||||||
result = new Date(resultData.send_dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
setResultData({ ...resultData, end_dt: result });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDelete = language => {
|
|
||||||
let filterList = resultData.game_message.filter(el => el.language !== language);
|
|
||||||
|
|
||||||
if (filterList.length === 1) {
|
|
||||||
setBtnValidation(true);
|
|
||||||
} else if (filterList.length > 1) {
|
|
||||||
setBtnValidation(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
setResultData({ ...resultData, game_message: filterList });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 반복횟수 입력 데이터 폼 처리
|
|
||||||
const handleRepeatValue = e => {
|
|
||||||
// e.target.value.length === 0 ? setIsNullValue(true) : setIsNullValue(false);
|
|
||||||
|
|
||||||
if (e.target.value === '0' || e.target.value === '-0' || e.target.value.length === 0) {
|
|
||||||
setResultData({ ...resultData, repeat_cnt: '1' });
|
|
||||||
e.target.value = '1';
|
|
||||||
} else if (e.target.value < 0) {
|
|
||||||
let plusNum = Math.abs(e.target.value);
|
|
||||||
setResultData({ ...resultData, repeat_cnt: plusNum });
|
|
||||||
} else {
|
|
||||||
setResultData({ ...resultData, repeat_cnt: e.target.value });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 등록 버튼
|
|
||||||
const handleRegistBtn = e => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (
|
|
||||||
!resultData.game_message.some(data => data.content !== '') ||
|
|
||||||
resultData.game_message.length === 0 ||
|
|
||||||
resultData.send_dt.length === 0 ||
|
|
||||||
typeof resultData.send_dt.length != 'undefined' ||
|
|
||||||
(resultData.is_repeat === true && resultData.repeat_dt === '00:00:00') ||
|
|
||||||
(resultData.is_repeat === true && resultData.message_type === "COUNT" && resultData.repeat_cnt.length === 0) ||
|
|
||||||
(resultData.is_repeat === true && resultData.message_type === "COUNT" && resultData.end_dt.length === 0) ||
|
|
||||||
(resultData.is_repeat === true && resultData.message_type === "COUNT" && typeof resultData.end_dt.length !== 'undefined')
|
|
||||||
) {
|
|
||||||
setIsNullValue(true);
|
|
||||||
} else {
|
|
||||||
setIsNullValue(false);
|
|
||||||
setConfirmText('인게임 메시지를 등록하시겠습니까?');
|
|
||||||
handleConfirmModal('regist');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 취소 버튼
|
|
||||||
const handleCancelBtn = e => {
|
|
||||||
e.preventDefault();
|
|
||||||
setConfirmText('인게임 메시지 등록을 취소하시겠습니까?');
|
|
||||||
handleConfirmModal('cancel');
|
|
||||||
};
|
|
||||||
|
|
||||||
// 입력창 글자 제한
|
|
||||||
const handleInputData = e => {
|
|
||||||
if (e.target.value.length > 250) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let list = [...resultData.game_message];
|
|
||||||
let findIndex = resultData.game_message.findIndex(item => item.language === e.target.id);
|
|
||||||
list[findIndex].content = e.target.value.trimStart();
|
|
||||||
|
|
||||||
setResultData({ ...resultData, game_message: list });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 알림창 텍스트
|
|
||||||
const handleSubmitNotice = async () => {
|
|
||||||
const token = sessionStorage.getItem('token');
|
|
||||||
|
|
||||||
if (confirmText === '인게임 메시지를 등록하시겠습니까?') {
|
|
||||||
const message = await NoticeRegist(token, resultData);
|
|
||||||
|
|
||||||
message.data.data.message !== '등록 하였습니다.' ? setCompleteText(message.data.data.message) : setCompleteText('등록이 완료되었습니다.');
|
|
||||||
|
|
||||||
handleConfirmModal();
|
|
||||||
handleCompleteModal();
|
|
||||||
setIsNullValue(false);
|
|
||||||
|
|
||||||
setRegistView('hidden');
|
|
||||||
} else if (confirmText === '인게임 메시지 등록을 취소하시겠습니까?') {
|
|
||||||
handleConfirmModal();
|
|
||||||
handleCompleteModal();
|
|
||||||
setCompleteText('등록이 취소되었습니다.');
|
|
||||||
|
|
||||||
setRegistView('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
itemId.current = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 언어 선택
|
|
||||||
const handleLanguage = e => {
|
|
||||||
setMessage_lang(e.target.value);
|
|
||||||
if(!resultData.game_message.some(({language}) => language === e.target.value))
|
|
||||||
setResultData({ ...resultData, game_message: [...resultData.game_message, {language: e.target.value, content: ''}] })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 확인 모달
|
|
||||||
const handleConfirmModal = step => {
|
|
||||||
if (confirmModal === 'hidden') {
|
|
||||||
setConfirmModal('view');
|
|
||||||
} else {
|
|
||||||
setConfirmModal('hidden');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 완료 모달창
|
|
||||||
const handleCompleteModal = () => {
|
|
||||||
setIsCopyData(false);
|
|
||||||
if (completeModal === 'hidden') {
|
|
||||||
setCompleteModal('view');
|
|
||||||
} else {
|
|
||||||
setCompleteModal('hidden');
|
|
||||||
setResultData(resetData);
|
|
||||||
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 필수값 입력 모달창
|
|
||||||
const handleErrorModal = () => {
|
|
||||||
if (errorModal === 'hidden') {
|
|
||||||
setErrorModal('view');
|
|
||||||
} else {
|
|
||||||
setErrorModal('hidden');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 내용 복사일 때 이동 페이지
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Modal min="960px" $view={registView}>
|
|
||||||
{/* 등록 후 정보 확인시 타이틀 텍스트 변경 인게임 메시지 등록 -> 인게임 메시지 정보 */}
|
|
||||||
<Title $align="center"> 인게임 메시지 등록</Title>
|
|
||||||
<MessageWrapper>
|
|
||||||
<InputLabel>[메세지 등록 설정]</InputLabel>
|
|
||||||
<NoticeRegistGroup>
|
|
||||||
<NoticeInputRow>
|
|
||||||
<RegistInputItem>
|
|
||||||
<InputLabel>송출 일자(예약)</InputLabel>
|
|
||||||
<InputGroup2>
|
|
||||||
<NoticeInputGroup>
|
|
||||||
<DatePickerWrapper>
|
|
||||||
<DatePickerComponent name="시작 일자" handleSelectedDate={data => handleSelectedDate(data)} selectedDate={resultData.send_dt} pastDate={new Date()} />
|
|
||||||
</DatePickerWrapper>
|
|
||||||
<SelectInput
|
|
||||||
onChange={e => handleSendTime(e)}
|
|
||||||
id="hour"
|
|
||||||
value={
|
|
||||||
resultData && String(new Date(resultData.send_dt).getHours()) < 10
|
|
||||||
? '0' + String(new Date(resultData.send_dt).getHours())
|
|
||||||
: (resultData && String(new Date(resultData.send_dt).getHours())) || ''
|
|
||||||
}>
|
|
||||||
{HourList.map(hour => (
|
|
||||||
<option
|
|
||||||
value={hour}
|
|
||||||
key={hour}
|
|
||||||
// selected={
|
|
||||||
// resultData && String(new Date(resultData.send_dt).getHours()) < 10
|
|
||||||
// ? '0' + String(new Date(resultData.send_dt).getHours()) === hour
|
|
||||||
// : resultData && String(new Date(resultData.send_dt).getHours()) === hour
|
|
||||||
// ? 'selected'
|
|
||||||
// : ''
|
|
||||||
// }
|
|
||||||
>
|
|
||||||
{hour}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
<SelectInput
|
|
||||||
onChange={e => handleSendTime(e)}
|
|
||||||
id="min"
|
|
||||||
value={
|
|
||||||
resultData && String(new Date(resultData.send_dt).getMinutes()) < 10
|
|
||||||
? '0' + String(new Date(resultData.send_dt).getMinutes())
|
|
||||||
: (resultData && String(new Date(resultData.send_dt).getMinutes())) || ''
|
|
||||||
}>
|
|
||||||
{MinuteList.map(min => (
|
|
||||||
<option
|
|
||||||
value={min}
|
|
||||||
key={min}
|
|
||||||
// selected={
|
|
||||||
// resultData && String(new Date(resultData.send_dt).getMinutes()) < 10
|
|
||||||
// ? '0' + String(new Date(resultData.send_dt).getMinutes()) === min
|
|
||||||
// : resultData && String(new Date(resultData.send_dt).getMinutes()) === min
|
|
||||||
// ? 'selected'
|
|
||||||
// : ''
|
|
||||||
// }
|
|
||||||
>
|
|
||||||
{min}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</NoticeInputGroup>
|
|
||||||
<SubText>* UTC+9 한국시간 기준으로 설정 (UTC+0 자동 반영처리)</SubText>
|
|
||||||
</InputGroup2>
|
|
||||||
</RegistInputItem>
|
|
||||||
<RegistInputItem>
|
|
||||||
<InputLabel>메시지 타입</InputLabel>
|
|
||||||
<SelectInput onChange={e => setResultData({ ...resultData, message_type: e.target.value })} value={resultData.message_type || ''}>
|
|
||||||
<option value="CHATTING">채팅</option>
|
|
||||||
<option value="CHATTING_TOAST">채팅 + 토스트</option>
|
|
||||||
</SelectInput>
|
|
||||||
</RegistInputItem>
|
|
||||||
</NoticeInputRow>
|
|
||||||
<NoticeInputRow>
|
|
||||||
<CheckBox label="반복 발송" id="input-regist" inline={false} checked={resultData.is_repeat} setData={e => setResultData({ ...resultData, is_repeat: e.target.checked })} style={{display: 'hidden'}}/>
|
|
||||||
{resultData.is_repeat === true && (
|
|
||||||
<>
|
|
||||||
<RegistInputItem>
|
|
||||||
<InputLabel>반복 타입</InputLabel>
|
|
||||||
<SelectInput onChange={e => setResultData({ ...resultData, repeat_type: e.target.value })} value={resultData.repeat_type || ''}>
|
|
||||||
<option value="COUNT">횟수</option>
|
|
||||||
<option value="DATE">일자</option>
|
|
||||||
<option value="TIME">특정시간</option>
|
|
||||||
</SelectInput>
|
|
||||||
</RegistInputItem>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</NoticeInputRow>
|
|
||||||
<NoticeInputRow>
|
|
||||||
{resultData.is_repeat === true && (
|
|
||||||
<>
|
|
||||||
{resultData.repeat_type !== "COUNT" && (
|
|
||||||
<>
|
|
||||||
<NoticeInputItem>
|
|
||||||
<InputLabel>종료 일자</InputLabel>
|
|
||||||
<InputGroup2>
|
|
||||||
<NoticeInputGroup>
|
|
||||||
<DatePickerWrapper>
|
|
||||||
<DatePickerComponent name="종료 일자" handleSelectedDate={data => handleSelectedEndDate(data)} selectedDate={resultData.end_dt} pastDate={new Date()} />
|
|
||||||
</DatePickerWrapper>
|
|
||||||
<SelectInput
|
|
||||||
onChange={e => handleEndTime(e)}
|
|
||||||
id="hour"
|
|
||||||
value={
|
|
||||||
resultData && String(new Date(resultData.end_dt).getHours()) < 10
|
|
||||||
? '0' + String(new Date(resultData.end_dt).getHours())
|
|
||||||
: (resultData && String(new Date(resultData.end_dt).getHours())) || ''
|
|
||||||
}>
|
|
||||||
{HourList.map(hour => (
|
|
||||||
<option
|
|
||||||
value={hour}
|
|
||||||
key={hour}
|
|
||||||
>
|
|
||||||
{hour}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
<SelectInput
|
|
||||||
onChange={e => handleEndTime(e)}
|
|
||||||
id="min"
|
|
||||||
value={
|
|
||||||
resultData && String(new Date(resultData.end_dt).getMinutes()) < 10
|
|
||||||
? '0' + String(new Date(resultData.end_dt).getMinutes())
|
|
||||||
: (resultData && String(new Date(resultData.end_dt).getMinutes())) || ''
|
|
||||||
}>
|
|
||||||
{MinuteList.map(min => (
|
|
||||||
<option
|
|
||||||
value={min}
|
|
||||||
key={min}
|
|
||||||
>
|
|
||||||
{min}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</NoticeInputGroup>
|
|
||||||
</InputGroup2>
|
|
||||||
</NoticeInputItem>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<RegistInputItem>
|
|
||||||
<RepeatTime>
|
|
||||||
{resultData.repeat_type === "TIME" && (<span>발송시간</span>)}
|
|
||||||
<SelectInput onChange={e => handleRepeatTime(e)} id="hour" value={resultData.repeat_dt.split(':')[0] || ''}>
|
|
||||||
{HourList.map(hour => (
|
|
||||||
<option
|
|
||||||
value={hour}
|
|
||||||
key={hour}
|
|
||||||
>
|
|
||||||
{hour}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
<SelectInput onChange={e => handleRepeatTime(e)} id="min" value={resultData.repeat_dt.split(':')[1] || ''}>
|
|
||||||
{MinuteList.map(min => (
|
|
||||||
<option
|
|
||||||
value={min}
|
|
||||||
key={min}
|
|
||||||
>
|
|
||||||
{min}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
{resultData.repeat_type !== "TIME" ? (
|
|
||||||
<>
|
|
||||||
<span>마다</span>
|
|
||||||
<SubText>* 최초 송출 이후 설정된 시간 단위마다 송출</SubText>
|
|
||||||
</>
|
|
||||||
) : (<SubText>* 설정된 시간에만 송출</SubText>)}
|
|
||||||
</RepeatTime>
|
|
||||||
</RegistInputItem>
|
|
||||||
{resultData.repeat_type === "COUNT" && (
|
|
||||||
<>
|
|
||||||
<NoticeInputItem>
|
|
||||||
<InputLabel>반복 횟수</InputLabel>
|
|
||||||
<NoticeInputGroup>
|
|
||||||
<TextInput
|
|
||||||
type="number"
|
|
||||||
value={resultData.repeat_cnt || ''}
|
|
||||||
onChange={e => {
|
|
||||||
handleRepeatValue(e);
|
|
||||||
}}
|
|
||||||
width="80px"
|
|
||||||
/>
|
|
||||||
<span>회</span>
|
|
||||||
</NoticeInputGroup>
|
|
||||||
</NoticeInputItem>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</NoticeInputRow>
|
|
||||||
</NoticeRegistGroup>
|
|
||||||
<NoticeInputRow2>
|
|
||||||
<InputLabel>
|
|
||||||
[메세지 작성]
|
|
||||||
<SubTextRow>* 작성하지 않은 언어는 발송되지 않습니다.</SubTextRow>
|
|
||||||
</InputLabel>
|
|
||||||
<NoticeInputItem2>
|
|
||||||
<InputLabel>언어</InputLabel>
|
|
||||||
<SelectInput onChange={e => handleLanguage(e) } value={message_lang}>
|
|
||||||
{languageType.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</NoticeInputItem2>
|
|
||||||
</NoticeInputRow2>
|
|
||||||
<BoxWrapper>
|
|
||||||
{resultData.game_message.map(content => {
|
|
||||||
return (
|
|
||||||
<Fragment key={content.language}>
|
|
||||||
{message_lang === content.language && (
|
|
||||||
<MessageBox>
|
|
||||||
{/* <BtnWrapper $justify="flex-end">
|
|
||||||
{btnValidation === false ? (
|
|
||||||
<ButtonClose
|
|
||||||
onClick={e => {
|
|
||||||
e.preventDefault();
|
|
||||||
handleDelete(content.language);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<ButtonClose opacity="10%" />
|
|
||||||
)}
|
|
||||||
</BtnWrapper> */}
|
|
||||||
<TitleLang>언어 : {content.language}</TitleLang>
|
|
||||||
<div>
|
|
||||||
<Textarea id={content.language} onChange={e => handleInputData(e)} defaultValue={content.content || ''} maxLength={250} />
|
|
||||||
</div>
|
|
||||||
</MessageBox>
|
|
||||||
)}
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</BoxWrapper>
|
|
||||||
</MessageWrapper>
|
|
||||||
{isNullValue && <SearchBarAlert $marginTop="25px">필수값을 입력해주세요.</SearchBarAlert>}
|
|
||||||
|
|
||||||
<BtnWrapper $gap="10px" $justify="center" $marginTop="20px">
|
|
||||||
<Button text="취소" theme="line" handleClick={handleCancelBtn} />
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
text="등록"
|
|
||||||
name="등록버튼"
|
|
||||||
theme={
|
|
||||||
// resultData.game_message.map(data => data.content === '').includes(true) ||
|
|
||||||
!resultData.game_message.some(data => data.content !== '') ||
|
|
||||||
resultData.game_message.length === 0 ||
|
|
||||||
resultData.send_dt.length === 0 ||
|
|
||||||
typeof resultData.send_dt.length != 'undefined' ||
|
|
||||||
(resultData.is_repeat === true && resultData.repeat_dt === '00:00:00') ||
|
|
||||||
(resultData.is_repeat === true && resultData.message_type === "COUNT" && resultData.repeat_cnt.length === 0) ||
|
|
||||||
(resultData.is_repeat === true && resultData.message_type === "COUNT" && resultData.end_dt.length === 0) ||
|
|
||||||
(resultData.is_repeat === true && resultData.message_type === "COUNT" && typeof resultData.end_dt.length !== 'undefined')
|
|
||||||
? 'disable'
|
|
||||||
: 'primary'
|
|
||||||
}
|
|
||||||
handleClick={handleRegistBtn}
|
|
||||||
/>
|
|
||||||
</BtnWrapper>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
{/* 확인 모달 */}
|
|
||||||
<DynamicModal
|
|
||||||
modalType={modalTypes.confirmOkCancel}
|
|
||||||
view={confirmModal}
|
|
||||||
modalText={confirmText}
|
|
||||||
handleSubmit={() => {
|
|
||||||
doubleSubmitFlag || handleSubmitNotice();
|
|
||||||
setDoubleSubmitFlag(true);
|
|
||||||
}}
|
|
||||||
handleCancel={handleConfirmModal}
|
|
||||||
/>
|
|
||||||
{/* 완료 모달 */}
|
|
||||||
<DynamicModal
|
|
||||||
modalType={modalTypes.completed}
|
|
||||||
view={completeModal}
|
|
||||||
modalText={completeText}
|
|
||||||
handleSubmit={handleCompleteModal}
|
|
||||||
/>
|
|
||||||
{/* 필수값 미입력 모달 */}
|
|
||||||
<DynamicModal
|
|
||||||
modalType={modalTypes.completed}
|
|
||||||
view={errorModal}
|
|
||||||
modalText={t('NULL_MSG')}
|
|
||||||
handleSubmit={handleErrorModal}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default BoardRegistModal;
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
import { TextInput, BtnWrapper, InputLabel, SelectInput } from '../../styles/Components';
|
|
||||||
import Button from '../common/button/Button';
|
|
||||||
import { SearchBarLayout, SearchPeriod } from '../common/SearchBar';
|
|
||||||
import { useState } from 'react';
|
|
||||||
import { caliumStatus } from '../../assets/data/options';
|
|
||||||
|
|
||||||
const CaliumRequestSearchBar = ({ handleSearch, setResultData }) => {
|
|
||||||
const [searchData, setSearchData] = useState({
|
|
||||||
content: '',
|
|
||||||
status: 'ALL',
|
|
||||||
startDate: '',
|
|
||||||
endDate: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleSubmit = event => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
handleSearch(
|
|
||||||
searchData.content,
|
|
||||||
searchData.status ? searchData.status : 'ALL',
|
|
||||||
searchData.startDate ? searchData.startDate : '',
|
|
||||||
searchData.endDate ? searchData.endDate : new Date(),
|
|
||||||
(searchData.startDate && searchData.endDate === '') && setSearchData({ startDate : searchData.startDate ,endDate : new Date()}),
|
|
||||||
);
|
|
||||||
|
|
||||||
setResultData(searchData);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleReset = () => {
|
|
||||||
setSearchData({
|
|
||||||
content: '',
|
|
||||||
status: 'ALL',
|
|
||||||
startDate: '',
|
|
||||||
endDate: '',
|
|
||||||
order: 'DESC',
|
|
||||||
});
|
|
||||||
|
|
||||||
handleSearch('', 'ALL', '', '');
|
|
||||||
setResultData('', 'ALL', '', '');
|
|
||||||
|
|
||||||
window.location.reload();
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchList = [
|
|
||||||
<>
|
|
||||||
<InputLabel>등록 일자</InputLabel>
|
|
||||||
<SearchPeriod
|
|
||||||
startDate={searchData.startDate}
|
|
||||||
handleStartDate={data => {
|
|
||||||
setSearchData({ ...searchData, startDate: data });
|
|
||||||
}}
|
|
||||||
endDate={searchData.endDate}
|
|
||||||
handleEndDate={data => setSearchData({ ...searchData, endDate: data })}
|
|
||||||
/>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>요청 내용</InputLabel>
|
|
||||||
<TextInput
|
|
||||||
type="text"
|
|
||||||
placeholder="요청 내용"
|
|
||||||
value={searchData.content}
|
|
||||||
onChange={e => setSearchData({ ...searchData, content: e.target.value })}
|
|
||||||
/>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>요청 상태</InputLabel>
|
|
||||||
<SelectInput value={searchData.status} onChange={e => setSearchData({ ...searchData, status: e.target.value })}>
|
|
||||||
{caliumStatus.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<BtnWrapper $gap="8px">
|
|
||||||
<Button theme="reset" handleClick={handleReset} type="button" />
|
|
||||||
<Button theme="search" text="검색" handleClick={handleSubmit} type="submit" />
|
|
||||||
</BtnWrapper>
|
|
||||||
</>,
|
|
||||||
];
|
|
||||||
|
|
||||||
return <SearchBarLayout firstColumnData={searchList} direction={'column'} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CaliumRequestSearchBar;
|
|
||||||
@@ -1,564 +0,0 @@
|
|||||||
import { useState, useEffect, Fragment } from 'react';
|
|
||||||
|
|
||||||
import { Title, SelectInput, BtnWrapper, TextInput, Label, InputLabel, Textarea, SearchBarAlert } from '../../styles/Components';
|
|
||||||
import Button from '../../components/common/button/Button';
|
|
||||||
import Modal from '../../components/common/modal/Modal';
|
|
||||||
import { EventIsItem, EventModify, MailModify } from '../../apis';
|
|
||||||
|
|
||||||
import { authList } from '../../store/authList';
|
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { authType, benItems, commonStatus, modalTypes, wellType } from '../../assets/data';
|
|
||||||
import {
|
|
||||||
AppendRegistBox, AppendRegistTable, AreaBtnClose,
|
|
||||||
BtnDelete, DetailInputItem, DetailInputRow,
|
|
||||||
DetailModalWrapper, RegistGroup, DetailRegistInfo, DetailState,
|
|
||||||
Item, ItemList, LangArea
|
|
||||||
} from '../../styles/ModuleComponents';
|
|
||||||
import DynamicModal from '../common/modal/DynamicModal';
|
|
||||||
import { convertKTC, combineDateTime, timeDiffMinute, convertKTCDate } from '../../utils';
|
|
||||||
import DateTimeInput from '../common/input/DateTimeInput';
|
|
||||||
|
|
||||||
const EventDetailModal = ({ detailView, handleDetailView, content, setDetailData }) => {
|
|
||||||
const userInfo = useRecoilValue(authList);
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const token = sessionStorage.getItem('token');
|
|
||||||
|
|
||||||
const id = content && content.id;
|
|
||||||
const updateAuth = userInfo.auth_list && userInfo.auth_list.some(auth => auth.id === authType.eventUpdate);
|
|
||||||
|
|
||||||
const [time, setTime] = useState({
|
|
||||||
start_hour: '00',
|
|
||||||
start_min: '00',
|
|
||||||
end_hour: '00',
|
|
||||||
end_min: '00',
|
|
||||||
}); //시간 정보
|
|
||||||
|
|
||||||
const [item, setItem] = useState('');
|
|
||||||
const [itemCount, setItemCount] = useState('');
|
|
||||||
const [resource, setResource] = useState('19010001');
|
|
||||||
const [resourceCount, setResourceCount] = useState('');
|
|
||||||
|
|
||||||
const [modifyModal, setModifyModal] = useState('hidden');
|
|
||||||
const [completeModal, setCompleteModal] = useState('hidden');
|
|
||||||
const [resultData, setResultData] = useState({});
|
|
||||||
|
|
||||||
const [modalState, setModalState] = useState({
|
|
||||||
updateConfirmModal: 'hidden',
|
|
||||||
updateCompleteModal: 'hidden',
|
|
||||||
});
|
|
||||||
|
|
||||||
const [isNullValue, setIsNullValue] = useState(false);
|
|
||||||
// 과거 판단
|
|
||||||
const [isPast, setIsPast] = useState(false);
|
|
||||||
const [isChanged, setIsChanged] = useState(false);
|
|
||||||
|
|
||||||
const [btnValidation, setBtnValidation] = useState(false);
|
|
||||||
const [isReadOnly, setIsReadOnly] = useState(false);
|
|
||||||
const [itemCheckMsg, setItemCheckMsg] = useState('');
|
|
||||||
const [alertMsg, setAlertMsg] = useState('');
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if(content){
|
|
||||||
const start_dt_KTC = convertKTCDate(content.start_dt)
|
|
||||||
const end_dt_KTC = convertKTCDate(content.end_dt)
|
|
||||||
|
|
||||||
setResultData({
|
|
||||||
start_dt: start_dt_KTC,
|
|
||||||
end_dt: end_dt_KTC,
|
|
||||||
event_type: content.event_type,
|
|
||||||
mail_list: content.mail_list,
|
|
||||||
item_list: content.item_list,
|
|
||||||
});
|
|
||||||
|
|
||||||
setTime({ ...time,
|
|
||||||
start_hour: String(start_dt_KTC.getHours()).padStart(2, '0'),
|
|
||||||
start_min: String(start_dt_KTC.getMinutes()).padStart(2, '0'),
|
|
||||||
end_hour: String(end_dt_KTC.getHours()).padStart(2, '0'),
|
|
||||||
end_min: String(end_dt_KTC.getMinutes()).padStart(2, '0')
|
|
||||||
});
|
|
||||||
|
|
||||||
start_dt_KTC < (new Date) ? setIsPast(true) : setIsPast(false);
|
|
||||||
content.mail_list.length === 1 && setBtnValidation(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
setItem('');
|
|
||||||
|
|
||||||
}, [content]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if(!updateAuth || isPast){
|
|
||||||
setIsReadOnly(true);
|
|
||||||
}else{
|
|
||||||
setIsReadOnly(false);
|
|
||||||
}
|
|
||||||
}, [updateAuth, isPast]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (conditionCheck()) {
|
|
||||||
setIsNullValue(false);
|
|
||||||
} else {
|
|
||||||
setIsNullValue(true);
|
|
||||||
}
|
|
||||||
}, [resultData]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setItemCheckMsg('');
|
|
||||||
}, [item]);
|
|
||||||
|
|
||||||
// 아이템 수량 숫자 체크
|
|
||||||
const handleItemCount = e => {
|
|
||||||
if (e.target.value === '0' || e.target.value === '-0') {
|
|
||||||
setItemCount('1');
|
|
||||||
e.target.value = '1';
|
|
||||||
} else if (e.target.value < 0) {
|
|
||||||
let plusNum = Math.abs(e.target.value);
|
|
||||||
setItemCount(plusNum);
|
|
||||||
} else {
|
|
||||||
setItemCount(e.target.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 아이템 추가
|
|
||||||
const handleItemList = async () => {
|
|
||||||
if(benItems.includes(item)){
|
|
||||||
setAlertMsg(t('MAIL_ITEM_ADD_BEN'))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(item.length === 0 || itemCount.length === 0) return;
|
|
||||||
|
|
||||||
const token = sessionStorage.getItem('token');
|
|
||||||
const result = await EventIsItem(token, {item: item});
|
|
||||||
|
|
||||||
if(result.data.result === "ERROR"){
|
|
||||||
setItemCheckMsg(t('NOT_ITEM'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const itemIndex = resultData.item_list.findIndex((data) => data.item === item);
|
|
||||||
if (itemIndex !== -1) {
|
|
||||||
setItemCheckMsg(t('MAIL_ITEM_ADD_DUPL'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const newItem = { item: item, item_cnt: itemCount, item_name: result.data.data.item_info.item_name };
|
|
||||||
|
|
||||||
resultData.item_list.push(newItem);
|
|
||||||
|
|
||||||
setIsChanged(true);
|
|
||||||
setItem('');
|
|
||||||
setItemCount('');
|
|
||||||
};
|
|
||||||
|
|
||||||
// 아이템 삭제
|
|
||||||
const onItemRemove = id => {
|
|
||||||
let filterList = resultData.item_list && resultData.item_list.filter(item => item !== resultData.item_list[id]);
|
|
||||||
setIsChanged(true);
|
|
||||||
|
|
||||||
setResultData({ ...resultData, item_list: filterList });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 자원 수량 숫자 체크
|
|
||||||
const handleResourceCount = e => {
|
|
||||||
if (e.target.value === '0' || e.target.value === '-0') {
|
|
||||||
setResourceCount('1');
|
|
||||||
e.target.value = '1';
|
|
||||||
} else if (e.target.value < 0) {
|
|
||||||
let plusNum = Math.abs(e.target.value);
|
|
||||||
setResourceCount(plusNum);
|
|
||||||
} else {
|
|
||||||
setResourceCount(e.target.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 자원 추가
|
|
||||||
const handleResourceList = (e) => {
|
|
||||||
if(resource.length === 0 || resourceCount.length === 0) return;
|
|
||||||
|
|
||||||
const itemIndex = resultData.item_list.findIndex(
|
|
||||||
(item) => item.item === resource
|
|
||||||
);
|
|
||||||
|
|
||||||
if (itemIndex !== -1) {
|
|
||||||
const item_cnt = resultData.item_list[itemIndex].item_cnt;
|
|
||||||
resultData.item_list[itemIndex].item_cnt = Number(item_cnt) + Number(resourceCount);
|
|
||||||
} else {
|
|
||||||
const name = wellType.find(well => well.value === resource).name;
|
|
||||||
const newItem = { item: resource, item_cnt: resourceCount, item_name: name };
|
|
||||||
resultData.item_list.push(newItem);
|
|
||||||
}
|
|
||||||
setIsChanged(true);
|
|
||||||
setResource('')
|
|
||||||
setResourceCount('');
|
|
||||||
};
|
|
||||||
|
|
||||||
// 입력창 삭제
|
|
||||||
const onLangDelete = language => {
|
|
||||||
let filterList = resultData.mail_list && resultData.mail_list.filter(el => el.language !== language);
|
|
||||||
|
|
||||||
if (filterList.length === 1) setBtnValidation(true);
|
|
||||||
|
|
||||||
setIsChanged(true);
|
|
||||||
setResultData({ ...resultData, mail_list: filterList });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 날짜 처리
|
|
||||||
const handleDateChange = (data, type) => {
|
|
||||||
const date = new Date(data);
|
|
||||||
setResultData({
|
|
||||||
...resultData,
|
|
||||||
[`${type}_dt`]: combineDateTime(date, time[`${type}_hour`], time[`${type}_min`]),
|
|
||||||
});
|
|
||||||
setIsChanged(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 시간 처리
|
|
||||||
const handleTimeChange = (e, type) => {
|
|
||||||
const { id, value } = e.target;
|
|
||||||
const newTime = { ...time, [`${type}_${id}`]: value };
|
|
||||||
setTime(newTime);
|
|
||||||
|
|
||||||
const date = resultData[`${type}_dt`] ? new Date(resultData[`${type}_dt`]) : new Date();
|
|
||||||
|
|
||||||
setResultData({
|
|
||||||
...resultData,
|
|
||||||
[`${type}_dt`]: combineDateTime(date, newTime[`${type}_hour`], newTime[`${type}_min`]),
|
|
||||||
});
|
|
||||||
setIsChanged(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 확인 버튼 후 다 초기화
|
|
||||||
const handleReset = () => {
|
|
||||||
setBtnValidation(false);
|
|
||||||
setIsNullValue(false);
|
|
||||||
setIsChanged(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const conditionCheck = () => {
|
|
||||||
return (
|
|
||||||
content && content.mail_list.every(data => data.content !== '' && data.title !== '') &&
|
|
||||||
isChanged
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleModalView = (type) => {
|
|
||||||
setModalState((prevState) => ({
|
|
||||||
...prevState,
|
|
||||||
[`${type}Modal`]: 'view',
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleModalClose = (type) => {
|
|
||||||
setModalState((prevState) => ({
|
|
||||||
...prevState,
|
|
||||||
[`${type}Modal`]: 'hidden',
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSubmit = async (type, param = null) => {
|
|
||||||
switch (type) {
|
|
||||||
case "submit":
|
|
||||||
if (!conditionCheck()) return;
|
|
||||||
|
|
||||||
handleModalView('updateConfirm');
|
|
||||||
break;
|
|
||||||
case "updateConfirm":
|
|
||||||
const timeDiff = timeDiffMinute(resultData.start_dt, (new Date))
|
|
||||||
// 이벤트 시작 30분전이나 이미 SystemMail이 add된 상태에서는 수정할 수 없다.
|
|
||||||
if(content.add_flag || timeDiff <= 30){
|
|
||||||
setAlertMsg(t('EVENT_TIME_LIMIT_UPDATE'));
|
|
||||||
handleModalClose('updateConfirm');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await EventModify(token, id, resultData);
|
|
||||||
handleModalClose('updateConfirm');
|
|
||||||
handleModalView('updateComplete');
|
|
||||||
break;
|
|
||||||
case "updateComplete":
|
|
||||||
handleModalClose('updateComplete');
|
|
||||||
window.location.reload();
|
|
||||||
break;
|
|
||||||
case "warning":
|
|
||||||
setAlertMsg('');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const detailState = (status) => {
|
|
||||||
switch (status) {
|
|
||||||
case commonStatus.wait:
|
|
||||||
return <DetailState>대기</DetailState>;
|
|
||||||
case commonStatus.running:
|
|
||||||
return <DetailState>진행중</DetailState>;
|
|
||||||
case commonStatus.finish:
|
|
||||||
return <DetailState result={commonStatus.finish}>완료</DetailState>;
|
|
||||||
case commonStatus.fail:
|
|
||||||
return <DetailState result={commonStatus.fail}>실패</DetailState>;
|
|
||||||
case commonStatus.delete:
|
|
||||||
return <DetailState result={commonStatus.delete}>삭제</DetailState>;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Modal min="960px" $view={detailView}>
|
|
||||||
<Title $align="center">이벤트 상세 정보</Title>
|
|
||||||
{content &&
|
|
||||||
<DetailRegistInfo>
|
|
||||||
<span>등록자 : {content.create_by}</span>
|
|
||||||
<span>등록일 : {convertKTC(content.create_dt, false)}</span>
|
|
||||||
{typeof content.update_by !== 'undefined' && (
|
|
||||||
<>
|
|
||||||
<span>수정자 : {content.update_by}</span>
|
|
||||||
<span>수정일 : {convertKTC(content.update_dt, false)}</span>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</DetailRegistInfo>
|
|
||||||
}
|
|
||||||
<DetailModalWrapper>
|
|
||||||
{content &&
|
|
||||||
<RegistGroup>
|
|
||||||
<DetailInputRow>
|
|
||||||
<DateTimeInput
|
|
||||||
title="이벤트 기간"
|
|
||||||
dateName="시작 일자"
|
|
||||||
selectedDate={convertKTCDate(content.start_dt)}
|
|
||||||
handleSelectedDate={data => handleDateChange(data, 'start')}
|
|
||||||
onChange={e => handleTimeChange(e, 'start')}
|
|
||||||
|
|
||||||
/>
|
|
||||||
<DateTimeInput
|
|
||||||
dateName="종료 일자"
|
|
||||||
selectedDate={convertKTCDate(content.end_dt)}
|
|
||||||
handleSelectedDate={data => handleDateChange(data, 'end')}
|
|
||||||
onChange={e => handleTimeChange(e, 'end')}
|
|
||||||
/>
|
|
||||||
</DetailInputRow>
|
|
||||||
<DetailInputRow>
|
|
||||||
<DetailInputItem>
|
|
||||||
<InputLabel>이벤트 상태</InputLabel>
|
|
||||||
<div>{detailState(content.status)}</div>
|
|
||||||
</DetailInputItem>
|
|
||||||
{content.status === commonStatus.delete &&
|
|
||||||
<DetailInputItem>
|
|
||||||
<InputLabel>삭제 사유</InputLabel>
|
|
||||||
<div>{content.delete_desc}</div>
|
|
||||||
</DetailInputItem>
|
|
||||||
}
|
|
||||||
</DetailInputRow>
|
|
||||||
|
|
||||||
</RegistGroup>
|
|
||||||
}
|
|
||||||
{resultData.mail_list &&
|
|
||||||
resultData.mail_list.map(data => {
|
|
||||||
return (
|
|
||||||
<Fragment key={data.language}>
|
|
||||||
<AppendRegistBox>
|
|
||||||
<LangArea>
|
|
||||||
언어 : {data.language}
|
|
||||||
{btnValidation === false && !isReadOnly ? (
|
|
||||||
<AreaBtnClose
|
|
||||||
onClick={e => {
|
|
||||||
e.preventDefault();
|
|
||||||
onLangDelete(data.language);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<AreaBtnClose opacity="10%" />
|
|
||||||
)}
|
|
||||||
</LangArea>
|
|
||||||
<AppendRegistTable>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th width="120">
|
|
||||||
<Label>제목</Label>
|
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
<DetailInputItem>
|
|
||||||
<TextInput
|
|
||||||
placeholder="우편 제목 입력"
|
|
||||||
maxLength="30"
|
|
||||||
id={data.language}
|
|
||||||
value={data.title}
|
|
||||||
readOnly={isReadOnly}
|
|
||||||
onChange={e => {
|
|
||||||
let list = [...resultData.mail_list];
|
|
||||||
let findIndex = resultData.mail_list && resultData.mail_list.findIndex(item => item.language === e.target.id);
|
|
||||||
list[findIndex].title = e.target.value.trimStart();
|
|
||||||
|
|
||||||
setResultData({ ...resultData, mail_list: list });
|
|
||||||
setIsChanged(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</DetailInputItem>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
<Label>내용</Label>
|
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
<Textarea
|
|
||||||
value={data.content}
|
|
||||||
readOnly={isReadOnly}
|
|
||||||
id={data.language}
|
|
||||||
onChange={e => {
|
|
||||||
if (e.target.value.length > 2000) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let list = [...resultData.mail_list];
|
|
||||||
let findIndex = resultData.mail_list && resultData.mail_list.findIndex(item => item.language === e.target.id);
|
|
||||||
list[findIndex].content = e.target.value.trimStart();
|
|
||||||
|
|
||||||
setResultData({ ...resultData, mail_list: list });
|
|
||||||
setIsChanged(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</AppendRegistTable>
|
|
||||||
</AppendRegistBox>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
<AppendRegistBox>
|
|
||||||
<AppendRegistTable>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th width="120">
|
|
||||||
<Label>아이템 첨부</Label>
|
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
<DetailInputItem>
|
|
||||||
<TextInput
|
|
||||||
placeholder="Item Meta id 입력"
|
|
||||||
value={item}
|
|
||||||
onChange={e => {
|
|
||||||
let list = [];
|
|
||||||
list = e.target.value.trimStart();
|
|
||||||
setItem(list);
|
|
||||||
}}
|
|
||||||
disabled={isReadOnly}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
placeholder="수량"
|
|
||||||
value={itemCount}
|
|
||||||
type="number"
|
|
||||||
onChange={e => handleItemCount(e)}
|
|
||||||
width="90px"
|
|
||||||
disabled={isReadOnly}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
text="추가"
|
|
||||||
theme={itemCount.length === 0 || item.length === 0 ? 'disable' : 'search'}
|
|
||||||
handleClick={handleItemList}
|
|
||||||
/>
|
|
||||||
{itemCheckMsg && <SearchBarAlert>{itemCheckMsg}</SearchBarAlert>}
|
|
||||||
</DetailInputItem>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th width="120">
|
|
||||||
<Label>자원 첨부</Label>
|
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
<DetailInputItem>
|
|
||||||
<SelectInput onChange={e => setResource(e.target.value)} value={resource} disabled={isReadOnly}>
|
|
||||||
{wellType.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
<TextInput
|
|
||||||
placeholder="수량"
|
|
||||||
type="number"
|
|
||||||
value={resourceCount}
|
|
||||||
disabled={isReadOnly}
|
|
||||||
onChange={e => handleResourceCount(e)}
|
|
||||||
width="200px"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
text="추가"
|
|
||||||
theme={resourceCount.length === 0 || resource.length === 0 ? 'disable' : 'search'}
|
|
||||||
handleClick={handleResourceList}
|
|
||||||
width="100px"
|
|
||||||
height="35px"
|
|
||||||
errorMessage={isReadOnly} />
|
|
||||||
</DetailInputItem>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
{resultData.item_list && (
|
|
||||||
<ItemList>
|
|
||||||
{resultData.item_list.map((data, index) => {
|
|
||||||
return (
|
|
||||||
<Item key={index}>
|
|
||||||
<span>
|
|
||||||
{data.item_name}[{data.item}] ({data.item_cnt})
|
|
||||||
</span>
|
|
||||||
{!isReadOnly && <BtnDelete onClick={() => onItemRemove(index)}></BtnDelete>}
|
|
||||||
</Item>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</ItemList>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</AppendRegistTable>
|
|
||||||
</AppendRegistBox>
|
|
||||||
</DetailModalWrapper>
|
|
||||||
<BtnWrapper $justify="flex-end" $gap="10px" $paddingTop="20px">
|
|
||||||
<Button
|
|
||||||
text="확인"
|
|
||||||
theme="line"
|
|
||||||
name="확인버튼"
|
|
||||||
handleClick={() => {
|
|
||||||
handleDetailView();
|
|
||||||
handleReset();
|
|
||||||
setDetailData('');
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{!isReadOnly && (
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
text="수정"
|
|
||||||
id="수정버튼"
|
|
||||||
theme={conditionCheck() ? 'primary' : 'disable'}
|
|
||||||
handleClick={() => handleSubmit('submit')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</BtnWrapper>
|
|
||||||
</Modal>
|
|
||||||
{/* 확인 모달 */}
|
|
||||||
<DynamicModal
|
|
||||||
modalType={modalTypes.confirmOkCancel}
|
|
||||||
view={modalState.updateConfirmModal}
|
|
||||||
modalText={t('MAIL_UPDATE_SAVE')}
|
|
||||||
handleCancel={() => handleModalClose('updateConfirm')}
|
|
||||||
handleSubmit={() => handleSubmit('updateConfirm')}
|
|
||||||
/>
|
|
||||||
{/* 완료 모달 */}
|
|
||||||
<DynamicModal
|
|
||||||
modalType={modalTypes.completed}
|
|
||||||
view={modalState.updateCompleteModal}
|
|
||||||
modalText={t('UPDATE_COMPLETED')}
|
|
||||||
handleSubmit={() => handleSubmit('updateComplete')}
|
|
||||||
/>
|
|
||||||
{/* 경고 모달 */}
|
|
||||||
<DynamicModal
|
|
||||||
modalType={modalTypes.completed}
|
|
||||||
view={alertMsg ? 'view' : 'hidden'}
|
|
||||||
modalText={alertMsg}
|
|
||||||
handleSubmit={() => handleSubmit('warning')}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default EventDetailModal;
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
import { TextInput, BtnWrapper, InputLabel, SelectInput } from '../../styles/Components';
|
|
||||||
import Button from '../common/button/Button';
|
|
||||||
import { SearchBarLayout, SearchPeriod } from '../common/SearchBar';
|
|
||||||
import { useState } from 'react';
|
|
||||||
import { eventStatus } from '../../assets/data';
|
|
||||||
|
|
||||||
const EventListSearchBar = ({ handleSearch, setResultData }) => {
|
|
||||||
const [searchData, setSearchData] = useState({
|
|
||||||
title: '',
|
|
||||||
content: '',
|
|
||||||
status: 'ALL',
|
|
||||||
startDate: '',
|
|
||||||
endDate: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleSubmit = event => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
handleSearch(
|
|
||||||
searchData.title,
|
|
||||||
searchData.content,
|
|
||||||
searchData.status ? searchData.status : 'ALL',
|
|
||||||
searchData.startDate ? searchData.startDate : '',
|
|
||||||
searchData.endDate ? searchData.endDate : new Date(),
|
|
||||||
(searchData.startDate && searchData.endDate === '') && setSearchData({ startDate : searchData.startDate ,endDate : new Date()}),
|
|
||||||
);
|
|
||||||
|
|
||||||
setResultData(searchData);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleReset = () => {
|
|
||||||
setSearchData({
|
|
||||||
title: '',
|
|
||||||
content: '',
|
|
||||||
status: 'ALL',
|
|
||||||
startDate: '',
|
|
||||||
endDate: '',
|
|
||||||
order: 'DESC',
|
|
||||||
});
|
|
||||||
|
|
||||||
handleSearch('', '', 'ALL', '', '');
|
|
||||||
setResultData('', '', 'ALL', '', '');
|
|
||||||
|
|
||||||
window.location.reload();
|
|
||||||
};
|
|
||||||
|
|
||||||
// console.log("searchData.endDate", searchData.endDate)
|
|
||||||
|
|
||||||
const searchList = [
|
|
||||||
<>
|
|
||||||
<InputLabel>우편 제목</InputLabel>
|
|
||||||
<TextInput
|
|
||||||
type="text"
|
|
||||||
placeholder="우편 제목"
|
|
||||||
value={searchData.title}
|
|
||||||
onChange={e => setSearchData({ ...searchData, title: e.target.value })}
|
|
||||||
/>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>조회 일자</InputLabel>
|
|
||||||
<SearchPeriod
|
|
||||||
startDate={searchData.startDate}
|
|
||||||
handleStartDate={data => {
|
|
||||||
setSearchData({ ...searchData, startDate: data });
|
|
||||||
}}
|
|
||||||
endDate={searchData.endDate}
|
|
||||||
handleEndDate={data => setSearchData({ ...searchData, endDate: data })}
|
|
||||||
/>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>우편 내용</InputLabel>
|
|
||||||
<TextInput
|
|
||||||
type="text"
|
|
||||||
placeholder="우편 내용(공백으로 구분)"
|
|
||||||
value={searchData.content}
|
|
||||||
onChange={e => setSearchData({ ...searchData, content: e.target.value })}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
];
|
|
||||||
|
|
||||||
const optionList = [
|
|
||||||
<>
|
|
||||||
<InputLabel>이벤트 상태</InputLabel>
|
|
||||||
<SelectInput value={searchData.status} onChange={e => setSearchData({ ...searchData, status: e.target.value })}>
|
|
||||||
{eventStatus.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<></>,<></>,<></>,<></>,<></>,<></>,<></>,<></>,<></>,<></>,<></>,<></>,<></>,
|
|
||||||
<>
|
|
||||||
<BtnWrapper $gap="8px">
|
|
||||||
<Button theme="reset" handleClick={handleReset} type="button" />
|
|
||||||
<Button theme="search" text="검색" handleClick={handleSubmit} type="submit" />
|
|
||||||
</BtnWrapper>
|
|
||||||
</>,
|
|
||||||
];
|
|
||||||
return <SearchBarLayout firstColumnData={searchList} secondColumnData={optionList} direction={'column'} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default EventListSearchBar;
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import { TextInput, BtnWrapper, InputLabel, SelectInput, InputGroup } from '../../styles/Components';
|
|
||||||
import Button from '../common/button/Button';
|
|
||||||
import { SearchBarLayout, SearchPeriod } from '../common/SearchBar';
|
|
||||||
|
|
||||||
const ItemsSearchBar = ({ handleSearch, setResultData }) => {
|
|
||||||
const [searchData, setSearchData] = useState({
|
|
||||||
searchType: 'GUID',
|
|
||||||
data: '',
|
|
||||||
status: 'ALL',
|
|
||||||
restore: 'ALL',
|
|
||||||
sendDate: '',
|
|
||||||
endDate: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const searchType = [
|
|
||||||
{ value: 'GUID', name: 'GUID' },
|
|
||||||
{ value: 'NAME', name: '닉네임' }
|
|
||||||
];
|
|
||||||
|
|
||||||
const status = [
|
|
||||||
{ value: 'ALL', name: '상태' },
|
|
||||||
{ value: 'ACTIVE', name: '활성' },
|
|
||||||
{ value: 'DEACTIVE', name: '비활성' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const restore = [
|
|
||||||
{ value: 'ALL', name: '복구' },
|
|
||||||
{ value: 'POSSIBLE', name: '가능' },
|
|
||||||
{ value: 'IMPOSSIBLE', name: '불가능' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const handleSubmit = event => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
handleSearch(
|
|
||||||
searchData.searchType ? searchData.searchType : 'GUID',
|
|
||||||
searchData.data,
|
|
||||||
searchData.status ? searchData.status : 'ALL',
|
|
||||||
searchData.restore ? searchData.restore : 'ALL',
|
|
||||||
searchData.sendDate ? searchData.sendDate : '',
|
|
||||||
searchData.endDate ? searchData.endDate : new Date(),
|
|
||||||
);
|
|
||||||
|
|
||||||
setResultData(searchData);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 초기화 버튼
|
|
||||||
const handleReset = () => {
|
|
||||||
setSearchData({
|
|
||||||
searchType: 'GUID',
|
|
||||||
data: '',
|
|
||||||
status: 'ALL',
|
|
||||||
restore: 'ALL',
|
|
||||||
sendDate: '',
|
|
||||||
endDate: '',
|
|
||||||
});
|
|
||||||
handleSearch('GUID', '', 'ALL', 'ALL', '', '');
|
|
||||||
setResultData('GUID', '', 'ALL', 'ALL', '', '');
|
|
||||||
window.location.reload();
|
|
||||||
};
|
|
||||||
|
|
||||||
// console.log(searchData);
|
|
||||||
|
|
||||||
const searchList = [
|
|
||||||
<>
|
|
||||||
<InputGroup>
|
|
||||||
<SelectInput value={searchData.searchType} onChange={e => setSearchData({ ...searchData, searchType: e.target.value })}>
|
|
||||||
{searchType.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
<TextInput
|
|
||||||
type="text"
|
|
||||||
placeholder={searchData.searchType === 'GUID' ? 'GUID 입력' : '닉네임 입력'}
|
|
||||||
value={searchData.data}
|
|
||||||
width="600px"
|
|
||||||
onChange={e => setSearchData({ ...searchData, data: e.target.value })}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
</>
|
|
||||||
];
|
|
||||||
|
|
||||||
const optionList = [
|
|
||||||
<>
|
|
||||||
<SelectInput value={searchData.status} onChange={e => setSearchData({ ...searchData, status: e.target.value })}>
|
|
||||||
{status.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<SelectInput value={searchData.restore} onChange={e => setSearchData({ ...searchData, restore: e.target.value })}>
|
|
||||||
{restore.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>생성 날짜</InputLabel>
|
|
||||||
<SearchPeriod
|
|
||||||
startDate={searchData.sendDate}
|
|
||||||
handleStartDate={data => {
|
|
||||||
setSearchData({ ...searchData, sendDate: data });
|
|
||||||
}}
|
|
||||||
endDate={searchData.endDate}
|
|
||||||
handleEndDate={data => setSearchData({ ...searchData, endDate: data })}
|
|
||||||
maxDate={new Date()}
|
|
||||||
/>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<BtnWrapper $gap="8px">
|
|
||||||
<Button theme="reset" handleClick={handleReset} />
|
|
||||||
<Button theme="search" text="검색" type="submit" handleClick={handleSubmit} />
|
|
||||||
</BtnWrapper>
|
|
||||||
</>,
|
|
||||||
];
|
|
||||||
return <SearchBarLayout firstColumnData={searchList} secondColumnData={optionList} direction={'column'} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ItemsSearchBar;
|
|
||||||
@@ -1,517 +0,0 @@
|
|||||||
import { 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, InputLabel,
|
|
||||||
} from '../../styles/Components';
|
|
||||||
|
|
||||||
import {
|
|
||||||
FormHelperText,
|
|
||||||
FormInput,
|
|
||||||
FormLabel,
|
|
||||||
FormTextArea,
|
|
||||||
FormTextAreaWrapper,
|
|
||||||
MessageWrapper,
|
|
||||||
FormRowGroup,
|
|
||||||
NoticeInputRow2,
|
|
||||||
NoticeInputItem2, BoxWrapper, FormStatusBar, FormStatusLabel, FormStatusWarning, FormButtonContainer,
|
|
||||||
} from '../../styles/ModuleComponents';
|
|
||||||
import { modalTypes } from '../../assets/data';
|
|
||||||
import {DynamicModal, Modal, DateTimeRangePicker} from '../common';
|
|
||||||
import { LandAuctionModify, LandAuctionSingleRegist } from '../../apis';
|
|
||||||
import { TYPE_MODIFY, TYPE_REGISTRY } from '../../assets/data/adminConstants';
|
|
||||||
import { landAuctionStatus, landAuctionStatusType, languageType, CurrencyType } from '../../assets/data';
|
|
||||||
import { useModal } from '../../utils/hook';
|
|
||||||
import { convertKTCDate } from '../../utils';
|
|
||||||
|
|
||||||
const LandAuctionModal = ({ modalType, detailView, handleDetailView, content, setDetailData, landData, buildingData }) => {
|
|
||||||
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 [message_lang, setMessage_lang] = useState('KO');
|
|
||||||
|
|
||||||
const [isNullValue, setIsNullValue] = useState(false); // 데이터 값 체크
|
|
||||||
const [alertMsg, setAlertMsg] = useState('');
|
|
||||||
const [selectLand, setSelectLand] = useState(initLandData);
|
|
||||||
|
|
||||||
const [resultData, setResultData] = useState(initData); //데이터 정보
|
|
||||||
const [resetDateTime, setResetDateTime] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if(modalType === TYPE_MODIFY && content && Object.keys(content).length > 0){
|
|
||||||
setResultData({
|
|
||||||
land_id: content.land_id,
|
|
||||||
land_name: content.land_name,
|
|
||||||
land_socket: content.land_socket,
|
|
||||||
land_size: content.land_size,
|
|
||||||
auction_seq: content.auction_seq,
|
|
||||||
currency_type: content.currency_type,
|
|
||||||
start_price: content.start_price,
|
|
||||||
resv_start_dt: convertKTCDate(content.resv_start_dt),
|
|
||||||
resv_end_dt: convertKTCDate(content.resv_end_dt),
|
|
||||||
auction_start_dt: convertKTCDate(content.auction_start_dt),
|
|
||||||
auction_end_dt: convertKTCDate(content.auction_end_dt),
|
|
||||||
message_list: content.message_list,
|
|
||||||
});
|
|
||||||
const land = landData.find(land => land.id === parseInt(content.land_id));
|
|
||||||
setSelectLand(land);
|
|
||||||
}
|
|
||||||
}, [modalType, content]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (checkCondition()) {
|
|
||||||
setIsNullValue(false);
|
|
||||||
} else {
|
|
||||||
setIsNullValue(true);
|
|
||||||
}
|
|
||||||
}, [resultData]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (resetDateTime) {
|
|
||||||
setResetDateTime(false);
|
|
||||||
}
|
|
||||||
}, [resetDateTime]);
|
|
||||||
|
|
||||||
// 입력 수량 처리
|
|
||||||
const handleCount = e => {
|
|
||||||
const regex = /^\d*\.?\d{0,2}$/;
|
|
||||||
if (!regex.test(e.target.value) && e.target.value !== '-') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let count = 0;
|
|
||||||
if (e.target.value === '-0') {
|
|
||||||
count = 1;
|
|
||||||
} else if (e.target.value < 0) {
|
|
||||||
let plusNum = Math.abs(e.target.value);
|
|
||||||
count = plusNum;
|
|
||||||
} else{
|
|
||||||
count = e.target.value;
|
|
||||||
}
|
|
||||||
setResultData((prevState) => ({
|
|
||||||
...prevState,
|
|
||||||
start_price: count,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleReservationChange = {
|
|
||||||
start: (date) => {
|
|
||||||
setResultData(prev => ({ ...prev, resv_start_dt: date }));
|
|
||||||
},
|
|
||||||
end: (date) => {
|
|
||||||
setResultData(prev => ({ ...prev, resv_end_dt: date }));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleAuctionChange = {
|
|
||||||
start: (date) => {
|
|
||||||
setResultData(prev => ({ ...prev, auction_start_dt: date }));
|
|
||||||
},
|
|
||||||
end: (date) => {
|
|
||||||
setResultData(prev => ({ ...prev, auction_end_dt: date }));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 입력 글자 제한
|
|
||||||
const handleInputData = e => {
|
|
||||||
if (e.target.value.length > 250) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const updatedMessages = resultData.message_list.map(msg =>
|
|
||||||
msg.language === message_lang
|
|
||||||
? { ...msg, content: e.target.value.trimStart() }
|
|
||||||
: msg
|
|
||||||
);
|
|
||||||
|
|
||||||
setResultData(prev => ({
|
|
||||||
...prev,
|
|
||||||
message_list: updatedMessages
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
// 언어 선택
|
|
||||||
const handleLanguage = e => {
|
|
||||||
setMessage_lang(e.target.value);
|
|
||||||
if(!resultData.message_list.some(({language}) => language === e.target.value))
|
|
||||||
setResultData({ ...resultData, message_list: [...resultData.message_list, {language: e.target.value, content: ''}] })
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleLand = e => {
|
|
||||||
const land_id = e.target.value;
|
|
||||||
const land = landData.find(land => land.id === parseInt(land_id));
|
|
||||||
const instance = buildingData.find(building => building.id === parseInt(land.buildingId))?.socket;
|
|
||||||
setSelectLand(land);
|
|
||||||
setResultData({ ...resultData, land_id: land_id, land_name: land.name, land_size: land.size, land_socket: instance });
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleReset = () => {
|
|
||||||
setMessage_lang('KO')
|
|
||||||
setDetailData({});
|
|
||||||
setSelectLand(initLandData);
|
|
||||||
setResultData(initData);
|
|
||||||
setResetDateTime(true);
|
|
||||||
handleDetailView();
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSubmit = async (type, param = null) => {
|
|
||||||
switch (type) {
|
|
||||||
case "submit":
|
|
||||||
if (!checkCondition()) return;
|
|
||||||
|
|
||||||
const minAllowedTime = new Date(new Date().getTime() + 5 * 60000);
|
|
||||||
if (isView('recv') && resultData.resv_start_dt < minAllowedTime) {
|
|
||||||
setAlertMsg(t('LAND_AUCTION_MADEL_RESV_START_WARNING'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (resultData.auction_start_dt < minAllowedTime) {
|
|
||||||
setAlertMsg(t('LAND_AUCTION_MADEL_AUCTION_START_WARNING'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(resultData.resv_start_dt >= resultData.auction_start_dt || resultData.resv_start_dt >= resultData.auction_end_dt) {
|
|
||||||
setAlertMsg(t('LAND_AUCTION_MADEL_AUCTION_DIFF_RESERVATION'))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(resultData.auction_start_dt >= resultData.auction_end_dt) {
|
|
||||||
setAlertMsg(t('LAND_AUCTION_MADEL_AUCTION_DIFF_AUCTION'))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//화면에 머물면서 상태는 안바꼈을 경우가 있기에 경매시작시간 지났을경우 차단
|
|
||||||
if (modalType === TYPE_MODIFY && resultData.auction_start_dt < new Date()) {
|
|
||||||
setAlertMsg(t('LAND_AUCTION_MADEL_MODIFY_START'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
handleModalView('registConfirm');
|
|
||||||
break;
|
|
||||||
case "cancel":
|
|
||||||
handleModalView('cancel');
|
|
||||||
break;
|
|
||||||
case "cancelConfirm":
|
|
||||||
handleModalClose('cancel');
|
|
||||||
handleReset();
|
|
||||||
break;
|
|
||||||
case "registConfirm":
|
|
||||||
setLoading(true);
|
|
||||||
|
|
||||||
if(isView('modify')){
|
|
||||||
await LandAuctionModify(token, content?.id, resultData).then(data => {
|
|
||||||
setLoading(false);
|
|
||||||
handleModalClose('registConfirm');
|
|
||||||
if(data.result === "SUCCESS") {
|
|
||||||
handleModalView('registComplete');
|
|
||||||
}else if(data.result === "ERROR_AUCTION_STATUS_IMPOSSIBLE"){
|
|
||||||
setAlertMsg(t('LAND_AUCTION_ERROR_MODIFY_STATUS'));
|
|
||||||
}else{
|
|
||||||
setAlertMsg(t('UPDATE_FAIL'));
|
|
||||||
}
|
|
||||||
}).catch(reason => {
|
|
||||||
setAlertMsg(t('API_FAIL'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
await LandAuctionSingleRegist(token, resultData).then(data => {
|
|
||||||
setLoading(false);
|
|
||||||
handleModalClose('registConfirm');
|
|
||||||
if(data.result === "SUCCESS") {
|
|
||||||
handleModalView('registComplete');
|
|
||||||
}else if(data.result === "ERROR_LAND_AUCTION_IMPOSSIBLE"){
|
|
||||||
setAlertMsg(t('LAND_AUCTION_ERROR_PROGRESS'));
|
|
||||||
}else if(data.result === "ERROR_AUCTION_LAND_OWNER"){
|
|
||||||
setAlertMsg(t('LAND_AUCTION_ERROR_OWNER'));
|
|
||||||
}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.start_price > 0
|
|
||||||
&& resultData.auction_start_dt !== ''
|
|
||||||
&& resultData.auction_end_dt !== ''
|
|
||||||
&& resultData.resv_start_dt !== ''
|
|
||||||
&& resultData.resv_end_dt !== ''
|
|
||||||
&& resultData.land_id !== ''
|
|
||||||
// && resultData.message_list?.every(data => data.content !== '')
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const isView = (label) => {
|
|
||||||
switch (label) {
|
|
||||||
case "recv":
|
|
||||||
return modalType === TYPE_REGISTRY || (modalType === TYPE_MODIFY && content?.status === landAuctionStatusType.wait);
|
|
||||||
case "auction":
|
|
||||||
case "price":
|
|
||||||
case "message":
|
|
||||||
return modalType === TYPE_REGISTRY || (modalType === TYPE_MODIFY &&(content?.status === landAuctionStatusType.resv_start || content?.status === landAuctionStatusType.wait));
|
|
||||||
case "modify":
|
|
||||||
return modalType === TYPE_MODIFY && (content?.status === landAuctionStatusType.resv_start || content?.status === landAuctionStatusType.wait);
|
|
||||||
case "registry":
|
|
||||||
return modalType === TYPE_REGISTRY
|
|
||||||
default:
|
|
||||||
return modalType === TYPE_MODIFY && (content?.status === landAuctionStatusType.stl_end
|
|
||||||
|| content?.status === landAuctionStatusType.auction_start
|
|
||||||
|| content?.status === landAuctionStatusType.auction_end
|
|
||||||
|| content?.status === landAuctionStatusType.fail
|
|
||||||
|| content?.status === landAuctionStatusType.cancel
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Modal min="760px" $view={detailView}>
|
|
||||||
<Title $align="center">{isView('registry') ? "랜드 경매 등록" : isView('modify') ? "랜드 경매 수정" : "랜드 경매 상세"}</Title>
|
|
||||||
<MessageWrapper>
|
|
||||||
<FormRowGroup>
|
|
||||||
<FormLabel>랜드선택</FormLabel>
|
|
||||||
<SelectInput value={resultData.land_id} onChange={e => handleLand(e)} disabled={!isView('registry')} width="400px">
|
|
||||||
{landData && landData.map((data, index) => (
|
|
||||||
<option key={index} value={data.id}>
|
|
||||||
{data.name}({data.id})
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</FormRowGroup>
|
|
||||||
<FormRowGroup>
|
|
||||||
<FormLabel>랜드 이름</FormLabel>
|
|
||||||
<FormInput
|
|
||||||
type="text"
|
|
||||||
disabled={true}
|
|
||||||
width='400px'
|
|
||||||
value={resultData?.land_name}
|
|
||||||
/>
|
|
||||||
</FormRowGroup>
|
|
||||||
<FormRowGroup>
|
|
||||||
<FormLabel>랜드 크기</FormLabel>
|
|
||||||
<FormInput
|
|
||||||
type="text"
|
|
||||||
disabled={true}
|
|
||||||
width='200px'
|
|
||||||
value={resultData?.land_size}
|
|
||||||
/>
|
|
||||||
<FormLabel>인스턴스 수</FormLabel>
|
|
||||||
<FormInput
|
|
||||||
type="text"
|
|
||||||
disabled={true}
|
|
||||||
width='200px'
|
|
||||||
value={resultData?.land_socket}
|
|
||||||
/>
|
|
||||||
</FormRowGroup>
|
|
||||||
|
|
||||||
<FormRowGroup>
|
|
||||||
<FormLabel>입찰 재화</FormLabel>
|
|
||||||
<SelectInput value={resultData.currency_type} width='200px' disabled={true} >
|
|
||||||
{CurrencyType.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
<FormLabel>입찰시작가</FormLabel>
|
|
||||||
<FormInput
|
|
||||||
type="number"
|
|
||||||
name="price"
|
|
||||||
value={resultData.start_price}
|
|
||||||
step={"0.01"}
|
|
||||||
min={0}
|
|
||||||
width='200px'
|
|
||||||
disabled={!isView('price')}
|
|
||||||
onChange={e => handleCount(e)}
|
|
||||||
/>
|
|
||||||
</FormRowGroup>
|
|
||||||
<DateTimeRangePicker
|
|
||||||
label="예약기간"
|
|
||||||
startDate={resultData.resv_start_dt}
|
|
||||||
endDate={resultData.resv_end_dt}
|
|
||||||
onStartDateChange={handleReservationChange.start}
|
|
||||||
onEndDateChange={handleReservationChange.end}
|
|
||||||
pastDate={new Date()}
|
|
||||||
disabled={!isView('recv')}
|
|
||||||
startLabel="시작 일자"
|
|
||||||
endLabel="종료 일자"
|
|
||||||
reset={resetDateTime}
|
|
||||||
setAlert={setAlertMsg}
|
|
||||||
/>
|
|
||||||
<DateTimeRangePicker
|
|
||||||
label="경매기간"
|
|
||||||
startDate={resultData.auction_start_dt}
|
|
||||||
endDate={resultData.auction_end_dt}
|
|
||||||
onStartDateChange={handleAuctionChange.start}
|
|
||||||
onEndDateChange={handleAuctionChange.end}
|
|
||||||
pastDate={new Date()}
|
|
||||||
disabled={!isView('auction')}
|
|
||||||
startLabel="시작 일자"
|
|
||||||
endLabel="종료 일자"
|
|
||||||
reset={resetDateTime}
|
|
||||||
setAlert={setAlertMsg}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/*<NoticeInputRow2>*/}
|
|
||||||
{/* <InputLabel>*/}
|
|
||||||
{/* 메세지 작성[경매 시작 5분전 공지 - 미구현]*/}
|
|
||||||
{/* </InputLabel>*/}
|
|
||||||
{/* <NoticeInputItem2>*/}
|
|
||||||
{/* <InputLabel>언어</InputLabel>*/}
|
|
||||||
{/* <SelectInput onChange={e => handleLanguage(e) } value={message_lang}>*/}
|
|
||||||
{/* {languageType.map((data, index) => (*/}
|
|
||||||
{/* <option key={index} value={data.value}>*/}
|
|
||||||
{/* {data.name}*/}
|
|
||||||
{/* </option>*/}
|
|
||||||
{/* ))}*/}
|
|
||||||
{/* </SelectInput>*/}
|
|
||||||
{/* </NoticeInputItem2>*/}
|
|
||||||
{/*</NoticeInputRow2>*/}
|
|
||||||
{/*<BoxWrapper>*/}
|
|
||||||
{/* {resultData.message_list.map(content => {*/}
|
|
||||||
{/* return (*/}
|
|
||||||
{/* <Fragment key={content.language}>*/}
|
|
||||||
{/* {message_lang === content.language && (*/}
|
|
||||||
{/* <FormTextAreaWrapper>*/}
|
|
||||||
{/* <FormTextArea*/}
|
|
||||||
{/* name="content"*/}
|
|
||||||
{/* id={content.language}*/}
|
|
||||||
{/* value={content.content}*/}
|
|
||||||
{/* onChange={e => handleInputData(e)}*/}
|
|
||||||
{/* maxLength={250}*/}
|
|
||||||
{/* disabled={!isView('message')}*/}
|
|
||||||
{/* />*/}
|
|
||||||
{/* </FormTextAreaWrapper>*/}
|
|
||||||
{/* )}*/}
|
|
||||||
{/* </Fragment>*/}
|
|
||||||
{/* );*/}
|
|
||||||
{/* })}*/}
|
|
||||||
{/*</BoxWrapper>*/}
|
|
||||||
{!isView() && isNullValue && <SearchBarAlert $marginTop="25px" $align="right">{t('REQUIRED_VALUE_CHECK')}</SearchBarAlert>}
|
|
||||||
</MessageWrapper>
|
|
||||||
|
|
||||||
<BtnWrapper $gap="10px" $marginTop="10px">
|
|
||||||
<FormStatusBar>
|
|
||||||
<FormStatusLabel>
|
|
||||||
현재상태: {landAuctionStatus.find(data => data.value === content?.status)?.name || "등록"}
|
|
||||||
</FormStatusLabel>
|
|
||||||
<FormStatusWarning>
|
|
||||||
{isView('registry') ? '' : t('LAND_AUCTION_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('LAND_UPDATE_CONFIRM') : t('LAND_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 = {
|
|
||||||
land_id: '',
|
|
||||||
land_name: '',
|
|
||||||
land_size: '',
|
|
||||||
land_socket: '',
|
|
||||||
currency_type: 'Calium',
|
|
||||||
start_price: 0,
|
|
||||||
resv_start_dt: '',
|
|
||||||
resv_end_dt: '',
|
|
||||||
auction_start_dt: '',
|
|
||||||
auction_end_dt: '',
|
|
||||||
message_list: [
|
|
||||||
{ language: 'KO', content: '' },
|
|
||||||
{ language: 'EN', content: '' },
|
|
||||||
{ language: 'JA', content: '' },
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
export const initLandData = {
|
|
||||||
land_id: 0,
|
|
||||||
name: '',
|
|
||||||
size: '',
|
|
||||||
socket: '',
|
|
||||||
desc: '',
|
|
||||||
open: false,
|
|
||||||
owner: ''
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LandAuctionModal;
|
|
||||||
|
|
||||||
@@ -1,205 +0,0 @@
|
|||||||
import { TextInput, BtnWrapper, InputLabel, SelectInput, InputGroup } from '../../styles/Components';
|
|
||||||
import Button from '../common/button/Button';
|
|
||||||
import { SearchBarLayout, SearchPeriod } from '../common/SearchBar';
|
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
|
||||||
import { LandAuctionView } from '../../apis';
|
|
||||||
import { landAuctionStatus, landSearchType, landSize, userSearchType } from '../../assets/data';
|
|
||||||
|
|
||||||
export const useLandAuctionSearch = (token, initialPageSize) => {
|
|
||||||
const [searchParams, setSearchParams] = useState({
|
|
||||||
landType: 'ID',
|
|
||||||
landData: '',
|
|
||||||
userType: 'GUID',
|
|
||||||
userData: '',
|
|
||||||
landSize: 'ALL',
|
|
||||||
status: 'ALL',
|
|
||||||
auctionStartDate: '',
|
|
||||||
auctionEndDate: '',
|
|
||||||
orderBy: 'DESC',
|
|
||||||
pageSize: initialPageSize,
|
|
||||||
currentPage: 1
|
|
||||||
});
|
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [data, setData] = useState(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetchData(searchParams); // 컴포넌트 마운트 시 초기 데이터 로드
|
|
||||||
}, [token]);
|
|
||||||
|
|
||||||
const fetchData = useCallback(async (params) => {
|
|
||||||
try {
|
|
||||||
setLoading(true);
|
|
||||||
const result = await LandAuctionView(
|
|
||||||
token,
|
|
||||||
params.landType,
|
|
||||||
params.landData,
|
|
||||||
params.userType,
|
|
||||||
params.userData,
|
|
||||||
params.landSize,
|
|
||||||
params.status,
|
|
||||||
params.auctionStartDate && new Date(params.auctionStartDate).toISOString(),
|
|
||||||
params.auctionEndDate && new Date(params.auctionEndDate).toISOString(),
|
|
||||||
params.orderBy,
|
|
||||||
params.pageSize,
|
|
||||||
params.currentPage
|
|
||||||
);
|
|
||||||
setData(result);
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching auction data:', error);
|
|
||||||
throw error;
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
}, [token]);
|
|
||||||
|
|
||||||
const updateSearchParams = useCallback((newParams) => {
|
|
||||||
setSearchParams(prev => ({
|
|
||||||
...prev,
|
|
||||||
...newParams
|
|
||||||
}));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleSearch = useCallback(async (newParams = {}) => {
|
|
||||||
const updatedParams = {
|
|
||||||
...searchParams,
|
|
||||||
...newParams,
|
|
||||||
currentPage: newParams.currentPage || 1 // Reset to first page on new search
|
|
||||||
};
|
|
||||||
updateSearchParams(updatedParams);
|
|
||||||
return await fetchData(updatedParams);
|
|
||||||
}, [searchParams, fetchData]);
|
|
||||||
|
|
||||||
const handleReset = useCallback(async () => {
|
|
||||||
const resetParams = {
|
|
||||||
landType: 'ID',
|
|
||||||
landData: '',
|
|
||||||
userType: 'GUID',
|
|
||||||
userData: '',
|
|
||||||
landSize: 'ALL',
|
|
||||||
status: 'ALL',
|
|
||||||
auctionStartDate: '',
|
|
||||||
auctionEndDate: '',
|
|
||||||
orderBy: 'DESC',
|
|
||||||
pageSize: initialPageSize,
|
|
||||||
currentPage: 1
|
|
||||||
};
|
|
||||||
setSearchParams(resetParams);
|
|
||||||
return await fetchData(resetParams);
|
|
||||||
}, [initialPageSize, fetchData]);
|
|
||||||
|
|
||||||
const handlePageChange = useCallback(async (newPage) => {
|
|
||||||
return await handleSearch({ currentPage: newPage });
|
|
||||||
}, [handleSearch]);
|
|
||||||
|
|
||||||
const handlePageSizeChange = useCallback(async (newSize) => {
|
|
||||||
return await handleSearch({ pageSize: newSize, currentPage: 1 });
|
|
||||||
}, [handleSearch]);
|
|
||||||
|
|
||||||
const handleOrderByChange = useCallback(async (newOrder) => {
|
|
||||||
return await handleSearch({ orderBy: newOrder });
|
|
||||||
}, [handleSearch]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
searchParams,
|
|
||||||
loading,
|
|
||||||
data,
|
|
||||||
handleSearch,
|
|
||||||
handleReset,
|
|
||||||
handlePageChange,
|
|
||||||
handlePageSizeChange,
|
|
||||||
handleOrderByChange,
|
|
||||||
updateSearchParams
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const LandAuctionSearchBar = ({ searchParams, onSearch, onReset }) => {
|
|
||||||
const handleSubmit = event => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
onSearch(searchParams);
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchList = [
|
|
||||||
<>
|
|
||||||
<InputGroup>
|
|
||||||
<SelectInput value={searchParams.landType} onChange={e => onSearch({landType: e.target.value })}>
|
|
||||||
{landSearchType.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
<TextInput
|
|
||||||
type="text"
|
|
||||||
placeholder={searchParams.landType === 'ID' ? '랜드 ID 입력' : '랜드명 입력'}
|
|
||||||
value={searchParams.landData}
|
|
||||||
width="300px"
|
|
||||||
onChange={e => onSearch({ landData: e.target.value })}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>낙찰자</InputLabel>
|
|
||||||
<InputGroup>
|
|
||||||
<SelectInput value={searchParams.userType} onChange={e => onSearch({userType: e.target.value })}>
|
|
||||||
{userSearchType.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
<TextInput
|
|
||||||
type="text"
|
|
||||||
placeholder={searchParams.userType === 'GUID' ? 'GUID 입력' : '닉네임 입력'}
|
|
||||||
value={searchParams.userData}
|
|
||||||
width="300px"
|
|
||||||
onChange={e => onSearch({ userData: e.target.value })}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
</>
|
|
||||||
];
|
|
||||||
|
|
||||||
const optionList = [
|
|
||||||
<>
|
|
||||||
<InputLabel>랜드크기</InputLabel>
|
|
||||||
<SelectInput value={searchParams.landSize} onChange={e => onSearch({ landSize: e.target.value }, false)} >
|
|
||||||
{landSize.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>경매상태</InputLabel>
|
|
||||||
<SelectInput value={searchParams.status} onChange={e => onSearch({ status: e.target.value }, false)}>
|
|
||||||
{landAuctionStatus.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>경매 일자</InputLabel>
|
|
||||||
<SearchPeriod
|
|
||||||
startDate={searchParams.auctionStartDate}
|
|
||||||
handleStartDate={date => onSearch({ auctionStartDate: date }, false)}
|
|
||||||
endDate={searchParams.auctionEndDate}
|
|
||||||
handleEndDate={date => onSearch({ auctionEndDate: date }, false)}
|
|
||||||
/>
|
|
||||||
</>,
|
|
||||||
<></>,<></>,
|
|
||||||
<>
|
|
||||||
<BtnWrapper $gap="8px">
|
|
||||||
<Button theme="reset" handleClick={onReset} type="button" />
|
|
||||||
<Button theme="search" text="검색" handleClick={handleSubmit} type="submit" />
|
|
||||||
</BtnWrapper>
|
|
||||||
</>,
|
|
||||||
];
|
|
||||||
return <SearchBarLayout firstColumnData={searchList} secondColumnData={optionList} direction={'column'} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default LandAuctionSearchBar;
|
|
||||||
@@ -1,979 +0,0 @@
|
|||||||
import { styled } from 'styled-components';
|
|
||||||
import RadioInput from '../../components/common/input/Radio';
|
|
||||||
import { useState, useEffect, Fragment } from 'react';
|
|
||||||
import CheckBox from '../../components/common/input/CheckBox';
|
|
||||||
|
|
||||||
import { Title, SelectInput, BtnWrapper, TextInput, Label, InputLabel, DatePickerWrapper, Textarea, ModalText, ButtonClose, SearchBarAlert } from '../../styles/Components';
|
|
||||||
import Button from '../../components/common/button/Button';
|
|
||||||
import Modal from '../../components/common/modal/Modal';
|
|
||||||
|
|
||||||
import IconDelete from '../../assets/img/icon/icon-delete.png';
|
|
||||||
import CloseIcon from '../../assets/img/icon/icon-close.png';
|
|
||||||
import DatePickerComponent from '../common/Date/DatePickerComponent';
|
|
||||||
import MailRegistUploadBtn from '../../components/ServiceManage/MailRegistUploadBtn';
|
|
||||||
import { benItems, HourList, MinuteList, modalTypes, wellType } from '../../assets/data';
|
|
||||||
import { EventModify, MailModify } from '../../apis';
|
|
||||||
|
|
||||||
import { authList } from '../../store/authList';
|
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
import { convertKTC, convertKTCDate, timeDiffMinute } from '../../utils';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import DynamicModal from '../common/modal/DynamicModal';
|
|
||||||
|
|
||||||
const MailDetailModal = ({ detailView, handleDetailView, content }) => {
|
|
||||||
const userInfo = useRecoilValue(authList);
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const token = sessionStorage.getItem('token');
|
|
||||||
|
|
||||||
const id = content && content.id;
|
|
||||||
const onlyView = userInfo.auth_list && !userInfo.auth_list.some(auth => auth.id === 23);
|
|
||||||
const updateAuth = userInfo.auth_list && userInfo.auth_list.some(auth => auth.id === 23);
|
|
||||||
|
|
||||||
const [sendHour, setSendHour] = useState('00');
|
|
||||||
const [sendMin, setSendMin] = useState('00');
|
|
||||||
|
|
||||||
const [item, setItem] = useState('');
|
|
||||||
const [itemCount, setItemCount] = useState('');
|
|
||||||
const [resource, setResource] = useState('19010001');
|
|
||||||
const [resourceCount, setResourceCount] = useState('');
|
|
||||||
|
|
||||||
const [modifyModal, setModifyModal] = useState('hidden');
|
|
||||||
const [completeModal, setCompleteModal] = useState('hidden');
|
|
||||||
const [resultData, setResultData] = useState({});
|
|
||||||
|
|
||||||
const [modalState, setModalState] = useState({
|
|
||||||
updateConfirmModal: 'hidden',
|
|
||||||
updateCompleteModal: 'hidden',
|
|
||||||
});
|
|
||||||
|
|
||||||
const [isNullValue, setIsNullValue] = useState(false);
|
|
||||||
// 과거 판단
|
|
||||||
const [isPast, setIsPast] = useState(false);
|
|
||||||
const [isChanged, setIsChanged] = useState(false);
|
|
||||||
const [isItemNullValue, setIsItemNullValue] = useState(false);
|
|
||||||
|
|
||||||
const [excelFile, setExcelFile] = useState(content.target ? content.target : '');
|
|
||||||
const [excelName, setExcelName] = useState(null);
|
|
||||||
const [downloadData, setDownLoadData] = useState(null);
|
|
||||||
|
|
||||||
const [btnValidation, setBtnValidation] = useState(false);
|
|
||||||
const [updateMessage, setUpdateMessage] = useState('수정이 완료되었습니다.');
|
|
||||||
const [alertMessage, setAlertMessage] = useState('');
|
|
||||||
const [undefinedFile, setUndefinedFile] = useState(false);
|
|
||||||
const [disabledBtn, setDisabledBtn] = useState(false); // 예약 발송 확인용
|
|
||||||
const [alertMsg, setAlertMsg] = useState('');
|
|
||||||
|
|
||||||
const KOREAN_TIME = content && convertKTCDate(content.send_dt);
|
|
||||||
|
|
||||||
const initialData = {
|
|
||||||
send_hour: content && KOREAN_TIME.getHours() < 10 ? '0' + content && KOREAN_TIME.getHours() : content && KOREAN_TIME.getHours(),
|
|
||||||
send_min: content && KOREAN_TIME.getMinutes() < 10 ? '0' + content && KOREAN_TIME.getMinutes() : content && KOREAN_TIME.getMinutes(),
|
|
||||||
send_status: content && content.send_status,
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
document.querySelector('#fileinput').value = '';
|
|
||||||
|
|
||||||
setResultData({
|
|
||||||
is_reserve: content && content.is_reserve,
|
|
||||||
send_dt: content && KOREAN_TIME,
|
|
||||||
mail_type: content && content.mail_type,
|
|
||||||
receive_type: content && content.receive_type,
|
|
||||||
user_type: content && content.user_type,
|
|
||||||
mail_list: content && content.mail_list,
|
|
||||||
item_list: content && content.item_list,
|
|
||||||
guid: content && content.target,
|
|
||||||
});
|
|
||||||
|
|
||||||
content && content.mail_list.length === 1 && setBtnValidation(true);
|
|
||||||
content && content.is_reserve === false && setBtnValidation(true);
|
|
||||||
|
|
||||||
setItem('');
|
|
||||||
KOREAN_TIME < new Date ? setIsPast(true) : setIsPast(false);
|
|
||||||
setExcelFile(content && content.target);
|
|
||||||
setDownLoadData(content && content.target);
|
|
||||||
setDisabledBtn(content && content.is_reserve && false);
|
|
||||||
|
|
||||||
// 복수 or 단일일 때 content.target을 exel name 으로 지정
|
|
||||||
(content && content.receive_type === 'MULTIPLE') ?
|
|
||||||
setExcelName(content && content.target)
|
|
||||||
: setExcelName('')
|
|
||||||
|
|
||||||
}, [content]);
|
|
||||||
|
|
||||||
// console.log('downloadData', downloadData);
|
|
||||||
// console.log('isPast', isPast);
|
|
||||||
// console.log("guid", resultData.guid)
|
|
||||||
// console.log("메일 형식", content && content.receive_type," 엑셀네임", excelName)
|
|
||||||
|
|
||||||
// 아이템 수량 숫자 체크
|
|
||||||
const handleItemCount = e => {
|
|
||||||
if (e.target.value === '0' || e.target.value === '-0') {
|
|
||||||
setItemCount('1');
|
|
||||||
e.target.value = '1';
|
|
||||||
} else if (e.target.value < 0) {
|
|
||||||
let plusNum = Math.abs(e.target.value);
|
|
||||||
setItemCount(plusNum);
|
|
||||||
} else {
|
|
||||||
setItemCount(e.target.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 아이템 추가
|
|
||||||
const handleItemList = () => {
|
|
||||||
if(benItems.includes(item)){
|
|
||||||
setAlertMsg(t('MAIL_ITEM_ADD_BEN'))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
item.length === 0 || itemCount.length === 0 ? setIsItemNullValue(true) : setIsItemNullValue(false);
|
|
||||||
|
|
||||||
if (item.length === '' || itemCount.length === 0 || itemCount <= 0) {
|
|
||||||
setIsItemNullValue(true);
|
|
||||||
} else if (item.length !== 0) {
|
|
||||||
setIsItemNullValue(false);
|
|
||||||
setIsChanged(true);
|
|
||||||
|
|
||||||
const newItem = { item: item, item_cnt: itemCount };
|
|
||||||
resultData.item_list.push(newItem);
|
|
||||||
|
|
||||||
setItem('');
|
|
||||||
setItemCount('');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 아이템 삭제
|
|
||||||
const onItemRemove = id => {
|
|
||||||
let filterList = resultData.item_list && resultData.item_list.filter(item => item !== resultData.item_list[id]);
|
|
||||||
setIsChanged(true);
|
|
||||||
|
|
||||||
// console.log('filterList', filterList);
|
|
||||||
|
|
||||||
setResultData({ ...resultData, item_list: filterList });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 자원 수량 숫자 체크
|
|
||||||
const handleResourceCount = e => {
|
|
||||||
if (e.target.value === '0' || e.target.value === '-0') {
|
|
||||||
setResourceCount('1');
|
|
||||||
e.target.value = '1';
|
|
||||||
} else if (e.target.value < 0) {
|
|
||||||
let plusNum = Math.abs(e.target.value);
|
|
||||||
setResourceCount(plusNum);
|
|
||||||
} else {
|
|
||||||
setResourceCount(e.target.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 자원 추가
|
|
||||||
const handleResourceList = () => {
|
|
||||||
resourceCount.length === 0 ? setIsItemNullValue(true) : setIsItemNullValue(false);
|
|
||||||
|
|
||||||
if (resourceCount.length === 0 || resourceCount <= 0) {
|
|
||||||
setIsItemNullValue(true);
|
|
||||||
} else {
|
|
||||||
setIsItemNullValue(false);
|
|
||||||
const name = wellType.find(well => well.value === resource).name;
|
|
||||||
const newItem = { item: resource, item_cnt: resourceCount, item_name: name };
|
|
||||||
|
|
||||||
resultData.item_list.push(newItem);
|
|
||||||
|
|
||||||
setResourceCount('');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 입력창 삭제
|
|
||||||
const onLangDelete = language => {
|
|
||||||
let filterList = resultData.mail_list && resultData.mail_list.filter(el => el.language !== language);
|
|
||||||
|
|
||||||
if (filterList.length === 1) setBtnValidation(true);
|
|
||||||
|
|
||||||
setIsChanged(true);
|
|
||||||
setResultData({ ...resultData, mail_list: filterList });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 발송 날짜 세팅 로직
|
|
||||||
const handleSelectedDate = data => {
|
|
||||||
const sendDate = new Date(data);
|
|
||||||
|
|
||||||
const resultSendData = new Date(sendDate.getFullYear(), sendDate.getMonth(), sendDate.getDate(), sendHour, sendMin);
|
|
||||||
|
|
||||||
setIsChanged(true);
|
|
||||||
setResultData({ ...resultData, send_dt: resultSendData });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 발송 시간 세팅 로직
|
|
||||||
const handleSendTime = e => {
|
|
||||||
if (e.target.id === 'hour') setSendHour(e.target.value);
|
|
||||||
else if (e.target.id === 'min') setSendMin(e.target.value);
|
|
||||||
|
|
||||||
const sendDate = new Date(resultData.send_dt);
|
|
||||||
const result = new Date(sendDate.getFullYear(), sendDate.getMonth(), sendDate.getDate(), e.target.id === 'hour' ? e.target.value : sendHour, e.target.id === 'min' ? e.target.value : sendMin);
|
|
||||||
|
|
||||||
setIsChanged(true);
|
|
||||||
setResultData({ ...resultData, send_dt: result });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 우편 상세 정보 수정
|
|
||||||
const handleModifyModal = () => {
|
|
||||||
if (
|
|
||||||
resultData.mail_list.map(data => data.content === '' || data.title === '').includes(true) ||
|
|
||||||
(resultData.receive_type === 'MULTIPLE' ? excelFile === null : resultData.guid === '') ||
|
|
||||||
resultData.send_dt.length === 0 ||
|
|
||||||
resultData.mail_type === 'SELECT' ||
|
|
||||||
isChanged === false ||
|
|
||||||
alertMessage
|
|
||||||
) {
|
|
||||||
isChanged === true && setIsNullValue(true);
|
|
||||||
} else {
|
|
||||||
// 복수로 수정하거나 복수로 등록할 때 항상 excel name을 넘겨줘야합니다.
|
|
||||||
content && content.receive_type === 'MULTIPLE' ? setResultData({ ...resultData, file_name: excelName === null ? downloadData : excelName }) : setExcelName('');
|
|
||||||
|
|
||||||
// setExcelName(content && content.target)
|
|
||||||
|
|
||||||
setIsNullValue(false);
|
|
||||||
if (modifyModal === 'hidden') {
|
|
||||||
setModifyModal('view');
|
|
||||||
} else {
|
|
||||||
setModifyModal('hidden');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 상세 정보 단일 체크
|
|
||||||
const handleSingleBtn = () => {
|
|
||||||
if (content && content.is_reserve === true && !onlyView && !isPast) {
|
|
||||||
setResultData({ ...resultData, guid: '' });
|
|
||||||
delete resultData.file_name;
|
|
||||||
|
|
||||||
document.querySelector('#fileinput').value = '';
|
|
||||||
|
|
||||||
setExcelFile(null);
|
|
||||||
setIsChanged(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// 상세 정보 복수 체크
|
|
||||||
const handleMultiBtn = () => {
|
|
||||||
if (content && content.is_reserve === true) {
|
|
||||||
delete resultData.guid;
|
|
||||||
}
|
|
||||||
setIsChanged(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 완료 모달창
|
|
||||||
const handleCompleteModal = () => {
|
|
||||||
if (completeModal === 'hidden') {
|
|
||||||
setCompleteModal('view');
|
|
||||||
} else {
|
|
||||||
setCompleteModal('hidden');
|
|
||||||
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 메일 수정 버튼
|
|
||||||
const handleModifyMail = () => {
|
|
||||||
|
|
||||||
if(resultData.receive_type === 'MULTIPLE') {
|
|
||||||
delete resultData.guid
|
|
||||||
|
|
||||||
MailModify(token, id, resultData);
|
|
||||||
} else {
|
|
||||||
MailModify(token, id, resultData);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCompleteModal();
|
|
||||||
handleModifyModal();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 확인 버튼 후 다 초기화
|
|
||||||
const handleReset = () => {
|
|
||||||
setBtnValidation(false);
|
|
||||||
setIsNullValue(false);
|
|
||||||
setIsChanged(false);
|
|
||||||
setUndefinedFile(false);
|
|
||||||
setIsItemNullValue(false);
|
|
||||||
setAlertMessage('');
|
|
||||||
setExcelFile(null);
|
|
||||||
setExcelName(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 상세 페이지에서 파일 삭제
|
|
||||||
const handleDetailDelete = e => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (content && content.is_reserve === true) {
|
|
||||||
setDownLoadData(undefined);
|
|
||||||
setUndefinedFile(true);
|
|
||||||
setResultData({ ...resultData, guid: '' });
|
|
||||||
delete resultData.file_name;
|
|
||||||
|
|
||||||
document.querySelector('#fileinput').value = '';
|
|
||||||
|
|
||||||
setExcelFile(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsChanged(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleModalView = (type) => {
|
|
||||||
setModalState((prevState) => ({
|
|
||||||
...prevState,
|
|
||||||
[`${type}Modal`]: 'view',
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleModalClose = (type) => {
|
|
||||||
setModalState((prevState) => ({
|
|
||||||
...prevState,
|
|
||||||
[`${type}Modal`]: 'hidden',
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSubmit = async (type, param = null) => {
|
|
||||||
switch (type) {
|
|
||||||
case "submit":
|
|
||||||
// if (!conditionCheck()) return;
|
|
||||||
|
|
||||||
handleModalView('updateConfirm');
|
|
||||||
break;
|
|
||||||
case "updateConfirm":
|
|
||||||
const timeDiff = timeDiffMinute(resultData.start_dt, (new Date))
|
|
||||||
// 이벤트 시작 30분전이나 이미 SystemMail이 add된 상태에서는 수정할 수 없다.
|
|
||||||
if(content.add_flag || timeDiff <= 30){
|
|
||||||
setAlertMsg(t('EVENT_TIME_LIMIT_UPDATE'));
|
|
||||||
handleModalClose('updateConfirm');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EventModify(token, id, resultData);
|
|
||||||
handleModalClose('updateConfirm');
|
|
||||||
handleModalView('updateComplete');
|
|
||||||
break;
|
|
||||||
case "updateComplete":
|
|
||||||
handleModalClose('updateComplete');
|
|
||||||
window.location.reload();
|
|
||||||
break;
|
|
||||||
case "warning":
|
|
||||||
setAlertMsg('');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Modal min="960px" $view={detailView}>
|
|
||||||
<Title $align="center">우편 상세 정보</Title>
|
|
||||||
|
|
||||||
<RegistInfo>
|
|
||||||
<span>등록자 : {content && content.create_by}</span>
|
|
||||||
<span>등록일 : {content && convertKTC(content.create_dt, false)}</span>
|
|
||||||
{content && typeof content.update_by !== 'undefined' && (
|
|
||||||
<>
|
|
||||||
<span>수정자 : {content && content.update_by}</span>
|
|
||||||
<span>수정일 : {content && convertKTC(content.update_dt, false)}</span>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</RegistInfo>
|
|
||||||
<ModalWrapper>
|
|
||||||
<RegistGroup>
|
|
||||||
<InputRow>
|
|
||||||
<CheckBox
|
|
||||||
label="예약 발송"
|
|
||||||
id="reserve"
|
|
||||||
checked={resultData && resultData.is_reserve}
|
|
||||||
setData={e => {
|
|
||||||
setResultData({ ...resultData, is_reserve: e.target.checked });
|
|
||||||
setDisabledBtn(e.target.checked);
|
|
||||||
setIsChanged(true);
|
|
||||||
}}
|
|
||||||
disabled={(content && content.is_reserve === false) || onlyView}
|
|
||||||
/>
|
|
||||||
{content && content.is_reserve === false ? (
|
|
||||||
<></>
|
|
||||||
) : (
|
|
||||||
content &&
|
|
||||||
content.is_reserve === true &&
|
|
||||||
resultData.is_reserve === true && (
|
|
||||||
<InputItem>
|
|
||||||
<InputLabel>발송 시간</InputLabel>
|
|
||||||
<InputGroup>
|
|
||||||
<DatePickerWrapper>
|
|
||||||
<DatePickerComponent
|
|
||||||
readOnly={(content && content.is_reserve === false) || onlyView || isPast}
|
|
||||||
name={initialData.send_dt}
|
|
||||||
selectedDate={resultData ? resultData.send_dt : initialData.send_dt}
|
|
||||||
handleSelectedDate={data => handleSelectedDate(data)}
|
|
||||||
pastDate={new Date()}
|
|
||||||
/>
|
|
||||||
</DatePickerWrapper>
|
|
||||||
<SelectInput
|
|
||||||
onChange={e => handleSendTime(e)}
|
|
||||||
id="hour"
|
|
||||||
disabled={(content && content.is_reserve === false) || onlyView || isPast}
|
|
||||||
value={
|
|
||||||
resultData && String(new Date(resultData.send_dt).getHours()) < 10
|
|
||||||
? '0' + String(new Date(resultData.send_dt).getHours())
|
|
||||||
: resultData && String(new Date(resultData.send_dt).getHours())
|
|
||||||
}>
|
|
||||||
{HourList.map(hour => (
|
|
||||||
<option
|
|
||||||
value={hour}
|
|
||||||
key={hour}
|
|
||||||
// selected={
|
|
||||||
// resultData && String(new Date(resultData.send_dt).getHours()) < 10
|
|
||||||
// ? '0' + String(new Date(resultData.send_dt).getHours()) === hour
|
|
||||||
// : resultData && String(new Date(resultData.send_dt).getHours()) === hour
|
|
||||||
// ? 'selected'
|
|
||||||
// : ''
|
|
||||||
// }
|
|
||||||
>
|
|
||||||
{hour}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
<SelectInput
|
|
||||||
onChange={e => {
|
|
||||||
handleSendTime(e);
|
|
||||||
setIsChanged(true);
|
|
||||||
}}
|
|
||||||
id="min"
|
|
||||||
disabled={(content && content.is_reserve === false) || onlyView || isPast}
|
|
||||||
value={
|
|
||||||
resultData && String(new Date(resultData.send_dt).getMinutes()) < 10
|
|
||||||
? '0' + String(new Date(resultData.send_dt).getMinutes())
|
|
||||||
: resultData && String(new Date(resultData.send_dt).getMinutes())
|
|
||||||
}>
|
|
||||||
{MinuteList.map(min => (
|
|
||||||
<option
|
|
||||||
value={min}
|
|
||||||
key={min}
|
|
||||||
// selected={
|
|
||||||
// resultData && String(new Date(resultData.send_dt).getMinutes()) < 10
|
|
||||||
// ? '0' + String(new Date(resultData.send_dt).getMinutes()) === min
|
|
||||||
// : resultData && String(new Date(resultData.send_dt).getMinutes()) === min
|
|
||||||
// ? 'selected'
|
|
||||||
// : ''
|
|
||||||
// }
|
|
||||||
>
|
|
||||||
{min}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</InputGroup>
|
|
||||||
</InputItem>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
<InputItem>
|
|
||||||
<InputLabel>우편 타입</InputLabel>
|
|
||||||
<SelectInput
|
|
||||||
onChange={e => {
|
|
||||||
setResultData({ ...resultData, mail_type: e.target.value });
|
|
||||||
setIsChanged(true);
|
|
||||||
}}
|
|
||||||
value={content && resultData.mail_type}
|
|
||||||
disabled={(content && content.is_reserve === false) || onlyView || isPast}>
|
|
||||||
<option value="SELECT">타입 선택</option>
|
|
||||||
<option value="SYSTEM_GUID">시스템 안내</option>
|
|
||||||
<option value="INSPECTION_COMPENSATION">점검 보상</option>
|
|
||||||
<option value="RECOVER_COMPENSATION">복구 보상</option>
|
|
||||||
<option value="EVENT_COMPENSATION">이벤트 보상</option>
|
|
||||||
</SelectInput>
|
|
||||||
</InputItem>
|
|
||||||
<InputItem>
|
|
||||||
<InputLabel>발송상태</InputLabel>
|
|
||||||
<div>
|
|
||||||
{content && initialData.send_status === 'WAIT' && <MailState>대기</MailState>}
|
|
||||||
{content && initialData.send_status === 'FINISH' && <MailState result="success">완료</MailState>}
|
|
||||||
{content && initialData.send_status === 'FAIL' && <MailState result="fail">실패</MailState>}
|
|
||||||
</div>
|
|
||||||
</InputItem>
|
|
||||||
</InputRow>
|
|
||||||
<MailReceiver>
|
|
||||||
<InputItem>
|
|
||||||
<InputLabel>수신대상</InputLabel>
|
|
||||||
<InputItem>
|
|
||||||
<SelectInput onChange={e => setResultData({ ...resultData, user_type: e.target.value })} value={resultData.user_type} disabled={(content && content.is_reserve === false) || onlyView || isPast}>
|
|
||||||
<option value="GUID">GUID</option>
|
|
||||||
<option value="NICKNAME">아바타명</option>
|
|
||||||
</SelectInput>
|
|
||||||
</InputItem>
|
|
||||||
<div>
|
|
||||||
<InputGroup>
|
|
||||||
<RadioInput
|
|
||||||
label="단일"
|
|
||||||
id="SINGLE"
|
|
||||||
name="receiver"
|
|
||||||
value="SINGLE"
|
|
||||||
disabled={(content && content.is_reserve === false) || onlyView || isPast}
|
|
||||||
fontWeight="600"
|
|
||||||
checked={resultData.receive_type === 'SINGLE'}
|
|
||||||
handleChange={e => {
|
|
||||||
setResultData({ ...resultData, receive_type: e.target.id });
|
|
||||||
setIsChanged(true);
|
|
||||||
}}
|
|
||||||
handleClick={handleSingleBtn}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
placeholder={resultData.user_type === "GUID" ? "GUID 입력" : resultData.user_type === "NICKNAME" ? "아바타명 입력" : "이메일 입력"}
|
|
||||||
disabled={resultData.receive_type !== 'SINGLE' || (content && content.is_reserve === false) || onlyView || isPast}
|
|
||||||
// defaultValue={resultData.receive_type === 'SINGLE' && resultData.guid !== '' ? content.target : ''}
|
|
||||||
value={resultData.receive_type === 'SINGLE' && resultData.guid !== '' ? resultData.guid : ''}
|
|
||||||
onChange={e => {
|
|
||||||
let list = [...resultData.guid];
|
|
||||||
list = e.target.value;
|
|
||||||
setResultData({ ...resultData, guid: list });
|
|
||||||
setIsChanged(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
{content && resultData.receive_type === 'MULTIPLE' && typeof resultData.guid !== 'undefined' ? (
|
|
||||||
<InputGroup>
|
|
||||||
<RadioInput
|
|
||||||
label="복수"
|
|
||||||
id="MULTIPLE"
|
|
||||||
name="receiver"
|
|
||||||
value="MULTIPLE"
|
|
||||||
fontWeight="600"
|
|
||||||
checked={content && resultData.receive_type === 'MULTIPLE'}
|
|
||||||
disabled
|
|
||||||
/>
|
|
||||||
<MailRegistUploadBtn
|
|
||||||
disabled={resultData.receive_type !== 'MULTIPLE'}
|
|
||||||
downloadData={downloadData}
|
|
||||||
setResultData={setResultData}
|
|
||||||
resultData={resultData}
|
|
||||||
handleDetailDelete={handleDetailDelete}
|
|
||||||
setExcelFile={setExcelFile}
|
|
||||||
alertMessage={alertMessage}
|
|
||||||
setAlertMessage={setAlertMessage}
|
|
||||||
undefinedFile={undefinedFile}
|
|
||||||
disabledBtn={disabledBtn}
|
|
||||||
excelName={excelName}
|
|
||||||
setExcelName={setExcelName}
|
|
||||||
status={initialData.send_status}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
) : (
|
|
||||||
<InputGroup>
|
|
||||||
<RadioInput
|
|
||||||
label="복수"
|
|
||||||
id="MULTIPLE"
|
|
||||||
name="receiver"
|
|
||||||
value="MULTIPLE"
|
|
||||||
fontWeight="600"
|
|
||||||
disabled={(content && content.is_reserve === false) || onlyView || isPast}
|
|
||||||
handleChange={e => setResultData({ ...resultData, receive_type: e.target.id })}
|
|
||||||
handleClick={handleMultiBtn}
|
|
||||||
/>
|
|
||||||
<MailRegistUploadBtn
|
|
||||||
setUpdateMessage={setUpdateMessage}
|
|
||||||
disabled={resultData.receive_type !== 'MULTIPLE'}
|
|
||||||
setResultData={setResultData}
|
|
||||||
resultData={resultData}
|
|
||||||
excelFile={excelFile}
|
|
||||||
setExcelFile={setExcelFile}
|
|
||||||
alertMessage={alertMessage}
|
|
||||||
setAlertMessage={setAlertMessage}
|
|
||||||
undefinedFile={undefinedFile}
|
|
||||||
handleDetailDelete={handleDetailDelete}
|
|
||||||
disabledBtn={disabledBtn}
|
|
||||||
excelName={excelName}
|
|
||||||
setExcelName={setExcelName}
|
|
||||||
status={initialData.send_status}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</InputItem>
|
|
||||||
</MailReceiver>
|
|
||||||
</RegistGroup>
|
|
||||||
{resultData.mail_list &&
|
|
||||||
resultData.mail_list.map(data => {
|
|
||||||
return (
|
|
||||||
<Fragment key={data.language}>
|
|
||||||
<MailRegistBox>
|
|
||||||
<LangArea>
|
|
||||||
언어 : {data.language}
|
|
||||||
{btnValidation === false ? (
|
|
||||||
<BtnClose
|
|
||||||
onClick={e => {
|
|
||||||
e.preventDefault();
|
|
||||||
onLangDelete(data.language);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<BtnClose opacity="10%" />
|
|
||||||
)}
|
|
||||||
</LangArea>
|
|
||||||
<MailRegistTable>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th width="120">
|
|
||||||
<Label>제목</Label>
|
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
<InputItem>
|
|
||||||
<TextInput
|
|
||||||
placeholder="우편 제목 입력"
|
|
||||||
maxLength="30"
|
|
||||||
id={data.language}
|
|
||||||
value={data.title}
|
|
||||||
readOnly={(content && content.is_reserve === false) || onlyView || isPast}
|
|
||||||
onChange={e => {
|
|
||||||
let list = [...resultData.mail_list];
|
|
||||||
let findIndex = resultData.mail_list && resultData.mail_list.findIndex(item => item.language === e.target.id);
|
|
||||||
list[findIndex].title = e.target.value.trimStart();
|
|
||||||
|
|
||||||
setResultData({ ...resultData, mail_list: list });
|
|
||||||
setIsChanged(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</InputItem>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
<Label>내용</Label>
|
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
<Textarea
|
|
||||||
value={data.content}
|
|
||||||
readOnly={(content && content.is_reserve === false) || onlyView || isPast}
|
|
||||||
id={data.language}
|
|
||||||
onChange={e => {
|
|
||||||
if (e.target.value.length > 2000) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let list = [...resultData.mail_list];
|
|
||||||
let findIndex = resultData.mail_list && resultData.mail_list.findIndex(item => item.language === e.target.id);
|
|
||||||
list[findIndex].content = e.target.value.trimStart();
|
|
||||||
|
|
||||||
setResultData({ ...resultData, mail_list: list });
|
|
||||||
setIsChanged(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</MailRegistTable>
|
|
||||||
</MailRegistBox>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
<MailRegistBox>
|
|
||||||
<MailRegistTable>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th width="120">
|
|
||||||
<Label>아이템 첨부</Label>
|
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
<InputItem>
|
|
||||||
<TextInput
|
|
||||||
placeholder="Item Meta id 입력"
|
|
||||||
value={item}
|
|
||||||
onChange={e => {
|
|
||||||
let list = [];
|
|
||||||
list = e.target.value.trimStart();
|
|
||||||
setItem(list);
|
|
||||||
}}
|
|
||||||
disabled={(content && content.is_reserve === false) || onlyView || isPast}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
placeholder="수량"
|
|
||||||
value={itemCount}
|
|
||||||
type="number"
|
|
||||||
onChange={e => handleItemCount(e)}
|
|
||||||
width="90px"
|
|
||||||
disabled={(content && content.is_reserve === false) || onlyView || isPast}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
text="추가"
|
|
||||||
theme={itemCount.length === 0 || item.length === 0 ? 'disable' : 'search'}
|
|
||||||
handleClick={handleItemList}
|
|
||||||
errorMessage={(content && content.is_reserve === false) || onlyView || isPast}
|
|
||||||
/>
|
|
||||||
</InputItem>
|
|
||||||
{/* {isItemNullValue && <SearchBarAlert $marginTop="15px">필수값을 입력해주세요.</SearchBarAlert>}
|
|
||||||
<div>
|
|
||||||
{resultData.item_list && (
|
|
||||||
<ItemList>
|
|
||||||
{content &&
|
|
||||||
resultData.item_list.map((data, index) => {
|
|
||||||
return (
|
|
||||||
<Item key={index}>
|
|
||||||
<span>
|
|
||||||
{data.item}({data.item_cnt})
|
|
||||||
</span>
|
|
||||||
{(content && content.is_reserve === false) ||
|
|
||||||
(updateAuth && <BtnDelete onClick={() => onItemRemove(index)}></BtnDelete>) ||
|
|
||||||
isPast
|
|
||||||
}
|
|
||||||
</Item>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</ItemList>
|
|
||||||
)}
|
|
||||||
</div> */}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th width="120">
|
|
||||||
<Label>자원 첨부</Label>
|
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
<InputItem>
|
|
||||||
<SelectInput onChange={e => setResource(e.target.value)} value={resource} disabled={(content && content.is_reserve === false) || onlyView || isPast}>
|
|
||||||
{wellType.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
<TextInput placeholder="수량" type="number" value={resourceCount} disabled={(content && content.is_reserve === false) || onlyView || isPast} onChange={e => handleResourceCount(e)} width="200px" />
|
|
||||||
<Button text="추가" theme={resourceCount.length === 0 || resource.length === 0 ? 'disable' : 'search'} handleClick={handleResourceList} width="100px" height="35px" errorMessage={(content && content.is_reserve === false) || onlyView || isPast} />
|
|
||||||
</InputItem>
|
|
||||||
{isItemNullValue && <SearchBarAlert $marginTop="15px">필수값을 입력해주세요.</SearchBarAlert>}
|
|
||||||
|
|
||||||
<div>
|
|
||||||
{resultData.item_list && (
|
|
||||||
<ItemList>
|
|
||||||
{resultData.item_list.map((data, index) => {
|
|
||||||
return (
|
|
||||||
<Item key={index}>
|
|
||||||
<span>
|
|
||||||
{data.item_name}[{data.item}] ({data.item_cnt})
|
|
||||||
</span>
|
|
||||||
{(content && content.is_reserve === true) || onlyView || isPast && <BtnDelete onClick={() => onItemRemove(index)}></BtnDelete>}
|
|
||||||
</Item>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</ItemList>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</MailRegistTable>
|
|
||||||
</MailRegistBox>
|
|
||||||
</ModalWrapper>
|
|
||||||
<BtnWrapper $justify="flex-end" $gap="10px" $paddingTop="20px">
|
|
||||||
<Button
|
|
||||||
text="확인"
|
|
||||||
theme="line"
|
|
||||||
name="확인버튼"
|
|
||||||
handleClick={() => {
|
|
||||||
handleDetailView();
|
|
||||||
handleReset();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{(updateAuth && content && content.is_reserve === true) && !isPast && (
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
text="수정"
|
|
||||||
id="수정버튼"
|
|
||||||
theme={
|
|
||||||
(content && content.mail_list.map(data => data.content === '' || data.title === '').includes(true)) ||
|
|
||||||
(resultData.receive_type === 'MULTIPLE' ? excelFile === null : resultData.guid === '') ||
|
|
||||||
resultData.mail_type === 'SELECT' ||
|
|
||||||
isChanged === false ||
|
|
||||||
alertMessage.length > 1
|
|
||||||
? 'disable'
|
|
||||||
: 'primary'
|
|
||||||
}
|
|
||||||
handleClick={() => {
|
|
||||||
handleModifyModal();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</BtnWrapper>
|
|
||||||
</Modal>
|
|
||||||
{/* 확인 모달 */}
|
|
||||||
<Modal min="440px" $padding="40px" $bgcolor="transparent" $view={modifyModal}>
|
|
||||||
<BtnWrapper $justify="flex-end">
|
|
||||||
<ButtonClose onClick={handleModifyModal} />
|
|
||||||
</BtnWrapper>
|
|
||||||
<ModalText $align="center">
|
|
||||||
우편 정보 수정사항을 <br />
|
|
||||||
저장하시겠습니까?
|
|
||||||
</ModalText>
|
|
||||||
<BtnWrapper $gap="10px">
|
|
||||||
<Button text="취소" theme="line" size="large" width="100%" handleClick={handleModifyModal} />
|
|
||||||
<Button text="확인" theme="primary" type="submit" size="large" width="100%" handleClick={handleModifyMail} />
|
|
||||||
</BtnWrapper>
|
|
||||||
</Modal>
|
|
||||||
{/* 완료 모달 */}
|
|
||||||
<Modal min="440px" $padding="40px" $bgcolor="transparent" $view={completeModal}>
|
|
||||||
<BtnWrapper $justify="flex-end">
|
|
||||||
<ButtonClose onClick={handleCompleteModal} />
|
|
||||||
</BtnWrapper>
|
|
||||||
<ModalText $align="center">수정이 완료되었습니다. </ModalText>
|
|
||||||
<BtnWrapper $gap="10px">
|
|
||||||
<Button text="확인" theme="primary" type="submit" size="large" width="100%" handleClick={handleCompleteModal} />
|
|
||||||
</BtnWrapper>
|
|
||||||
</Modal>
|
|
||||||
{/* 경고 모달 */}
|
|
||||||
<DynamicModal
|
|
||||||
modalType={modalTypes.completed}
|
|
||||||
view={alertMsg ? 'view' : 'hidden'}
|
|
||||||
modalText={alertMsg}
|
|
||||||
handleSubmit={() => handleSubmit('warning')}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MailDetailModal;
|
|
||||||
|
|
||||||
const InputItem = styled.div`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 20px;
|
|
||||||
${TextInput},${SelectInput} {
|
|
||||||
height: 35px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
${TextInput} {
|
|
||||||
padding: 0 15px;
|
|
||||||
}
|
|
||||||
${SelectInput} {
|
|
||||||
width: max-content;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ModalWrapper = styled.div`
|
|
||||||
max-height: 70vh;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
overflow: auto;
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
width: 4px;
|
|
||||||
}
|
|
||||||
&::-webkit-scrollbar-thumb {
|
|
||||||
background: #666666;
|
|
||||||
}
|
|
||||||
&::-webkit-scrollbar-track {
|
|
||||||
background: #d9d9d9;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const RegistInfo = styled.div`
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 50px;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const BtnClose = styled.button`
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
background: url(${CloseIcon}) 50% 50% no-repeat;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
transform: translate(0, -50%);
|
|
||||||
right: 20px;
|
|
||||||
opacity: ${props => props.opacity};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const LangArea = styled.div`
|
|
||||||
background: #f9f9f9;
|
|
||||||
padding: 10px 20px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
position: relative;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const MailRegistBox = styled.div`
|
|
||||||
margin-bottom: 20px;
|
|
||||||
border-top: 1px solid #999;
|
|
||||||
border-bottom: 1px solid #999;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const MailRegistTable = styled.table`
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
padding: 15px 0;
|
|
||||||
}
|
|
||||||
td {
|
|
||||||
${TextInput} {
|
|
||||||
max-width: 600px;
|
|
||||||
}
|
|
||||||
${Textarea} {
|
|
||||||
width: 100%;
|
|
||||||
border: 1px solid #d9d9d9;
|
|
||||||
border-radius: 5px;
|
|
||||||
height: 150px;
|
|
||||||
padding: 15px;
|
|
||||||
&:focus {
|
|
||||||
border: 1px solid #2c2c2c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const RegistGroup = styled.div`
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
flex-flow: column;
|
|
||||||
gap: 20px;
|
|
||||||
padding: 20px;
|
|
||||||
border-top: 1px solid #000;
|
|
||||||
border-bottom: 1px solid #000;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const InputRow = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 20px 50px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const InputGroup = styled.div`
|
|
||||||
display: flex;
|
|
||||||
gap: 5px;
|
|
||||||
align-items: center;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const MailReceiver = styled.div`
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
${InputItem} {
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
${InputLabel} {
|
|
||||||
line-height: 35px;
|
|
||||||
}
|
|
||||||
${TextInput} {
|
|
||||||
margin-left: 20px;
|
|
||||||
width: 400px;
|
|
||||||
}
|
|
||||||
${InputGroup} {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const MailState = styled.span`
|
|
||||||
font-weight: 600;
|
|
||||||
color: ${props => (props.result === 'success' ? '#08994B' : props.result === 'fail' ? '#ff0000' : '#2c2c2c')};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ItemList = styled.ul`
|
|
||||||
display: flex;
|
|
||||||
gap: 20px;
|
|
||||||
padding: 10px 20px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Item = styled.li`
|
|
||||||
display: flex;
|
|
||||||
gap: 5px;
|
|
||||||
align-items: center;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const BtnDelete = styled.button`
|
|
||||||
width: 12px;
|
|
||||||
height: 12px;
|
|
||||||
background: url(${IconDelete}) 50% 50% no-repeat;
|
|
||||||
`;
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
import { TextInput, BtnWrapper, InputLabel, SelectInput } from '../../styles/Components';
|
|
||||||
import Button from '../common/button/Button';
|
|
||||||
import { SearchBarLayout, SearchPeriod } from '../common/SearchBar';
|
|
||||||
import { useState } from 'react';
|
|
||||||
import { mailReceiveType, mailSendStatus, mailSendType, mailType } from '../../assets/data';
|
|
||||||
|
|
||||||
const MailListSearchBar = ({ handleSearch, setResultData }) => {
|
|
||||||
const [searchData, setSearchData] = useState({
|
|
||||||
mailTitle: '',
|
|
||||||
content: '',
|
|
||||||
sendType: 'ALL',
|
|
||||||
sendStatus: 'ALL',
|
|
||||||
mailType: 'ALL',
|
|
||||||
receiveType: 'ALL',
|
|
||||||
sendDate: '',
|
|
||||||
endDate: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleSubmit = event => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
handleSearch(
|
|
||||||
searchData.mailTitle,
|
|
||||||
searchData.content,
|
|
||||||
searchData.sendType ? searchData.sendType : 'ALL',
|
|
||||||
searchData.sendStatus ? searchData.sendStatus : 'ALL',
|
|
||||||
searchData.mailType ? searchData.mailType : 'ALL',
|
|
||||||
searchData.receiveType ? searchData.receiveType : 'ALL',
|
|
||||||
searchData.sendDate ? searchData.sendDate : '',
|
|
||||||
searchData.endDate ? searchData.endDate : new Date(),
|
|
||||||
(searchData.sendDate && searchData.endDate === '') && setSearchData({ sendDate : searchData.sendDate ,endDate : new Date()}),
|
|
||||||
);
|
|
||||||
|
|
||||||
setResultData(searchData);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleReset = () => {
|
|
||||||
setSearchData({
|
|
||||||
mailTitle: '',
|
|
||||||
content: '',
|
|
||||||
sendType: 'ALL',
|
|
||||||
sendStatus: 'ALL',
|
|
||||||
mailType: 'ALL',
|
|
||||||
receiveType: 'ALL',
|
|
||||||
sendDate: '',
|
|
||||||
endDate: '',
|
|
||||||
order: 'DESC',
|
|
||||||
});
|
|
||||||
|
|
||||||
handleSearch('', '', 'ALL', 'ALL', 'ALL', 'ALL', '', '');
|
|
||||||
setResultData('', '', 'ALL', 'ALL', 'ALL', 'ALL', '', '');
|
|
||||||
|
|
||||||
window.location.reload();
|
|
||||||
};
|
|
||||||
|
|
||||||
// console.log("searchData.endDate", searchData.endDate)
|
|
||||||
|
|
||||||
const searchList = [
|
|
||||||
<>
|
|
||||||
<InputLabel>우편 제목</InputLabel>
|
|
||||||
<TextInput
|
|
||||||
type="text"
|
|
||||||
placeholder="우편 제목"
|
|
||||||
value={searchData.mailTitle}
|
|
||||||
onChange={e => setSearchData({ ...searchData, mailTitle: e.target.value })}
|
|
||||||
/>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>조회 일자</InputLabel>
|
|
||||||
<SearchPeriod
|
|
||||||
startDate={searchData.sendDate}
|
|
||||||
handleStartDate={data => {
|
|
||||||
setSearchData({ ...searchData, sendDate: data });
|
|
||||||
}}
|
|
||||||
endDate={searchData.endDate}
|
|
||||||
handleEndDate={data => setSearchData({ ...searchData, endDate: data })}
|
|
||||||
maxDate={new Date()}
|
|
||||||
/>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>우편 내용</InputLabel>
|
|
||||||
<TextInput
|
|
||||||
type="text"
|
|
||||||
placeholder="우편 내용(공백으로 구분)"
|
|
||||||
value={searchData.content}
|
|
||||||
onChange={e => setSearchData({ ...searchData, content: e.target.value })}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
];
|
|
||||||
|
|
||||||
const optionList = [
|
|
||||||
<>
|
|
||||||
<InputLabel>발송 방식</InputLabel>
|
|
||||||
<SelectInput value={searchData.sendType} onChange={e => setSearchData({ ...searchData, sendType: e.target.value })}>
|
|
||||||
{mailSendType.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>발송 상태</InputLabel>
|
|
||||||
<SelectInput value={searchData.sendStatus} onChange={e => setSearchData({ ...searchData, sendStatus: e.target.value })}>
|
|
||||||
{mailSendStatus.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>우편 타입</InputLabel>
|
|
||||||
<SelectInput value={searchData.mailType} onChange={e => setSearchData({ ...searchData, mailType: e.target.value })}>
|
|
||||||
{mailType.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>수신 대상</InputLabel>
|
|
||||||
<SelectInput value={searchData.receiveType} onChange={e => setSearchData({ ...searchData, receiveType: e.target.value })}>
|
|
||||||
{mailReceiveType.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<BtnWrapper $gap="8px">
|
|
||||||
<Button theme="reset" handleClick={handleReset} type="button" />
|
|
||||||
<Button theme="search" text="검색" handleClick={handleSubmit} type="submit" />
|
|
||||||
</BtnWrapper>
|
|
||||||
</>,
|
|
||||||
];
|
|
||||||
return <SearchBarLayout firstColumnData={searchList} secondColumnData={optionList} direction={'column'} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MailListSearchBar;
|
|
||||||
@@ -1,349 +0,0 @@
|
|||||||
import { useState, useEffect } from 'react';
|
|
||||||
import { styled } from 'styled-components';
|
|
||||||
import { Title, BtnWrapper, TextInput, Label, Textarea, InputItem, ModalText, SearchBarAlert } from '../../styles/Components';
|
|
||||||
|
|
||||||
import { RepostReplyMessage } from '../../apis/Report';
|
|
||||||
|
|
||||||
import Modal from '../common/modal/Modal';
|
|
||||||
import Button from '../common/button/Button';
|
|
||||||
import CloseIcon from '../../assets/img/icon/icon-close.png';
|
|
||||||
|
|
||||||
const ReportListAnswerModal = ({ answerView, setAnswerView, detailData, replyData, pkId, skId }) => {
|
|
||||||
const token = sessionStorage.getItem('token');
|
|
||||||
const [replied, setReplied] = useState(false);
|
|
||||||
|
|
||||||
// 버튼 validation -> true 일 때 disable 처리
|
|
||||||
const [isNullValue, setIsNullValue] = useState(false);
|
|
||||||
|
|
||||||
// 발송 API 전달용 resultData 세팅
|
|
||||||
const [resultData, setResultData] = useState({
|
|
||||||
pk: '',
|
|
||||||
sk: '',
|
|
||||||
title: '',
|
|
||||||
detail: '',
|
|
||||||
reporter_nickname: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
// 모달 , 모달 메세지용 state
|
|
||||||
const [modalStep, setModalStep] = useState(false);
|
|
||||||
const [modalText, setModalText] = useState('');
|
|
||||||
const [confirmModal, setConfirmModal] = useState('hidden');
|
|
||||||
const [completeModal, setCompleteModal] = useState('hidden');
|
|
||||||
|
|
||||||
// 답변 조회 DATA 세팅용 resultData
|
|
||||||
useEffect(() => {
|
|
||||||
// 답변 조회 api에 호출할 pk, sk 세팅용
|
|
||||||
const pk = encodeURI(pkId);
|
|
||||||
const sk = encodeURI(skId);
|
|
||||||
|
|
||||||
setResultData({
|
|
||||||
pk: pkId && pk,
|
|
||||||
sk: skId && sk,
|
|
||||||
title: replyData ? replyData.title : '',
|
|
||||||
detail: replyData ? replyData.detail : '',
|
|
||||||
reporter_nickname: detailData && detailData.reporter_nickname,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 답변 유무 확인용
|
|
||||||
replyData ? setReplied(true) : setReplied(false);
|
|
||||||
}, [detailData, replyData]);
|
|
||||||
// console.log('신고답변작성 : ', resultData);
|
|
||||||
|
|
||||||
// Button Validation용 if 문
|
|
||||||
const btnVali = resultData.title && resultData.title.length > 0 && resultData.detail && resultData.detail.length > 0;
|
|
||||||
|
|
||||||
const titleLeng = resultData.title && resultData.title.length;
|
|
||||||
const detailLeng = resultData.detail && resultData.detail.length;
|
|
||||||
|
|
||||||
// Button Validation (2) - 에러 메세지
|
|
||||||
const handleNullVali = e => {
|
|
||||||
if (btnVali) {
|
|
||||||
setIsNullValue(false);
|
|
||||||
} else {
|
|
||||||
setIsNullValue(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 텍스트 변경 함수
|
|
||||||
const handleNoticeText = e => {
|
|
||||||
let btnName = e.target.name;
|
|
||||||
|
|
||||||
if (btnName === '취소버튼') {
|
|
||||||
setModalText('신고 답변을 취소하시겠습니까? \n 취소 시 작성된 모든 정보가 사라집니다.');
|
|
||||||
setModalStep(false);
|
|
||||||
} else {
|
|
||||||
setModalText('신고 답변 우편을 발송하시겠습니까?');
|
|
||||||
setModalStep(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 확인 모달
|
|
||||||
const handleConfirmModal = e => {
|
|
||||||
if (confirmModal === 'hidden') {
|
|
||||||
setConfirmModal('view');
|
|
||||||
} else {
|
|
||||||
setConfirmModal('hidden');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 완료 모달창
|
|
||||||
const handleCompleteModal = () => {
|
|
||||||
if (completeModal === 'hidden') {
|
|
||||||
setCompleteModal('view');
|
|
||||||
} else {
|
|
||||||
setCompleteModal('hidden');
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 확인 모달창에서 취소, 확인 버튼 처리
|
|
||||||
const handleModalStep = async e => {
|
|
||||||
e.preventDefault();
|
|
||||||
handleConfirmModal();
|
|
||||||
|
|
||||||
if (modalStep) {
|
|
||||||
await RepostReplyMessage(token, resultData);
|
|
||||||
setModalText('답변 발송이 완료되었습니다.');
|
|
||||||
handleCompleteModal();
|
|
||||||
} else {
|
|
||||||
setModalText('답변이 취소되었습니다.');
|
|
||||||
handleCompleteModal();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleReset();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 확인 버튼에서 불러올 초기화 처리
|
|
||||||
const handleReset = () => {
|
|
||||||
setAnswerView('hidden');
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Modal min="960px" $view={answerView}>
|
|
||||||
<Title $align="center">{replied ? '신고 답변' : '신고 답변 작성'}</Title>
|
|
||||||
<Subtitle>[답변 수신자 정보]</Subtitle>
|
|
||||||
<ReportDetailState>
|
|
||||||
<table>
|
|
||||||
<caption></caption>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th width="100px">수신자 GUID</th>
|
|
||||||
<td>
|
|
||||||
<TextInput value={detailData.reporter_guid || ''} readOnly />
|
|
||||||
</td>
|
|
||||||
<th width="100px">닉네임</th>
|
|
||||||
<td>
|
|
||||||
<TextInput value={detailData.reporter_nickname || ''} readOnly />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>제목</th>
|
|
||||||
<td colSpan="3">{detailData.title || ''}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th width="120">발송 경로</th>
|
|
||||||
<td>개인 우편함</td>
|
|
||||||
<th width="120">발송자</th>
|
|
||||||
<td>GM</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</ReportDetailState>
|
|
||||||
|
|
||||||
<Subtitle>[답변 내용]</Subtitle>
|
|
||||||
<AnswerRegistTable>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th width="120">
|
|
||||||
<Label>제목</Label>
|
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
<InputItem>
|
|
||||||
<TextInput
|
|
||||||
maxLength="30"
|
|
||||||
name="title"
|
|
||||||
value={resultData.title || ''}
|
|
||||||
onInput={e => {
|
|
||||||
setResultData({ ...resultData, title: e.target.value.trimStart() });
|
|
||||||
}}
|
|
||||||
readOnly={replyData}
|
|
||||||
/>
|
|
||||||
</InputItem>
|
|
||||||
{/* 답변 작성시에 글자 수 확인 */}
|
|
||||||
<ReportNotice $color={titleLeng > 29 ? 'red' : '#666'}>* 최대 등록 가능 글자수 ({Number(titleLeng)}/30자)</ReportNotice>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
<Label>내용</Label>
|
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
<Textarea
|
|
||||||
value={resultData.detail || ''}
|
|
||||||
name="detail"
|
|
||||||
maxLength="2000"
|
|
||||||
onInput={e => {
|
|
||||||
setResultData({ ...resultData, detail: e.target.value.trimStart() });
|
|
||||||
}}
|
|
||||||
readOnly={replyData}
|
|
||||||
/>
|
|
||||||
{/* 답변 작성시에 글자 수 확인 */}
|
|
||||||
<ReportNotice $color={detailLeng > 1999 ? 'red' : '#666'}>* 최대 등록 가능 글자수 ({Number(detailLeng)}/2000자)</ReportNotice>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</AnswerRegistTable>
|
|
||||||
{isNullValue && (
|
|
||||||
<SearchBarAlert $align="right" $padding="15px">
|
|
||||||
필수값을 입력해주세요.
|
|
||||||
</SearchBarAlert>
|
|
||||||
)}
|
|
||||||
<BtnWrapper $justify="flex-end" $gap="10px">
|
|
||||||
{replyData ? (
|
|
||||||
<Button text="확인" theme="line" handleClick={e => setAnswerView('hidden')} />
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
text="취소"
|
|
||||||
theme="line"
|
|
||||||
name="취소버튼"
|
|
||||||
handleClick={e => {
|
|
||||||
handleConfirmModal(e);
|
|
||||||
handleNoticeText(e);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
text="발송"
|
|
||||||
name="발송버튼"
|
|
||||||
// errorMessage={btnValidation}
|
|
||||||
theme={btnVali ? 'primary' : 'disable'}
|
|
||||||
handleClick={e => {
|
|
||||||
{
|
|
||||||
!btnVali ? handleNullVali(e) : handleConfirmModal(e);
|
|
||||||
handleNoticeText(e);
|
|
||||||
handleNullVali(e);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</BtnWrapper>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
{/* 확인 모달 */}
|
|
||||||
<Modal min="440px" $padding="40px" $bgcolor="transparent" $view={confirmModal}>
|
|
||||||
<BtnWrapper $justify="flex-end">
|
|
||||||
<ButtonClose onClick={handleConfirmModal} />
|
|
||||||
</BtnWrapper>
|
|
||||||
<ModalText $align="center">{modalText}</ModalText>
|
|
||||||
<BtnWrapper $gap="10px">
|
|
||||||
<Button text="취소" theme="line" size="large" width="100%" handleClick={handleConfirmModal} />
|
|
||||||
<Button
|
|
||||||
text="확인"
|
|
||||||
theme="primary"
|
|
||||||
type="submit"
|
|
||||||
size="large"
|
|
||||||
width="100%"
|
|
||||||
handleClick={e => {
|
|
||||||
handleModalStep(e);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</BtnWrapper>
|
|
||||||
</Modal>
|
|
||||||
{/* 완료 모달 */}
|
|
||||||
<Modal min="440px" $padding="40px" $bgcolor="transparent" $view={completeModal}>
|
|
||||||
<BtnWrapper $justify="flex-end">
|
|
||||||
<ButtonClose onClick={handleCompleteModal} />
|
|
||||||
</BtnWrapper>
|
|
||||||
<ModalText $align="center">{modalText}</ModalText>
|
|
||||||
<BtnWrapper $gap="10px">
|
|
||||||
<Button text="확인" theme="primary" type="submit" size="large" width="100%" handleClick={handleCompleteModal} />
|
|
||||||
</BtnWrapper>
|
|
||||||
</Modal>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ReportListAnswerModal;
|
|
||||||
|
|
||||||
const ReportDetailState = styled.div`
|
|
||||||
border-top: 1px solid #000;
|
|
||||||
border-bottom: 1px solid #000;
|
|
||||||
padding: 15px 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
input {
|
|
||||||
height: 35px;
|
|
||||||
max-width: 330px;
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 5px 10px;
|
|
||||||
}
|
|
||||||
table {
|
|
||||||
tr {
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
padding: 5px;
|
|
||||||
height: 45px;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Subtitle = styled.div`
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 1.6;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const AnswerRegistTable = styled.table`
|
|
||||||
border-top: 1px solid #999;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
padding: 15px 0;
|
|
||||||
border-bottom: 1px solid #f6f6f6;
|
|
||||||
}
|
|
||||||
tr:last-child {
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
padding: 15px 0;
|
|
||||||
border-bottom: 1px solid #999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
th {
|
|
||||||
vertical-align: top;
|
|
||||||
line-height: 30px;
|
|
||||||
}
|
|
||||||
td {
|
|
||||||
${TextInput} {
|
|
||||||
max-width: 600px;
|
|
||||||
}
|
|
||||||
${Textarea} {
|
|
||||||
width: 100%;
|
|
||||||
border: 1px solid #d9d9d9;
|
|
||||||
border-radius: 5px;
|
|
||||||
height: 150px;
|
|
||||||
padding: 15px;
|
|
||||||
&:focus {
|
|
||||||
border: 1px solid #2c2c2c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ReportNotice = styled.span`
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 300;
|
|
||||||
color: ${props => props.$color || '#999'};
|
|
||||||
margin-top: 10px;
|
|
||||||
display: block;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ButtonClose = styled.button`
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
background: url(${CloseIcon}) 50% 50% no-repeat;
|
|
||||||
opacity: ${props => props.opacity};
|
|
||||||
`;
|
|
||||||
@@ -1,221 +0,0 @@
|
|||||||
import { styled } from 'styled-components';
|
|
||||||
import { Title, BtnWrapper, TextInput, Label, Textarea, InputItem } from '../../styles/Components';
|
|
||||||
|
|
||||||
import Modal from '../common/modal/Modal';
|
|
||||||
import Button from '../common/button/Button';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { convertKTC } from '../../utils';
|
|
||||||
|
|
||||||
const ReportListDetailModal = ({ detailView, handleDetailView, handleReply, detailData, replyData, replyAuth }) => {
|
|
||||||
const [dataList, setDataList] = useState([]);
|
|
||||||
|
|
||||||
// UTC + 9 처리 해줄 변수
|
|
||||||
const RESOLVE_TIME = detailData && new Date(detailData.resolution_time);
|
|
||||||
const REPORT_TIME = detailData && new Date(detailData.create_time);
|
|
||||||
|
|
||||||
// 신고 유형 데이터 매핑
|
|
||||||
const report_type = [
|
|
||||||
{ value: 'ALL', name: '전체' },
|
|
||||||
{ value: 'UNMANNERED_ACT', name: '비매너 행위' },
|
|
||||||
{ value: 'USE_UNHEALTHY_NAMES', name: '불건전 이름 사용' },
|
|
||||||
{ value: 'CASH_TRADING', name: '현금거래 행위' },
|
|
||||||
{ value: 'INTERFERENCE_GAME', name: '게임 진행 방해' },
|
|
||||||
{ value: 'INTERFERENCE_SERVICE', name: '운영서비스 방해' },
|
|
||||||
{ value: 'ACCOUNT_EXPLOITATION', name: '계정도용' },
|
|
||||||
{ value: 'BUG_ABUSING', name: '버그/어뷰징' },
|
|
||||||
{ value: 'USE_HACK', name: '불법프로그램 사용' },
|
|
||||||
{ value: 'LEAK_PERSONAL_INFO', name: '개인정보 유출' },
|
|
||||||
{ value: 'PRETENDING_GM', name: '운영자 사칭' },
|
|
||||||
];
|
|
||||||
|
|
||||||
// console.log(detailData);
|
|
||||||
useEffect(() => {
|
|
||||||
setDataList({
|
|
||||||
create_time: detailData && convertKTC(REPORT_TIME, false),
|
|
||||||
detail: detailData && detailData.detail,
|
|
||||||
manager_email: replyData && replyData.manager_email,
|
|
||||||
report_type: detailData && detailData.report_type,
|
|
||||||
reporter_guid: detailData && detailData.reporter_guid,
|
|
||||||
reporter_nickname: detailData && detailData.reporter_nickname,
|
|
||||||
resolution_time: detailData && detailData.resolution_time,
|
|
||||||
state: detailData && detailData.state,
|
|
||||||
target_guid: detailData && detailData.target_guid,
|
|
||||||
target_nickname: detailData && detailData.target_nickname,
|
|
||||||
title: detailData && detailData.title,
|
|
||||||
});
|
|
||||||
}, [detailData]);
|
|
||||||
|
|
||||||
// console.log('모달창에서 리포트 상세 정보 : ', dataList);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Modal min="960px" $view={detailView}>
|
|
||||||
<Title $align="center">신고내역 상세 정보</Title>
|
|
||||||
{/* RegistInfo는 답변 완료시에만 보여집니다 */}
|
|
||||||
{dataList && dataList.resolution_time && (
|
|
||||||
<RegistInfo>
|
|
||||||
<span>등록자(이메일주소) : {dataList && dataList.manager_email}</span>
|
|
||||||
<span>등록일 : {dataList && convertKTC(RESOLVE_TIME)}</span>
|
|
||||||
</RegistInfo>
|
|
||||||
)}
|
|
||||||
<Subtitle>[신고 대상 정보]</Subtitle>
|
|
||||||
<ReportDetailState>
|
|
||||||
<table>
|
|
||||||
<caption></caption>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th width="120">신고 일자</th>
|
|
||||||
<td>{dataList.create_time}</td>
|
|
||||||
<th width="120">신고 유형</th>
|
|
||||||
<td>{report_type.map(data => data.value === (dataList && dataList.report_type) && data.name)}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>처리상태</th>
|
|
||||||
<td colSpan="3">{dataList && dataList.state === 'RESOLVED' ? <ReportState results="solved">해결</ReportState> : <ReportState results="remain">미해결</ReportState>}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<th width="100px">신고자 GUID</th>
|
|
||||||
<td>
|
|
||||||
<TextInput value={(dataList && dataList.reporter_guid) || ''} readOnly />
|
|
||||||
</td>
|
|
||||||
<th width="100px">닉네임</th>
|
|
||||||
<td>
|
|
||||||
<TextInput value={(dataList && dataList.reporter_nickname) || ''} readOnly />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th width="100px">신고대상 GUID</th>
|
|
||||||
<td>
|
|
||||||
<TextInput value={(dataList && dataList.target_guid) || ''} readOnly />
|
|
||||||
</td>
|
|
||||||
<th width="100px">닉네임</th>
|
|
||||||
<td>
|
|
||||||
<TextInput value={(dataList && dataList.target_nickname) || ''} readOnly />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</ReportDetailState>
|
|
||||||
|
|
||||||
<Subtitle>[신고내용]</Subtitle>
|
|
||||||
<AnswerRegistTable>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th width="120">
|
|
||||||
<Label>제목</Label>
|
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
<InputItem>
|
|
||||||
<TextInput maxLength="30" value={(dataList && dataList.title) || ''} readOnly />
|
|
||||||
</InputItem>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
<Label>내용</Label>
|
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
<Textarea value={(dataList && dataList.detail) || ''} readOnly></Textarea>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</AnswerRegistTable>
|
|
||||||
<BtnWrapper $justify="flex-end" $gap="10px">
|
|
||||||
<Button text="확인" theme="line" handleClick={() => handleDetailView()} />
|
|
||||||
{
|
|
||||||
// 답변이 있을 때
|
|
||||||
dataList && dataList.resolution_time ? (
|
|
||||||
<Button text="답변보기" theme="line" handleClick={() => handleReply()} />
|
|
||||||
) : // 답변이 없고, 답변 권한이 있을 때
|
|
||||||
dataList && !dataList.resolution_time && replyAuth ? (
|
|
||||||
<Button text="답변하기" theme="primary" handleClick={() => handleReply()} />
|
|
||||||
) : (
|
|
||||||
// 답변이 없고, 답변 권한도 없을 때
|
|
||||||
<></>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</BtnWrapper>
|
|
||||||
</Modal>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ReportListDetailModal;
|
|
||||||
|
|
||||||
const ReportDetailState = styled.div`
|
|
||||||
border-top: 1px solid #000;
|
|
||||||
border-bottom: 1px solid #000;
|
|
||||||
padding: 15px 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
input {
|
|
||||||
height: 35px;
|
|
||||||
max-width: 330px;
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 5px 10px;
|
|
||||||
}
|
|
||||||
table {
|
|
||||||
tr {
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
padding: 5px;
|
|
||||||
height: 45px;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
const ReportState = styled.span`
|
|
||||||
font-weight: 600;
|
|
||||||
color: ${props => (props.results === 'solved' ? '#08994B' : props.results === 'remain' ? '#ff0000' : '#2c2c2c')};
|
|
||||||
`;
|
|
||||||
const RegistInfo = styled.div`
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 50px;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Subtitle = styled.div`
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 1.6;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const AnswerRegistTable = styled.table`
|
|
||||||
border-top: 1px solid #999;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
padding: 15px 0;
|
|
||||||
border-bottom: 1px solid #f6f6f6;
|
|
||||||
}
|
|
||||||
tr:last-child {
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
padding: 15px 0;
|
|
||||||
border-bottom: 1px solid #999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
th {
|
|
||||||
vertical-align: top;
|
|
||||||
line-height: 30px;
|
|
||||||
}
|
|
||||||
td {
|
|
||||||
${TextInput} {
|
|
||||||
max-width: 600px;
|
|
||||||
}
|
|
||||||
${Textarea} {
|
|
||||||
width: 100%;
|
|
||||||
border: 1px solid #d9d9d9;
|
|
||||||
border-radius: 5px;
|
|
||||||
height: 150px;
|
|
||||||
padding: 15px;
|
|
||||||
&:focus {
|
|
||||||
border: 1px solid #2c2c2c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
import { styled } from 'styled-components';
|
|
||||||
import { TextInput, BtnWrapper, InputLabel, SelectInput } from '../../styles/Components';
|
|
||||||
import Button from '../common/button/Button';
|
|
||||||
import { SearchBarLayout, SearchPeriod } from '../common/SearchBar';
|
|
||||||
import { useState } from 'react';
|
|
||||||
|
|
||||||
const ReportListSearchBar = ({ handleSearch, setResultData }) => {
|
|
||||||
let d = new Date();
|
|
||||||
const START_DATE = new Date(new Date(d.setDate(d.getDate() - 1)).setHours(0, 0, 0, 0));
|
|
||||||
const END_DATE = new Date();
|
|
||||||
|
|
||||||
const reportType = [
|
|
||||||
{ value: 'ALL', name: '전체' },
|
|
||||||
{ value: 'UNMANNERED_ACT', name: '비매너 행위' },
|
|
||||||
{ value: 'USE_UNHEALTHY_NAMES', name: '불건전 이름 사용' },
|
|
||||||
{ value: 'CASH_TRADING', name: '현금거래 행위' },
|
|
||||||
{ value: 'INTERFERENCE_GAME', name: '게임 진행 방해' },
|
|
||||||
{ value: 'INTERFERENCE_SERVICE', name: '운영서비스 방해' },
|
|
||||||
{ value: 'ACCOUNT_EXPLOITATION', name: '계정도용' },
|
|
||||||
{ value: 'BUG_ABUSING', name: '버그/어뷰징' },
|
|
||||||
{ value: 'USE_HACK', name: '불법프로그램 사용' },
|
|
||||||
{ value: 'LEAK_PERSONAL_INFO', name: '개인정보 유출' },
|
|
||||||
{ value: 'PRETENDING_GM', name: '운영자 사칭' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const reportState = [
|
|
||||||
{ value: 'ALL', name: '전체' },
|
|
||||||
{ value: 'RESOLVED', name: '해결' },
|
|
||||||
{ value: 'UNRESOLVED', name: '미해결' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const searchType = [
|
|
||||||
{ value: 'ALL', name: '전체' },
|
|
||||||
{ value: 'GUID', name: '신고자' },
|
|
||||||
{ value: 'EMAIL', name: '담당자' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const [searchData, setSearchData] = useState({
|
|
||||||
startDate: START_DATE,
|
|
||||||
endDate: END_DATE,
|
|
||||||
reportType: 'ALL',
|
|
||||||
status: 'ALL',
|
|
||||||
searchType: 'ALL',
|
|
||||||
searchKey: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
// console.log(searchData);
|
|
||||||
|
|
||||||
const handleSubmit = event => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
handleSearch(
|
|
||||||
searchData.startDate ? new Date(searchData.startDate).toISOString().split('.')[0] : new Date(START_DATE).toISOString().split('.')[0],
|
|
||||||
searchData.endDate ? new Date(searchData.endDate).toISOString().split('.')[0] : new Date(END_DATE).toISOString().split('.')[0],
|
|
||||||
searchData.reportType ? searchData.reportType : 'ALL',
|
|
||||||
searchData.status ? searchData.status : 'ALL',
|
|
||||||
searchData.searchType ? searchData.searchType : 'ALL',
|
|
||||||
searchData.searchKey ? searchData.searchKey : '',
|
|
||||||
);
|
|
||||||
setResultData(searchData);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleReset = () => {
|
|
||||||
setSearchData({
|
|
||||||
startDate: START_DATE,
|
|
||||||
endDate: END_DATE,
|
|
||||||
reportType: 'ALL',
|
|
||||||
status: 'ALL',
|
|
||||||
searchKey: '',
|
|
||||||
order: 'DESC',
|
|
||||||
});
|
|
||||||
handleSearch(START_DATE, END_DATE, 'ALL', 'ALL', 'ALL', '');
|
|
||||||
setResultData(START_DATE, END_DATE, 'ALL', 'ALL', 'ALL', '');
|
|
||||||
window.location.reload();
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchList = [
|
|
||||||
<>
|
|
||||||
<InputLabel>신고 일자</InputLabel>
|
|
||||||
<SearchPeriod
|
|
||||||
startDate={searchData.startDate}
|
|
||||||
handleStartDate={data => {
|
|
||||||
setSearchData({ ...searchData, startDate: data });
|
|
||||||
}}
|
|
||||||
endDate={searchData.endDate}
|
|
||||||
handleEndDate={data => setSearchData({ ...searchData, endDate: data })}
|
|
||||||
maxDate={new Date()}
|
|
||||||
/>
|
|
||||||
</>,
|
|
||||||
];
|
|
||||||
|
|
||||||
const optionList = [
|
|
||||||
<>
|
|
||||||
<InputLabel>신고 유형</InputLabel>
|
|
||||||
<SelectInput value={searchData.reportType || ''} onChange={e => setSearchData({ ...searchData, reportType: e.target.value })}>
|
|
||||||
{reportType.map((data, index) => (
|
|
||||||
<option key={index} value={data.value || ''}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>상태</InputLabel>
|
|
||||||
<SelectInput value={searchData.status || ''} onChange={e => setSearchData({ ...searchData, status: e.target.value })}>
|
|
||||||
{reportState.map((data, index) => (
|
|
||||||
<option key={index} value={data.value || ''}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>신고자 / 담당자</InputLabel>
|
|
||||||
<InputGroup>
|
|
||||||
<SelectInput value={searchData.searchType || ''} onChange={e => setSearchData({ ...searchData, searchType: e.target.value })}>
|
|
||||||
{searchType.map((data, index) => (
|
|
||||||
<option key={index} value={data.value || ''}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
<TextInput placeholder="입력" onChange={e => setSearchData({ ...searchData, searchKey: e.target.value })} />
|
|
||||||
</InputGroup>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<BtnWrapper $gap="8px">
|
|
||||||
<Button theme="reset" handleClick={handleReset} type="button" />
|
|
||||||
<Button theme="search" text="검색" handleClick={handleSubmit} type="submit" />
|
|
||||||
</BtnWrapper>
|
|
||||||
</>,
|
|
||||||
];
|
|
||||||
return <SearchBarLayout firstColumnData={searchList} secondColumnData={optionList} direction={'column'} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ReportListSearchBar;
|
|
||||||
|
|
||||||
const InputGroup = styled.div`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 5px;
|
|
||||||
`;
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
import { Fragment, useState } from 'react';
|
|
||||||
import { styled } from 'styled-components';
|
|
||||||
|
|
||||||
import { Title, TableStyle, BtnWrapper, TextInput } from '../../styles/Components';
|
|
||||||
import Modal from '../../components/common/modal/Modal';
|
|
||||||
import Button from '../common/button/Button';
|
|
||||||
import { convertKTC } from '../../utils';
|
|
||||||
|
|
||||||
const UserBlockDetailModal = ({ stateModal, handleModal, data }) => {
|
|
||||||
const history = data.history;
|
|
||||||
|
|
||||||
const type = [
|
|
||||||
{ value: 'ACCESS_RESTRICTIONS', name: '접근 제한' },
|
|
||||||
{ value: 'CHATTING_RESTRICTIONS', name: '채팅 제한' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const sanctions = [
|
|
||||||
{ value: 'BAD_BEHAVIOR', name: '비매너 행위' },
|
|
||||||
{ value: 'INAPPROPRIATE_NAME', name: '불건전 이름 사용' },
|
|
||||||
{ value: 'CASH_TRANSACTION', name: '현금거래 행위' },
|
|
||||||
{ value: 'GAME_INTERFERENCE', name: '게임 진행 방해' },
|
|
||||||
{ value: 'SERVICE_INTERFERENCE', name: '운영서비스 방해' },
|
|
||||||
{ value: 'ACCOUNT_IMPERSONATION', name: '계정도용' },
|
|
||||||
{ value: 'BUG_ABUSE', name: '버그/어뷰징' },
|
|
||||||
{ value: 'ILLEGAL_PROGRAM', name: '불법프로그램 사용' },
|
|
||||||
{ value: 'PERSONAL_INFO_LEAK', name: '개인정보 유출' },
|
|
||||||
{ value: 'ADMIN_IMPERSONATION', name: '운영자 사칭' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const period = [
|
|
||||||
{ value: 'WARNING', name: '경고' },
|
|
||||||
{ value: 'D1', name: '1일' },
|
|
||||||
{ value: 'D3', name: '3일' },
|
|
||||||
{ value: 'D7', name: '7일' },
|
|
||||||
{ value: 'D15', name: '15일' },
|
|
||||||
{ value: 'D30', name: '30일' },
|
|
||||||
{ value: 'PERMANENT', name: '영구정지' },
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Modal min="960px" $view={stateModal}>
|
|
||||||
<Title $align="center">이용자 제재 상세 정보</Title>
|
|
||||||
<RegistInfo>
|
|
||||||
<span>등록자 : {data.create_by}</span>
|
|
||||||
<span>등록일 : {convertKTC(data.create_dt, false)}</span>
|
|
||||||
</RegistInfo>
|
|
||||||
<BlockDetailState>
|
|
||||||
<table>
|
|
||||||
<caption></caption>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th width="100px">유저 GUID</th>
|
|
||||||
<td>
|
|
||||||
<TextInput value={data && data.guid || ''} disabled />
|
|
||||||
</td>
|
|
||||||
<th width="100px">아바타명</th>
|
|
||||||
<td>
|
|
||||||
<TextInput value={data && data.nickname || ''} disabled />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>제재 방식</th>
|
|
||||||
<td>
|
|
||||||
<TextInput value={type.map(item => item.value === data.type && item.name).filter(data => data !== false) || ''} disabled />
|
|
||||||
</td>
|
|
||||||
<th></th>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>제재 기간</th>
|
|
||||||
<td colSpan="3">
|
|
||||||
<InputWrapper>
|
|
||||||
<TextInput value={period.map(item => item.value === data.period && item.name).filter(data => data !== false) || ''} disabled />
|
|
||||||
<span>시작일 : {convertKTC(data.start_dt, false)}</span>
|
|
||||||
<span>종료일 : {convertKTC(data.end_dt, false)}</span>
|
|
||||||
</InputWrapper>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>제재 사유</th>
|
|
||||||
<td>
|
|
||||||
<TextInput value={sanctions.map(item => item.value === data.sanctions && item.name).filter(data => data !== false) || ''} disabled />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</BlockDetailState>
|
|
||||||
|
|
||||||
<BlockCount>전체 제재 이력({history && history.length}건)</BlockCount>
|
|
||||||
<BlockHistory>
|
|
||||||
<TableStyle>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>일자</th>
|
|
||||||
<th width="10%">제재 기간</th>
|
|
||||||
<th width="10%">제재 방식</th>
|
|
||||||
<th width="20%">제재 사유</th>
|
|
||||||
<th width="20%">등록자</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{history &&
|
|
||||||
history.map((content, index) => (
|
|
||||||
<Fragment key={index}>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
{convertKTC(content.start_dt, false)} ~
|
|
||||||
{convertKTC(content.end_dt, false)}
|
|
||||||
</td>
|
|
||||||
<td>{period.map(item => item.value === data.period && item.name)}</td>
|
|
||||||
<td>{type.map(item => item.value === data.type && item.name)}</td>
|
|
||||||
<td>{sanctions.map(item => item.value === data.sanctions && item.name)}</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</Fragment>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</TableStyle>
|
|
||||||
</BlockHistory>
|
|
||||||
<BlockNotice>※ 삭제된 제재 이력은 표시되지 않습니다.</BlockNotice>
|
|
||||||
<BtnWrapper $justify="flex-end">
|
|
||||||
<Button text="확인" theme="line" handleClick={handleModal} />
|
|
||||||
</BtnWrapper>
|
|
||||||
</Modal>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default UserBlockDetailModal;
|
|
||||||
|
|
||||||
const BlockDetailState = styled.div`
|
|
||||||
border-top: 1px solid #000;
|
|
||||||
border-bottom: 1px solid #000;
|
|
||||||
padding: 15px 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
input {
|
|
||||||
height: 35px;
|
|
||||||
max-width: 330px;
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 5px 10px;
|
|
||||||
}
|
|
||||||
table {
|
|
||||||
tr {
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const RegistInfo = styled.div`
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 50px;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const BlockCount = styled.div`
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 1.6;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const BlockHistory = styled.div`
|
|
||||||
max-height: 324px;
|
|
||||||
position: relative;
|
|
||||||
overflow: auto;
|
|
||||||
border-top: 1px solid #000;
|
|
||||||
${TableStyle} {
|
|
||||||
border-collapse: separate;
|
|
||||||
&:before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
th {
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
tbody {
|
|
||||||
tr:first-child {
|
|
||||||
color: #d60000;
|
|
||||||
}
|
|
||||||
tr:last-child td {
|
|
||||||
border-bottom: 1px solid #e8eaec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const BlockNotice = styled.span`
|
|
||||||
font-size: 12px;
|
|
||||||
color: #686868;
|
|
||||||
padding-left: 10px;
|
|
||||||
font-weight: 300;
|
|
||||||
line-height: 2;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const InputWrapper = styled.div`
|
|
||||||
display: flex;
|
|
||||||
gap: 20px;
|
|
||||||
align-items: center;
|
|
||||||
`;
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import { TextInput, BtnWrapper, InputLabel, SelectInput, InputGroup } from '../../styles/Components';
|
|
||||||
import Button from '../common/button/Button';
|
|
||||||
import { SearchBarLayout } from '../common/SearchBar';
|
|
||||||
import { blockPeriod, blockSanctions, blockSearchType, blockStatus } from '../../assets/data';
|
|
||||||
import { userSearchType } from '../../assets/data/options';
|
|
||||||
|
|
||||||
const UserBlockSearchBar = ({ handleSearch, setResultData }) => {
|
|
||||||
const [searchData, setSearchData] = useState({
|
|
||||||
searchType: 'GUID',
|
|
||||||
data: '',
|
|
||||||
email: '',
|
|
||||||
status: 'ALL',
|
|
||||||
sanctions: 'ALL',
|
|
||||||
period: 'ALL',
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleSubmit = event => {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
handleSearch(
|
|
||||||
searchData.searchType ? searchData.searchType : 'GUID',
|
|
||||||
searchData.data,
|
|
||||||
searchData.email,
|
|
||||||
searchData.status ? searchData.status : 'ALL',
|
|
||||||
searchData.sanctions ? searchData.sanctions : 'ALL',
|
|
||||||
searchData.period ? searchData.period : 'ALL',
|
|
||||||
);
|
|
||||||
|
|
||||||
setResultData(searchData);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 초기화 버튼
|
|
||||||
const handleReset = () => {
|
|
||||||
setSearchData({
|
|
||||||
searchType: 'GUID',
|
|
||||||
data: '',
|
|
||||||
email: '',
|
|
||||||
status: 'ALL',
|
|
||||||
sanctions: 'ALL',
|
|
||||||
period: 'ALL',
|
|
||||||
});
|
|
||||||
handleSearch('GUID', '', '', 'ALL', 'ALL', 'ALL');
|
|
||||||
setResultData('GUID', '', '', 'ALL', 'ALL', 'ALL');
|
|
||||||
window.location.reload();
|
|
||||||
};
|
|
||||||
|
|
||||||
// console.log(searchData);
|
|
||||||
|
|
||||||
const searchList = [
|
|
||||||
<>
|
|
||||||
<InputLabel>대상</InputLabel>
|
|
||||||
<InputGroup>
|
|
||||||
<SelectInput value={searchData.searchType} onChange={e => setSearchData({ ...searchData, searchType: e.target.value })}>
|
|
||||||
{userSearchType.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
<TextInput
|
|
||||||
type="text"
|
|
||||||
placeholder={searchData.searchType === 'GUID' ? 'GUID 입력' : '닉네임 입력'}
|
|
||||||
value={searchData.data}
|
|
||||||
width="600px"
|
|
||||||
onChange={e => setSearchData({ ...searchData, data: e.target.value })}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>등록자</InputLabel>
|
|
||||||
<TextInput type="text" placeholder="이메일 입력" width="600px" value={searchData.email} onChange={e => setSearchData({ ...searchData, email: e.target.value })} />
|
|
||||||
</>,
|
|
||||||
];
|
|
||||||
|
|
||||||
const optionList = [
|
|
||||||
<>
|
|
||||||
<InputLabel>상태</InputLabel>
|
|
||||||
<SelectInput value={searchData.status} onChange={e => setSearchData({ ...searchData, status: e.target.value })}>
|
|
||||||
{blockStatus.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>제재 사유</InputLabel>
|
|
||||||
<SelectInput value={searchData.sanctions} onChange={e => setSearchData({ ...searchData, sanctions: e.target.value })}>
|
|
||||||
{blockSanctions.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<InputLabel>제재 기간</InputLabel>
|
|
||||||
<SelectInput value={searchData.period} onChange={e => setSearchData({ ...searchData, period: e.target.value })}>
|
|
||||||
{blockPeriod.map((data, index) => (
|
|
||||||
<option key={index} value={data.value}>
|
|
||||||
{data.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</SelectInput>
|
|
||||||
</>,
|
|
||||||
<>
|
|
||||||
<BtnWrapper $gap="8px">
|
|
||||||
<Button theme="reset" handleClick={handleReset} />
|
|
||||||
<Button theme="search" text="검색" type="submit" handleClick={handleSubmit} />
|
|
||||||
</BtnWrapper>
|
|
||||||
</>,
|
|
||||||
];
|
|
||||||
return <SearchBarLayout firstColumnData={searchList} secondColumnData={optionList} direction={'column'} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default UserBlockSearchBar;
|
|
||||||
@@ -6,38 +6,33 @@ import Loading from '../../common/Loading';
|
|||||||
import {
|
import {
|
||||||
Title,
|
Title,
|
||||||
BtnWrapper,
|
BtnWrapper,
|
||||||
SearchBarAlert, SelectInput, InputLabel, DatePickerWrapper,
|
SearchBarAlert, SelectInput,
|
||||||
} from '../../../styles/Components';
|
} from '../../../styles/Components';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
FormHelperText,
|
|
||||||
FormInput,
|
FormInput,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormTextArea,
|
|
||||||
FormTextAreaWrapper,
|
|
||||||
MessageWrapper,
|
MessageWrapper,
|
||||||
FormRowGroup,
|
FormRowGroup,
|
||||||
NoticeInputRow2,
|
|
||||||
NoticeInputItem2,
|
|
||||||
BoxWrapper,
|
|
||||||
FormStatusBar,
|
FormStatusBar,
|
||||||
FormStatusLabel,
|
FormStatusLabel,
|
||||||
FormStatusWarning,
|
FormStatusWarning,
|
||||||
FormButtonContainer,
|
FormButtonContainer,
|
||||||
StyledSelectInput, TimeSeparator, TimeContainer,
|
|
||||||
} from '../../../styles/ModuleComponents';
|
} from '../../../styles/ModuleComponents';
|
||||||
import { HourList, MinuteList, modalTypes } from '../../../assets/data';
|
import { modalTypes } from '../../../assets/data';
|
||||||
import { DynamicModal, Modal, DateTimeRangePicker, SingleDatePicker, SingleTimePicker } from '../../common';
|
import { DynamicModal, Modal, SingleDatePicker, SingleTimePicker } from '../../common';
|
||||||
import { LandAuctionModify, LandAuctionSingleRegist } from '../../../apis';
|
|
||||||
import { NONE, TYPE_MODIFY, TYPE_REGISTRY } from '../../../assets/data/adminConstants';
|
import { NONE, TYPE_MODIFY, TYPE_REGISTRY } from '../../../assets/data/adminConstants';
|
||||||
import { landAuctionStatus, landAuctionStatusType, languageType, CurrencyType } from '../../../assets/data';
|
|
||||||
import { useModal } from '../../../utils/hook';
|
import { useModal } from '../../../utils/hook';
|
||||||
import { convertKTCDate } from '../../../utils';
|
import { convertKTCDate } from '../../../utils';
|
||||||
import { battleEventStatus, battleRepeatType } from '../../../assets/data/options';
|
import {
|
||||||
import DatePickerComponent from '../../common/Date/DatePickerComponent';
|
battleEventHotTime,
|
||||||
|
battleEventRoundCount,
|
||||||
|
battleEventStatus,
|
||||||
|
battleRepeatType,
|
||||||
|
} from '../../../assets/data/options';
|
||||||
import { BattleEventModify, BattleEventSingleRegist } from '../../../apis/Battle';
|
import { BattleEventModify, BattleEventSingleRegist } from '../../../apis/Battle';
|
||||||
import { battleEventStatusType } from '../../../assets/data/types';
|
import { battleEventStatusType } from '../../../assets/data/types';
|
||||||
import { result } from 'lodash';
|
import { isValidDayRange } from '../../../utils/date';
|
||||||
|
|
||||||
const BattleEventModal = ({ modalType, detailView, handleDetailView, content, setDetailData, configData, rewardData }) => {
|
const BattleEventModal = ({ modalType, detailView, handleDetailView, content, setDetailData, configData, rewardData }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -53,18 +48,17 @@ const BattleEventModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
registConfirm: 'hidden',
|
registConfirm: 'hidden',
|
||||||
registComplete: 'hidden'
|
registComplete: 'hidden'
|
||||||
});
|
});
|
||||||
const [message_lang, setMessage_lang] = useState('KO');
|
|
||||||
|
|
||||||
const [isNullValue, setIsNullValue] = useState(false); // 데이터 값 체크
|
const [isNullValue, setIsNullValue] = useState(false); // 데이터 값 체크
|
||||||
const [alertMsg, setAlertMsg] = useState('');
|
const [alertMsg, setAlertMsg] = useState('');
|
||||||
|
|
||||||
const [resultData, setResultData] = useState(initData); //데이터 정보
|
const [resultData, setResultData] = useState(initData); //데이터 정보
|
||||||
const [resetDateTime, setResetDateTime] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(modalType === TYPE_MODIFY && content && Object.keys(content).length > 0){
|
if(modalType === TYPE_MODIFY && content && Object.keys(content).length > 0){
|
||||||
setResultData({
|
setResultData({
|
||||||
group_id: content.group_id,
|
group_id: content.group_id,
|
||||||
|
event_id: content.event_id,
|
||||||
event_name: content.event_name,
|
event_name: content.event_name,
|
||||||
repeat_type: content.repeat_type,
|
repeat_type: content.repeat_type,
|
||||||
config_id: content.config_id,
|
config_id: content.config_id,
|
||||||
@@ -74,11 +68,21 @@ const BattleEventModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
round_time: content.round_time,
|
round_time: content.round_time,
|
||||||
status: content.status,
|
status: content.status,
|
||||||
event_start_dt: convertKTCDate(content.event_start_dt),
|
event_start_dt: convertKTCDate(content.event_start_dt),
|
||||||
event_end_dt: convertKTCDate(content.event_end_dt)
|
event_end_dt: content.event_end_dt,
|
||||||
|
event_operation_time: content.event_operation_time,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [modalType, content]);
|
}, [modalType, content]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(modalType === TYPE_REGISTRY && configData?.length > 0){
|
||||||
|
setResultData(prev => ({
|
||||||
|
...prev,
|
||||||
|
round_count: configData[0].default_round_count
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}, [modalType, configData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (checkCondition()) {
|
if (checkCondition()) {
|
||||||
setIsNullValue(false);
|
setIsNullValue(false);
|
||||||
@@ -87,18 +91,23 @@ const BattleEventModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
}
|
}
|
||||||
}, [resultData]);
|
}, [resultData]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (resetDateTime) {
|
|
||||||
setResetDateTime(false);
|
|
||||||
}
|
|
||||||
}, [resetDateTime]);
|
|
||||||
|
|
||||||
// 시작 날짜 변경 핸들러
|
// 시작 날짜 변경 핸들러
|
||||||
const handleStartDateChange = (date) => {
|
const handleStartDateChange = (date) => {
|
||||||
if (!date) return;
|
if (!date) return;
|
||||||
|
|
||||||
const newDate = new Date(date);
|
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('BATTLE_EVENT_MODAL_START_DIFF_END_WARNING'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setResultData(prev => ({
|
setResultData(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
event_start_dt: newDate
|
event_start_dt: newDate
|
||||||
@@ -128,9 +137,9 @@ const BattleEventModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
|
|
||||||
// 종료 날짜 변경 핸들러
|
// 종료 날짜 변경 핸들러
|
||||||
const handleEndDateChange = (date) => {
|
const handleEndDateChange = (date) => {
|
||||||
if (!date || !resultData.start_dt) return;
|
if (!date || !resultData.event_start_dt) return;
|
||||||
|
|
||||||
const startDate = new Date(resultData.start_dt);
|
const startDate = new Date(resultData.event_start_dt);
|
||||||
const endDate = new Date(date);
|
const endDate = new Date(date);
|
||||||
|
|
||||||
// 일자만 비교하기 위해 년/월/일만 추출
|
// 일자만 비교하기 위해 년/월/일만 추출
|
||||||
@@ -138,29 +147,32 @@ const BattleEventModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
const endDay = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
const endDay = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||||
|
|
||||||
if (endDay <= startDay) {
|
if (endDay <= startDay) {
|
||||||
setAlertMsg('종료일은 시작일보다 하루 이후여야 합니다.');
|
setAlertMsg(t('BATTLE_EVENT_MODAL_START_DIFF_END_WARNING'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newDate = new Date(date);
|
|
||||||
newDate.setHours(23, 59, 59, 0);
|
|
||||||
|
|
||||||
setResultData(prev => ({
|
setResultData(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
event_end_dt: newDate
|
event_end_dt: endDate
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleConfigChange = (e) => {
|
const handleConfigChange = (e) => {
|
||||||
const config = configData.find(data => data.id === e.target.value);
|
const config = configData.find(data => String(data.id) === String(e.target.value));
|
||||||
setResultData({ ...resultData, config_id: config.id, round_time: config.round_time });
|
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 = () => {
|
const handleReset = () => {
|
||||||
setMessage_lang('KO')
|
|
||||||
setDetailData({});
|
setDetailData({});
|
||||||
setResultData(initData);
|
setResultData(initData);
|
||||||
setResetDateTime(true);
|
|
||||||
handleDetailView();
|
handleDetailView();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,18 +182,20 @@ const BattleEventModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
if (!checkCondition()) return;
|
if (!checkCondition()) return;
|
||||||
|
|
||||||
const minAllowedTime = new Date(new Date().getTime() + 10 * 60000);
|
const minAllowedTime = new Date(new Date().getTime() + 10 * 60000);
|
||||||
if (resultData.event_start_dt < minAllowedTime) {
|
const startDt = resultData.event_start_dt;
|
||||||
setAlertMsg(t('BATTLE_EVENT_MADEL_START_DT_WARNING'));
|
const endDt = resultData.event_end_dt;
|
||||||
|
if (modalType === TYPE_REGISTRY && startDt < minAllowedTime) {
|
||||||
|
setAlertMsg(t('BATTLE_EVENT_MODAL_START_DT_WARNING'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(resultData.repeat_type !== 'NONE' && resultData.event_start_dt >= resultData.event_end_dt) {
|
if(resultData.repeat_type !== 'NONE' && !isValidDayRange(startDt, endDt)) {
|
||||||
setAlertMsg(t('LAND_AUCTION_MADEL_AUCTION_DIFF_AUCTION'))
|
setAlertMsg(t('BATTLE_EVENT_MODAL_START_DIFF_END_WARNING'))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//화면에 머물면서 상태는 안바꼈을 경우가 있기에 시작시간 지났을경우 차단
|
//화면에 머물면서 상태는 안바꼈을 경우가 있기에 시작시간 지났을경우 차단
|
||||||
if (modalType === TYPE_MODIFY && resultData.event_start_dt < new Date()) {
|
if (modalType === TYPE_REGISTRY && startDt < new Date()) {
|
||||||
setAlertMsg(t('LAND_AUCTION_MADEL_MODIFY_START'));
|
setAlertMsg(t('BATTLE_EVENT_MODAL_START_DT_WARNING'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,8 +222,8 @@ const BattleEventModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
handleModalClose('registConfirm');
|
handleModalClose('registConfirm');
|
||||||
if(data.result === "SUCCESS") {
|
if(data.result === "SUCCESS") {
|
||||||
handleModalView('registComplete');
|
handleModalView('registComplete');
|
||||||
}else if(data.result === "ERROR_AUCTION_STATUS_IMPOSSIBLE"){
|
}else if(data.result === "ERROR_BATTLE_EVENT_TIME_OVER"){
|
||||||
setAlertMsg(t('LAND_AUCTION_ERROR_MODIFY_STATUS'));
|
setAlertMsg(t('BATTLE_EVENT_MODAL_TIME_CHECK_WARNING'));
|
||||||
}else{
|
}else{
|
||||||
setAlertMsg(t('UPDATE_FAIL'));
|
setAlertMsg(t('UPDATE_FAIL'));
|
||||||
}
|
}
|
||||||
@@ -223,8 +237,8 @@ const BattleEventModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
handleModalClose('registConfirm');
|
handleModalClose('registConfirm');
|
||||||
if(data.result === "SUCCESS") {
|
if(data.result === "SUCCESS") {
|
||||||
handleModalView('registComplete');
|
handleModalView('registComplete');
|
||||||
}else if(data.result === "ERROR_LAND_AUCTION_IMPOSSIBLE"){
|
}else if(data.result === "ERROR_BATTLE_EVENT_TIME_OVER"){
|
||||||
setAlertMsg(t('LAND_AUCTION_ERROR_PROGRESS'));
|
setAlertMsg(t('BATTLE_EVENT_MODAL_TIME_CHECK_WARNING'));
|
||||||
}else{
|
}else{
|
||||||
setAlertMsg(t('REGIST_FAIL'));
|
setAlertMsg(t('REGIST_FAIL'));
|
||||||
}
|
}
|
||||||
@@ -256,20 +270,21 @@ const BattleEventModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
const isView = (label) => {
|
const isView = (label) => {
|
||||||
switch (label) {
|
switch (label) {
|
||||||
case "modify":
|
case "modify":
|
||||||
return modalType === TYPE_MODIFY && (content?.status === battleEventStatusType.register);
|
return modalType === TYPE_MODIFY && (content?.status === battleEventStatusType.stop);
|
||||||
case "registry":
|
case "start_dt":
|
||||||
case "repeat":
|
case "repeat":
|
||||||
|
case "registry":
|
||||||
|
return modalType === TYPE_REGISTRY
|
||||||
|
case "end_dt":
|
||||||
case "group":
|
case "group":
|
||||||
case "name":
|
case "name":
|
||||||
case "config":
|
case "config":
|
||||||
case "reward":
|
case "reward":
|
||||||
case "round":
|
case "round":
|
||||||
case "hot":
|
case "hot":
|
||||||
case "start_dt":
|
return modalType === TYPE_REGISTRY || (modalType === TYPE_MODIFY &&(content?.status === battleEventStatusType.stop));
|
||||||
return modalType === TYPE_REGISTRY
|
|
||||||
default:
|
default:
|
||||||
return modalType === TYPE_MODIFY && (content?.status === battleEventStatusType.register
|
return modalType === TYPE_MODIFY && (content?.status !== battleEventStatusType.stop);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +338,7 @@ const BattleEventModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
{resultData?.repeat_type !== 'NONE' &&
|
{resultData?.repeat_type !== 'NONE' &&
|
||||||
<SingleDatePicker
|
<SingleDatePicker
|
||||||
label="종료일자"
|
label="종료일자"
|
||||||
disabled={false}
|
disabled={!isView('end_dt')}
|
||||||
dateLabel="종료 일자"
|
dateLabel="종료 일자"
|
||||||
onDateChange={handleEndDateChange}
|
onDateChange={handleEndDateChange}
|
||||||
selectedDate={resultData?.event_end_dt}
|
selectedDate={resultData?.event_end_dt}
|
||||||
@@ -341,7 +356,7 @@ const BattleEventModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
</SelectInput>
|
</SelectInput>
|
||||||
<FormLabel>라운드 수</FormLabel>
|
<FormLabel>라운드 수</FormLabel>
|
||||||
<SelectInput value={resultData.round_count} onChange={e => setResultData({ ...resultData, round_count: e.target.value })} disabled={!isView('round')} width="100px">
|
<SelectInput value={resultData.round_count} onChange={e => setResultData({ ...resultData, round_count: e.target.value })} disabled={!isView('round')} width="100px">
|
||||||
{[1,2,3,4,8,12,16].map((data, index) => (
|
{battleEventRoundCount.map((data, index) => (
|
||||||
<option key={index} value={data}>
|
<option key={index} value={data}>
|
||||||
{data}
|
{data}
|
||||||
</option>
|
</option>
|
||||||
@@ -359,7 +374,7 @@ const BattleEventModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
</SelectInput>
|
</SelectInput>
|
||||||
<FormLabel>핫타임</FormLabel>
|
<FormLabel>핫타임</FormLabel>
|
||||||
<SelectInput value={resultData.hot_time} onChange={e => setResultData({ ...resultData, hot_time: e.target.value })} disabled={!isView('hot')} width="100px">
|
<SelectInput value={resultData.hot_time} onChange={e => setResultData({ ...resultData, hot_time: e.target.value })} disabled={!isView('hot')} width="100px">
|
||||||
{[1,2,3,4,5,6,7,8].map((data, index) => (
|
{battleEventHotTime.map((data, index) => (
|
||||||
<option key={index} value={data}>
|
<option key={index} value={data}>
|
||||||
{data}배
|
{data}배
|
||||||
</option>
|
</option>
|
||||||
@@ -376,7 +391,7 @@ const BattleEventModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
현재상태: {battleEventStatus.find(data => data.value === content?.status)?.name || "등록"}
|
현재상태: {battleEventStatus.find(data => data.value === content?.status)?.name || "등록"}
|
||||||
</FormStatusLabel>
|
</FormStatusLabel>
|
||||||
<FormStatusWarning>
|
<FormStatusWarning>
|
||||||
{isView('registry') ? '' : t('LAND_AUCTION_MODAL_STATUS_WARNING')}
|
{isView('registry') ? '' : t('BATTLE_EVENT_MODAL_STATUS_WARNING')}
|
||||||
</FormStatusWarning>
|
</FormStatusWarning>
|
||||||
</FormStatusBar>
|
</FormStatusBar>
|
||||||
<FormButtonContainer $gap="5px">
|
<FormButtonContainer $gap="5px">
|
||||||
@@ -411,7 +426,7 @@ const BattleEventModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
<DynamicModal
|
<DynamicModal
|
||||||
modalType={modalTypes.confirmOkCancel}
|
modalType={modalTypes.confirmOkCancel}
|
||||||
view={modalState.registConfirmModal}
|
view={modalState.registConfirmModal}
|
||||||
modalText={isView('modify') ? t('LAND_UPDATE_CONFIRM') : t('LAND_REGIST_CONFIRM')}
|
modalText={isView('modify') ? t('BATTLE_EVENT_UPDATE_CONFIRM') : t('BATTLE_EVENT_REGIST_CONFIRM')}
|
||||||
handleSubmit={() => handleSubmit('registConfirm')}
|
handleSubmit={() => handleSubmit('registConfirm')}
|
||||||
handleCancel={() => handleModalClose('registConfirm')}
|
handleCancel={() => handleModalClose('registConfirm')}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -23,10 +23,17 @@ import {
|
|||||||
import { modalTypes } from '../../../assets/data';
|
import { modalTypes } from '../../../assets/data';
|
||||||
import {DynamicModal, Modal, DateTimeRangePicker} from '../../common';
|
import {DynamicModal, Modal, DateTimeRangePicker} from '../../common';
|
||||||
import { LandAuctionModify, LandAuctionSingleRegist } from '../../../apis';
|
import { LandAuctionModify, LandAuctionSingleRegist } from '../../../apis';
|
||||||
import { TYPE_MODIFY, TYPE_REGISTRY } from '../../../assets/data/adminConstants';
|
import {
|
||||||
|
AUCTION_MIN_MINUTE_TIME,
|
||||||
|
ONE_MINUTE,
|
||||||
|
ONE_MINUTE_MS,
|
||||||
|
TYPE_MODIFY,
|
||||||
|
TYPE_REGISTRY,
|
||||||
|
} from '../../../assets/data/adminConstants';
|
||||||
import { landAuctionStatus, landAuctionStatusType, languageType, CurrencyType } from '../../../assets/data';
|
import { landAuctionStatus, landAuctionStatusType, languageType, CurrencyType } from '../../../assets/data';
|
||||||
import { useModal } from '../../../utils/hook';
|
import { useModal } from '../../../utils/hook';
|
||||||
import { convertKTCDate } from '../../../utils';
|
import { convertKTCDate } from '../../../utils';
|
||||||
|
import { msToMinutes } from '../../../utils/date';
|
||||||
|
|
||||||
const LandAuctionModal = ({ modalType, detailView, handleDetailView, content, setDetailData, landData, buildingData }) => {
|
const LandAuctionModal = ({ modalType, detailView, handleDetailView, content, setDetailData, landData, buildingData }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -174,19 +181,24 @@ const LandAuctionModal = ({ modalType, detailView, handleDetailView, content, se
|
|||||||
|
|
||||||
const minAllowedTime = new Date(new Date().getTime() + 5 * 60000);
|
const minAllowedTime = new Date(new Date().getTime() + 5 * 60000);
|
||||||
if (isView('recv') && resultData.resv_start_dt < minAllowedTime) {
|
if (isView('recv') && resultData.resv_start_dt < minAllowedTime) {
|
||||||
setAlertMsg(t('LAND_AUCTION_MADEL_RESV_START_WARNING'));
|
setAlertMsg(t('LAND_AUCTION_MODEL_RESV_START_WARNING'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (resultData.auction_start_dt < minAllowedTime) {
|
if (resultData.auction_start_dt < minAllowedTime) {
|
||||||
setAlertMsg(t('LAND_AUCTION_MADEL_AUCTION_START_WARNING'));
|
setAlertMsg(t('LAND_AUCTION_MODEL_AUCTION_START_WARNING'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(resultData.resv_start_dt >= resultData.auction_start_dt || resultData.resv_start_dt >= resultData.auction_end_dt) {
|
if(resultData.resv_start_dt >= resultData.auction_start_dt || resultData.resv_start_dt >= resultData.auction_end_dt) {
|
||||||
setAlertMsg(t('LAND_AUCTION_MADEL_AUCTION_DIFF_RESERVATION'))
|
setAlertMsg(t('LAND_AUCTION_MODEL_AUCTION_DIFF_RESERVATION'))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(resultData.auction_start_dt >= resultData.auction_end_dt) {
|
if(resultData.auction_start_dt >= resultData.auction_end_dt) {
|
||||||
setAlertMsg(t('LAND_AUCTION_MADEL_AUCTION_DIFF_AUCTION'))
|
setAlertMsg(t('LAND_AUCTION_MODEL_AUCTION_DIFF_AUCTION'))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const diffAuctionTime = resultData.auction_end_dt - resultData.auction_start_dt;
|
||||||
|
if(msToMinutes(diffAuctionTime) < AUCTION_MIN_MINUTE_TIME){
|
||||||
|
setAlertMsg(t('LAND_AUCTION_MODEL_MIN_TIME_WARNING'))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,19 +2,27 @@ import { TextInput, BtnWrapper, InputLabel, SelectInput, InputGroup } from '../.
|
|||||||
import Button from '../../common/button/Button';
|
import Button from '../../common/button/Button';
|
||||||
import { SearchBarLayout, SearchPeriod } from '../../common/SearchBar';
|
import { SearchBarLayout, SearchPeriod } from '../../common/SearchBar';
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { landAuctionStatus, landSearchType, landSize, userSearchType } from '../../../assets/data';
|
|
||||||
import { BattleEventView } from '../../../apis/Battle';
|
import { BattleEventView } from '../../../apis/Battle';
|
||||||
|
import {
|
||||||
|
battleEventHotTime,
|
||||||
|
battleEventRoundCount,
|
||||||
|
battleEventStatus,
|
||||||
|
battleRepeatType,
|
||||||
|
eventSearchType,
|
||||||
|
} from '../../../assets/data/options';
|
||||||
|
|
||||||
export const useBattleEventSearch = (token, initialPageSize) => {
|
export const useBattleEventSearch = (token, initialPageSize) => {
|
||||||
const [searchParams, setSearchParams] = useState({
|
const [searchParams, setSearchParams] = useState({
|
||||||
landType: 'ID',
|
searchType: 'ID',
|
||||||
landData: '',
|
searchData: '',
|
||||||
userType: 'GUID',
|
configId: 'ALL',
|
||||||
userData: '',
|
rewardId: 'ALL',
|
||||||
landSize: 'ALL',
|
repeatType: 'ALL',
|
||||||
status: 'ALL',
|
status: 'ALL',
|
||||||
auctionStartDate: '',
|
roundCount: 'ALL',
|
||||||
auctionEndDate: '',
|
hotTime: 'ALL',
|
||||||
|
startDate: '',
|
||||||
|
endDate: '',
|
||||||
orderBy: 'DESC',
|
orderBy: 'DESC',
|
||||||
pageSize: initialPageSize,
|
pageSize: initialPageSize,
|
||||||
currentPage: 1
|
currentPage: 1
|
||||||
@@ -32,14 +40,16 @@ export const useBattleEventSearch = (token, initialPageSize) => {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
const result = await BattleEventView(
|
const result = await BattleEventView(
|
||||||
token,
|
token,
|
||||||
params.landType,
|
params.searchType,
|
||||||
params.landData,
|
params.searchData,
|
||||||
params.userType,
|
params.configId,
|
||||||
params.userData,
|
params.rewardId,
|
||||||
params.landSize,
|
params.repeatType,
|
||||||
params.status,
|
params.status,
|
||||||
params.auctionStartDate && new Date(params.auctionStartDate).toISOString(),
|
params.roundCount,
|
||||||
params.auctionEndDate && new Date(params.auctionEndDate).toISOString(),
|
params.hotTime,
|
||||||
|
params.startDate && new Date(params.startDate).toISOString(),
|
||||||
|
params.endDate && new Date(params.endDate).toISOString(),
|
||||||
params.orderBy,
|
params.orderBy,
|
||||||
params.pageSize,
|
params.pageSize,
|
||||||
params.currentPage
|
params.currentPage
|
||||||
@@ -73,14 +83,16 @@ export const useBattleEventSearch = (token, initialPageSize) => {
|
|||||||
|
|
||||||
const handleReset = useCallback(async () => {
|
const handleReset = useCallback(async () => {
|
||||||
const resetParams = {
|
const resetParams = {
|
||||||
landType: 'ID',
|
searchType: 'ID',
|
||||||
landData: '',
|
searchData: '',
|
||||||
userType: 'GUID',
|
configId: 'ALL',
|
||||||
userData: '',
|
rewardId: 'ALL',
|
||||||
landSize: 'ALL',
|
repeatType: 'ALL',
|
||||||
status: 'ALL',
|
status: 'ALL',
|
||||||
auctionStartDate: '',
|
roundCount: 'ALL',
|
||||||
auctionEndDate: '',
|
hotTime: 'ALL',
|
||||||
|
startDate: '',
|
||||||
|
endDate: '',
|
||||||
orderBy: 'DESC',
|
orderBy: 'DESC',
|
||||||
pageSize: initialPageSize,
|
pageSize: initialPageSize,
|
||||||
currentPage: 1
|
currentPage: 1
|
||||||
@@ -114,7 +126,7 @@ export const useBattleEventSearch = (token, initialPageSize) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const BattleEventSearchBar = ({ searchParams, onSearch, onReset }) => {
|
const BattleEventSearchBar = ({ searchParams, onSearch, onReset, configData, rewardData }) => {
|
||||||
const handleSubmit = event => {
|
const handleSubmit = event => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
@@ -124,8 +136,8 @@ const BattleEventSearchBar = ({ searchParams, onSearch, onReset }) => {
|
|||||||
const searchList = [
|
const searchList = [
|
||||||
<>
|
<>
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<SelectInput value={searchParams.landType} onChange={e => onSearch({landType: e.target.value })}>
|
<SelectInput value={searchParams.searchType} onChange={e => onSearch({searchType: e.target.value })}>
|
||||||
{landSearchType.map((data, index) => (
|
{eventSearchType.map((data, index) => (
|
||||||
<option key={index} value={data.value}>
|
<option key={index} value={data.value}>
|
||||||
{data.name}
|
{data.name}
|
||||||
</option>
|
</option>
|
||||||
@@ -133,39 +145,55 @@ const BattleEventSearchBar = ({ searchParams, onSearch, onReset }) => {
|
|||||||
</SelectInput>
|
</SelectInput>
|
||||||
<TextInput
|
<TextInput
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={searchParams.landType === 'ID' ? '랜드 ID 입력' : '랜드명 입력'}
|
placeholder={searchParams.searchType === 'ID' ? '이벤트 ID 입력' : '이벤트명 입력'}
|
||||||
value={searchParams.landData}
|
value={searchParams.searchData}
|
||||||
width="300px"
|
width="300px"
|
||||||
onChange={e => onSearch({ landData: e.target.value })}
|
onChange={e => onSearch({ searchData: e.target.value })}
|
||||||
/>
|
/>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
</>,
|
</>,
|
||||||
<>
|
<>
|
||||||
<InputLabel>낙찰자</InputLabel>
|
<InputLabel>라운드 시간</InputLabel>
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<SelectInput value={searchParams.userType} onChange={e => onSearch({userType: e.target.value })}>
|
<SelectInput value={searchParams.configId} onChange={e => onSearch({ configId: e.target.value })}>
|
||||||
{userSearchType.map((data, index) => (
|
<option value="ALL">전체</option>
|
||||||
<option key={index} value={data.value}>
|
{configData?.map((data, index) => (
|
||||||
{data.name}
|
<option key={index} value={data.id}>
|
||||||
|
{data.desc}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</SelectInput>
|
||||||
|
</InputGroup>
|
||||||
|
<InputLabel>배정 포드</InputLabel>
|
||||||
|
<InputGroup>
|
||||||
|
<SelectInput value={searchParams.rewardId} onChange={e => onSearch({ rewardId: e.target.value })}>
|
||||||
|
<option value='ALL'>전체</option>
|
||||||
|
{rewardData?.map((data, index) => (
|
||||||
|
<option key={index} value={data.id}>
|
||||||
|
{data.desc}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</SelectInput>
|
||||||
|
</InputGroup>
|
||||||
|
<InputLabel>라운드 수</InputLabel>
|
||||||
|
<InputGroup>
|
||||||
|
<SelectInput value={searchParams.roundCount} onChange={e => onSearch({ roundCount: e.target.value })}>
|
||||||
|
<option value='ALL'>전체</option>
|
||||||
|
{battleEventRoundCount.map((data, index) => (
|
||||||
|
<option key={index} value={data}>
|
||||||
|
{data}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</SelectInput>
|
</SelectInput>
|
||||||
<TextInput
|
|
||||||
type="text"
|
|
||||||
placeholder={searchParams.userType === 'GUID' ? 'GUID 입력' : '닉네임 입력'}
|
|
||||||
value={searchParams.userData}
|
|
||||||
width="300px"
|
|
||||||
onChange={e => onSearch({ userData: e.target.value })}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
</>
|
</>
|
||||||
];
|
];
|
||||||
|
|
||||||
const optionList = [
|
const optionList = [
|
||||||
<>
|
<>
|
||||||
<InputLabel>랜드크기</InputLabel>
|
<InputLabel>반복</InputLabel>
|
||||||
<SelectInput value={searchParams.landSize} onChange={e => onSearch({ landSize: e.target.value }, false)} >
|
<SelectInput value={searchParams.repeatType} onChange={e => onSearch({ repeatType: e.target.value }, false)} >
|
||||||
{landSize.map((data, index) => (
|
{battleRepeatType.map((data, index) => (
|
||||||
<option key={index} value={data.value}>
|
<option key={index} value={data.value}>
|
||||||
{data.name}
|
{data.name}
|
||||||
</option>
|
</option>
|
||||||
@@ -173,9 +201,9 @@ const BattleEventSearchBar = ({ searchParams, onSearch, onReset }) => {
|
|||||||
</SelectInput>
|
</SelectInput>
|
||||||
</>,
|
</>,
|
||||||
<>
|
<>
|
||||||
<InputLabel>경매상태</InputLabel>
|
<InputLabel>이벤트상태</InputLabel>
|
||||||
<SelectInput value={searchParams.status} onChange={e => onSearch({ status: e.target.value }, false)}>
|
<SelectInput value={searchParams.status} onChange={e => onSearch({ status: e.target.value }, false)}>
|
||||||
{landAuctionStatus.map((data, index) => (
|
{battleEventStatus.map((data, index) => (
|
||||||
<option key={index} value={data.value}>
|
<option key={index} value={data.value}>
|
||||||
{data.name}
|
{data.name}
|
||||||
</option>
|
</option>
|
||||||
@@ -183,12 +211,23 @@ const BattleEventSearchBar = ({ searchParams, onSearch, onReset }) => {
|
|||||||
</SelectInput>
|
</SelectInput>
|
||||||
</>,
|
</>,
|
||||||
<>
|
<>
|
||||||
<InputLabel>경매 일자</InputLabel>
|
<InputLabel>핫타임</InputLabel>
|
||||||
|
<SelectInput value={searchParams.hotTime} onChange={e => onSearch({ hotTime: e.target.value }, false)}>
|
||||||
|
<option value="ALL">전체</option>
|
||||||
|
{battleEventHotTime.map((data, index) => (
|
||||||
|
<option key={index} value={data}>
|
||||||
|
{data}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</SelectInput>
|
||||||
|
</>,
|
||||||
|
<>
|
||||||
|
<InputLabel>이벤트 기간</InputLabel>
|
||||||
<SearchPeriod
|
<SearchPeriod
|
||||||
startDate={searchParams.auctionStartDate}
|
startDate={searchParams.startDate}
|
||||||
handleStartDate={date => onSearch({ auctionStartDate: date }, false)}
|
handleStartDate={date => onSearch({ startDate: date }, false)}
|
||||||
endDate={searchParams.auctionEndDate}
|
endDate={searchParams.endDate}
|
||||||
handleEndDate={date => onSearch({ auctionEndDate: date }, false)}
|
handleEndDate={date => onSearch({ endDate: date }, false)}
|
||||||
/>
|
/>
|
||||||
</>,
|
</>,
|
||||||
<></>,<></>,
|
<></>,<></>,
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
import DatePicker, { registerLocale } from 'react-datepicker';
|
|
||||||
import { ko } from 'date-fns/esm/locale';
|
|
||||||
import { getMonth, getYear } from 'date-fns';
|
|
||||||
import range from 'lodash/range';
|
|
||||||
import { months } from '../../assets/data';
|
|
||||||
registerLocale('ko', ko);
|
|
||||||
|
|
||||||
const DatePickerComponent = ({ selectedDate, handleSelectedDate, pastDate, disabled, name, readOnly, maxDate, type }) => {
|
|
||||||
const years = range(1990, getYear(new Date()) + 100, 1);
|
|
||||||
|
|
||||||
const parseDate = (date) => {
|
|
||||||
if (!date) return null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 이미 Date 객체인 경우
|
|
||||||
if (date instanceof Date) {
|
|
||||||
return date;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 문자열인 경우
|
|
||||||
if (typeof date === 'string') {
|
|
||||||
// ISO 형식의 날짜 문자열인 경우 (예: "2025-01-03T15:00:00")
|
|
||||||
if (date.includes('T')) {
|
|
||||||
return new Date(date);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 일반 날짜 문자열인 경우 (예: "2025-01-03")
|
|
||||||
const [year, month, day] = date.split('-').map(num => num.trim());
|
|
||||||
return new Date(year, month - 1, day);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Date parsing error:', error);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const parsedDate = parseDate(selectedDate);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DatePicker
|
|
||||||
onKeyDown={event => {
|
|
||||||
if (event.keyCode === 8) {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
disabled={disabled}
|
|
||||||
readOnly={readOnly}
|
|
||||||
// selected={type !== 'retention' ? '' : parsedDate}
|
|
||||||
selected={parsedDate}
|
|
||||||
onChange={data => handleSelectedDate(data)}
|
|
||||||
className="datepicker"
|
|
||||||
placeholderText={name ? name : '검색기간 선택'}
|
|
||||||
calendarClassName="calendar"
|
|
||||||
dateFormat="yyyy - MM - dd"
|
|
||||||
locale="ko"
|
|
||||||
minDate={pastDate}
|
|
||||||
maxDate={maxDate}
|
|
||||||
renderCustomHeader={({ date, changeYear, changeMonth, decreaseMonth, increaseMonth, prevMonthButtonDisabled, nextMonthButtonDisabled }) => (
|
|
||||||
<div className="calendar-top">
|
|
||||||
<button
|
|
||||||
className="btn-prev"
|
|
||||||
onClick={e => {
|
|
||||||
e.preventDefault();
|
|
||||||
decreaseMonth();
|
|
||||||
}}
|
|
||||||
disabled={prevMonthButtonDisabled}></button>
|
|
||||||
<select value={getYear(date)} onChange={({ target: { value } }) => changeYear(value)}>
|
|
||||||
{years.map(option => (
|
|
||||||
<option key={option} value={option}>
|
|
||||||
{option}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
.
|
|
||||||
<select value={months[getMonth(date)]} onChange={({ target: { value } }) => changeMonth(months.indexOf(value))}>
|
|
||||||
{months.map(option => (
|
|
||||||
<option key={option} value={option}>
|
|
||||||
{option}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
<button
|
|
||||||
className="btn-next"
|
|
||||||
onClick={e => {
|
|
||||||
e.preventDefault();
|
|
||||||
increaseMonth();
|
|
||||||
}}
|
|
||||||
disabled={nextMonthButtonDisabled}></button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DatePickerComponent;
|
|
||||||
@@ -1,171 +0,0 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
import DatePickerComponent from './DatePickerComponent';
|
|
||||||
import { DatePickerWrapper } from '../../styles/Components';
|
|
||||||
import {
|
|
||||||
FormRowGroup,
|
|
||||||
FormLabel,
|
|
||||||
DateTimeGroup, DateTimeWrapper, DateContainer, StyledSelectInput, TimeSeparator, TimeContainer,
|
|
||||||
} from '../../styles/ModuleComponents';
|
|
||||||
import { HourList, MinuteList } from '../../assets/data';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
const DateTimeRangePicker = ({
|
|
||||||
label,
|
|
||||||
startDate,
|
|
||||||
endDate,
|
|
||||||
onStartDateChange,
|
|
||||||
onEndDateChange,
|
|
||||||
pastDate = new Date(),
|
|
||||||
disabled,
|
|
||||||
startLabel = '시작 일자',
|
|
||||||
endLabel = '종료 일자',
|
|
||||||
reset = false,
|
|
||||||
setAlert
|
|
||||||
}) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const [startHour, setStartHour] = useState('00');
|
|
||||||
const [startMin, setStartMin] = useState('00');
|
|
||||||
const [endHour, setEndHour] = useState('00');
|
|
||||||
const [endMin, setEndMin] = useState('00');
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (startDate) {
|
|
||||||
const date = new Date(startDate);
|
|
||||||
setStartHour(String(date.getHours()).padStart(2, '0'));
|
|
||||||
setStartMin(String(date.getMinutes()).padStart(2, '0'));
|
|
||||||
}
|
|
||||||
}, [startDate]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (endDate) {
|
|
||||||
const date = new Date(endDate);
|
|
||||||
setEndHour(String(date.getHours()).padStart(2, '0'));
|
|
||||||
setEndMin(String(date.getMinutes()).padStart(2, '0'));
|
|
||||||
}
|
|
||||||
}, [endDate]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (reset) {
|
|
||||||
setStartHour('00');
|
|
||||||
setStartMin('00');
|
|
||||||
setEndHour('00');
|
|
||||||
setEndMin('00');
|
|
||||||
}
|
|
||||||
}, [reset]);
|
|
||||||
|
|
||||||
const handleStartDate = (date) => {
|
|
||||||
const newDate = new Date(date);
|
|
||||||
newDate.setHours(parseInt(startHour), parseInt(startMin));
|
|
||||||
onStartDateChange(newDate);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEndDate = (date) => {
|
|
||||||
let newDate = new Date(date);
|
|
||||||
newDate.setHours(parseInt(endHour), parseInt(endMin));
|
|
||||||
|
|
||||||
if (startDate && newDate < startDate) {
|
|
||||||
setAlert(t('TIME_START_DIFF_END'));
|
|
||||||
newDate = new Date(startDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
onEndDateChange(newDate);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleStartTime = (e) => {
|
|
||||||
const { id, value } = e.target;
|
|
||||||
const newDate = startDate ? new Date(startDate) : new Date();
|
|
||||||
|
|
||||||
if (id === 'hour') {
|
|
||||||
setStartHour(value);
|
|
||||||
newDate.setHours(parseInt(value), parseInt(startMin));
|
|
||||||
} else {
|
|
||||||
setStartMin(value);
|
|
||||||
newDate.setHours(parseInt(startHour), parseInt(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
onStartDateChange(newDate);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEndTime = (e) => {
|
|
||||||
const { id, value } = e.target;
|
|
||||||
let newDate = endDate ? new Date(endDate) : new Date();
|
|
||||||
|
|
||||||
if (id === 'hour') {
|
|
||||||
setEndHour(value);
|
|
||||||
newDate.setHours(parseInt(value), parseInt(endMin));
|
|
||||||
} else {
|
|
||||||
setEndMin(value);
|
|
||||||
newDate.setHours(parseInt(endHour), parseInt(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startDate && newDate < startDate) {
|
|
||||||
setAlert(t('TIME_START_DIFF_END'));
|
|
||||||
newDate = new Date(startDate)
|
|
||||||
}
|
|
||||||
|
|
||||||
onEndDateChange(newDate);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FormRowGroup>
|
|
||||||
<FormLabel>{label}</FormLabel>
|
|
||||||
<DateTimeWrapper>
|
|
||||||
<DateTimeGroup>
|
|
||||||
<DateContainer>
|
|
||||||
<DatePickerWrapper>
|
|
||||||
<DatePickerComponent
|
|
||||||
name={startLabel}
|
|
||||||
handleSelectedDate={handleStartDate}
|
|
||||||
selectedDate={startDate}
|
|
||||||
pastDate={pastDate}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
</DatePickerWrapper>
|
|
||||||
</DateContainer>
|
|
||||||
<TimeContainer>
|
|
||||||
<StyledSelectInput onChange={handleStartTime} id="hour" value={startHour} disabled={disabled}>
|
|
||||||
{HourList.map(hour => (
|
|
||||||
<option value={hour} key={hour}>{hour}</option>
|
|
||||||
))}
|
|
||||||
</StyledSelectInput>
|
|
||||||
<TimeSeparator>:</TimeSeparator>
|
|
||||||
<StyledSelectInput onChange={handleStartTime} id="min" value={startMin} disabled={disabled}>
|
|
||||||
{MinuteList.map(min => (
|
|
||||||
<option value={min} key={min}>{min}</option>
|
|
||||||
))}
|
|
||||||
</StyledSelectInput>
|
|
||||||
</TimeContainer>
|
|
||||||
</DateTimeGroup>
|
|
||||||
|
|
||||||
<DateTimeGroup>
|
|
||||||
<DateContainer>
|
|
||||||
<DatePickerWrapper>
|
|
||||||
<DatePickerComponent
|
|
||||||
name={endLabel}
|
|
||||||
handleSelectedDate={handleEndDate}
|
|
||||||
selectedDate={endDate}
|
|
||||||
pastDate={pastDate}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
</DatePickerWrapper>
|
|
||||||
</DateContainer>
|
|
||||||
<TimeContainer>
|
|
||||||
<StyledSelectInput onChange={handleEndTime} id="hour" value={endHour} disabled={disabled}>
|
|
||||||
{HourList.map(hour => (
|
|
||||||
<option value={hour} key={hour}>{hour}</option>
|
|
||||||
))}
|
|
||||||
</StyledSelectInput>
|
|
||||||
<TimeSeparator>:</TimeSeparator>
|
|
||||||
<StyledSelectInput onChange={handleEndTime} id="min" value={endMin} disabled={disabled}>
|
|
||||||
{MinuteList.map(min => (
|
|
||||||
<option value={min} key={min}>{min}</option>
|
|
||||||
))}
|
|
||||||
</StyledSelectInput>
|
|
||||||
</TimeContainer>
|
|
||||||
</DateTimeGroup>
|
|
||||||
</DateTimeWrapper>
|
|
||||||
</FormRowGroup>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DateTimeRangePicker;
|
|
||||||
27
src/i18n.js
27
src/i18n.js
@@ -10,6 +10,7 @@ const resources = {
|
|||||||
REGIST_COMPLTE: "등록이 완료되었습니다.",
|
REGIST_COMPLTE: "등록이 완료되었습니다.",
|
||||||
REGIST_FAIL: '등록에 실패하였습니다. 잠시 후 다시 한번 진행해 주세요.',
|
REGIST_FAIL: '등록에 실패하였습니다. 잠시 후 다시 한번 진행해 주세요.',
|
||||||
UPDATE_FAIL: '수정에 실패하였습니다. 잠시 후 다시 한번 진행해 주세요.',
|
UPDATE_FAIL: '수정에 실패하였습니다. 잠시 후 다시 한번 진행해 주세요.',
|
||||||
|
STOP_FAIL: '중단에 실패하였습니다. 잠시 후 다시 한번 진행해 주세요.',
|
||||||
DELETE_FAIL: '삭제에 실패하였습니다. 잠시 후 다시 한번 진행해 주세요.',
|
DELETE_FAIL: '삭제에 실패하였습니다. 잠시 후 다시 한번 진행해 주세요.',
|
||||||
API_FAIL: '처리 중 오류가 발생하였습니다. 잠시 후 다시 한번 진행해 주세요. 오류가 지속될 경우, 담당자에게 문의해주세요.',
|
API_FAIL: '처리 중 오류가 발생하였습니다. 잠시 후 다시 한번 진행해 주세요. 오류가 지속될 경우, 담당자에게 문의해주세요.',
|
||||||
USER_MAIL_DEL_CONFIRM: '해당 우편을 삭제하시겠습니까?',
|
USER_MAIL_DEL_CONFIRM: '해당 우편을 삭제하시겠습니까?',
|
||||||
@@ -20,6 +21,7 @@ const resources = {
|
|||||||
CANCEL_COMPLETED: '취소가 완료되었습니다.',
|
CANCEL_COMPLETED: '취소가 완료되었습니다.',
|
||||||
DEL_CONFIRM: "해당 아이템을 삭제하시겠습니까?",
|
DEL_CONFIRM: "해당 아이템을 삭제하시겠습니까?",
|
||||||
DEL_COMPLETE: '삭제가 완료되었습니다.',
|
DEL_COMPLETE: '삭제가 완료되었습니다.',
|
||||||
|
STOP_COMPLETE: '중단이 완료되었습니다.',
|
||||||
DEL_ITEM_COMPLETE: '아이템 삭제가 완료되었습니다.',
|
DEL_ITEM_COMPLETE: '아이템 삭제가 완료되었습니다.',
|
||||||
REQUIRED_VALUE_CHECK: '필수값을 입력해주세요.',
|
REQUIRED_VALUE_CHECK: '필수값을 입력해주세요.',
|
||||||
UPDATE_COMPLETED: '수정이 완료되었습니다.',
|
UPDATE_COMPLETED: '수정이 완료되었습니다.',
|
||||||
@@ -31,14 +33,19 @@ const resources = {
|
|||||||
EXCEL_SELECT: 'Excel 파일을 선택해주세요.',
|
EXCEL_SELECT: 'Excel 파일을 선택해주세요.',
|
||||||
TIME_NOW_DIFF_START: '현재 시간보다 5분 이전의 시간은 선택할 수 없습니다.',
|
TIME_NOW_DIFF_START: '현재 시간보다 5분 이전의 시간은 선택할 수 없습니다.',
|
||||||
TIME_START_DIFF_END: '시작 시간보다 작을 수 없습니다.',
|
TIME_START_DIFF_END: '시작 시간보다 작을 수 없습니다.',
|
||||||
|
WARNING_GUID_CHECK: 'GUID를 확인해주세요.',
|
||||||
|
WARNING_NICKNAME_CHECK: '닉네임을 확인해주세요.',
|
||||||
|
WARNING_EMAIL_CHECK: '이메일을 확인해주세요.',
|
||||||
|
WARNING_TYPE_CHECK: '타입을 확인해주세요.',
|
||||||
//랜드
|
//랜드
|
||||||
LAND_AUCTION_SELECT_DELETE: "선택된 경매를 삭제하시겠습니까?",
|
LAND_AUCTION_SELECT_DELETE: "선택된 경매를 삭제하시겠습니까?",
|
||||||
LAND_AUCTION_WARNING_DELETE: "대기 상태의 경매만 삭제할 수 있습니다.",
|
LAND_AUCTION_WARNING_DELETE: "대기 상태의 경매만 삭제할 수 있습니다.",
|
||||||
LAND_AUCTION_MODAL_STATUS_WARNING: "경매 시작일시 이후에는 변경이 불가합니다.",
|
LAND_AUCTION_MODAL_STATUS_WARNING: "경매 시작일시 이후에는 변경이 불가합니다.",
|
||||||
LAND_AUCTION_MADEL_RESV_START_WARNING: "예약 시작 시간은 현재 시간으로부터 5분 이후여야 합니다.",
|
LAND_AUCTION_MODEL_RESV_START_WARNING: "예약 시작 시간은 현재 시간으로부터 5분 이후여야 합니다.",
|
||||||
LAND_AUCTION_MADEL_AUCTION_START_WARNING: "경매 시작 시간은 현재 시간으로부터 5분 이후여야 합니다.",
|
LAND_AUCTION_MODEL_AUCTION_START_WARNING: "경매 시작 시간은 현재 시간으로부터 5분 이후여야 합니다.",
|
||||||
LAND_AUCTION_MADEL_AUCTION_DIFF_RESERVATION: "경매 시간은 예약 시간보다 이전으로 설정할 수 없습니다.",
|
LAND_AUCTION_MODEL_AUCTION_DIFF_RESERVATION: "경매 시간은 예약 시간보다 이전으로 설정할 수 없습니다.",
|
||||||
LAND_AUCTION_MADEL_AUCTION_DIFF_AUCTION: "경매 종료일자는 경매 시작일보다 같거나 작을 수 없습니다.",
|
LAND_AUCTION_MODEL_AUCTION_DIFF_AUCTION: "경매 종료일자는 경매 시작일보다 같거나 작을 수 없습니다.",
|
||||||
|
LAND_AUCTION_MODEL_MIN_TIME_WARNING: "경매시간은 최소 15분의 시간이 필요합니다.",
|
||||||
LAND_AUCTION_MADEL_MODIFY_START: "경매가 시작되어 수정할 수 없습니다.",
|
LAND_AUCTION_MADEL_MODIFY_START: "경매가 시작되어 수정할 수 없습니다.",
|
||||||
LAND_AUCTION_DELETE_DATE_WARNING: "경매 시작 3분 전에는 삭제할 수 없습니다.",
|
LAND_AUCTION_DELETE_DATE_WARNING: "경매 시작 3분 전에는 삭제할 수 없습니다.",
|
||||||
LAND_AUCTION_DELETE_STATUS_WARNING: "경매가 시작되거나 종료된 상태는 삭제할 수 없습니다.",
|
LAND_AUCTION_DELETE_STATUS_WARNING: "경매가 시작되거나 종료된 상태는 삭제할 수 없습니다.",
|
||||||
@@ -65,6 +72,7 @@ const resources = {
|
|||||||
MAIL_SELECT_DELETE: "선택된 우편을 삭제하시겠습니까?\r\n삭제시 설정 정보가 제거됩니다.",
|
MAIL_SELECT_DELETE: "선택된 우편을 삭제하시겠습니까?\r\n삭제시 설정 정보가 제거됩니다.",
|
||||||
MAIL_ITEM_ADD_DUPL: '이미 추가된 아이템입니다. 삭제 후 다시 추가해주세요.',
|
MAIL_ITEM_ADD_DUPL: '이미 추가된 아이템입니다. 삭제 후 다시 추가해주세요.',
|
||||||
MAIL_ITEM_ADD_BEN: '첨부 할 수 없는 아이템입니다.',
|
MAIL_ITEM_ADD_BEN: '첨부 할 수 없는 아이템입니다.',
|
||||||
|
MAIL_ITEM_CALIUM_TOTAL_OVER_WARNING: '첨부 가능한 칼리움 수량을 초과 하였습니다.',
|
||||||
MAIL_CANCEL: '우편 등록이 취소되었습니다.',
|
MAIL_CANCEL: '우편 등록이 취소되었습니다.',
|
||||||
//칼리움 요청
|
//칼리움 요청
|
||||||
CHARGE_COMPLTED: '해당 건에 대한 충전 처리가 완료되었습니다.',
|
CHARGE_COMPLTED: '해당 건에 대한 충전 처리가 완료되었습니다.',
|
||||||
@@ -77,7 +85,16 @@ const resources = {
|
|||||||
CHARGE_FINISH_FAIL: '충전 처리가 불가능합니다. 이미 충전이 완료되었거나, 관리자에 의해 요청 건에 대한 취소(반려) 처리된 것입니다. 해당 요청건에 대한 진행 상태를 다시 확인해 주세요.',
|
CHARGE_FINISH_FAIL: '충전 처리가 불가능합니다. 이미 충전이 완료되었거나, 관리자에 의해 요청 건에 대한 취소(반려) 처리된 것입니다. 해당 요청건에 대한 진행 상태를 다시 확인해 주세요.',
|
||||||
SEARCH_LIMIT_FAIL: '인출 가능 수량 조회에 대한 요청 중 오류가 발생하였습니다. 잠시 후 다시 한번 진행해 주세요. 오류가 지속될 경우, 담당자에게 문의해주세요.',
|
SEARCH_LIMIT_FAIL: '인출 가능 수량 조회에 대한 요청 중 오류가 발생하였습니다. 잠시 후 다시 한번 진행해 주세요. 오류가 지속될 경우, 담당자에게 문의해주세요.',
|
||||||
//전투시스템
|
//전투시스템
|
||||||
BATTLE_EVENT_MADEL_START_DT_WARNING: "시작 시간은 현재 시간으로부터 10분 이후부터 가능합니다.",
|
BATTLE_EVENT_MODAL_START_DT_WARNING: "시작 시간은 현재 시간으로부터 10분 이후부터 가능합니다.",
|
||||||
|
BATTLE_EVENT_MODAL_START_DIFF_END_WARNING :"종료일은 시작일보다 하루 이후여야 합니다.",
|
||||||
|
BATTLE_EVENT_MODAL_TIME_CHECK_WARNING :"해당 시간에 속하는 이벤트가 존재합니다.",
|
||||||
|
BATTLE_EVENT_REGIST_CONFIRM: "랜드 경매를 등록하시겠습니까?",
|
||||||
|
BATTLE_EVENT_UPDATE_CONFIRM: "랜드 경매를 수정하시겠습니까?",
|
||||||
|
BATTLE_EVENT_SELECT_DELETE: "선택된 이벤트를 삭제하시겠습니까?",
|
||||||
|
BATTLE_EVENT_SELECT_STOP: "선택된 이벤트를 중단하시겠습니까?",
|
||||||
|
BATTLE_EVENT_STOP_5MINUTES_DATE_WARNING: "이벤트 시작 5분 전에는 중단할 수 없습니다.",
|
||||||
|
BATTLE_EVENT_STATUS_RUNNING_WARNING: "이벤트 진행중에는 중단할 수 없습니다.",
|
||||||
|
BATTLE_EVENT_MODAL_STATUS_WARNING: "이벤트가 중단일때만 수정이 가능합니다.",
|
||||||
//파일명칭
|
//파일명칭
|
||||||
FILE_INDEX_USER_CONTENT: 'Caliverse_User_Index.xlsx',
|
FILE_INDEX_USER_CONTENT: 'Caliverse_User_Index.xlsx',
|
||||||
FILE_CALIUM_REQUEST: 'Caliverse_Calium_Request.xlsx',
|
FILE_CALIUM_REQUEST: 'Caliverse_Calium_Request.xlsx',
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import 'react-datepicker/dist/react-datepicker.css';
|
|||||||
import {
|
import {
|
||||||
BattleConfigView,
|
BattleConfigView,
|
||||||
BattleEventDelete,
|
BattleEventDelete,
|
||||||
BattleEventDetailView,
|
BattleEventDetailView, BattleEventStop,
|
||||||
BattleEventView,
|
BattleEventView,
|
||||||
BattleRewardView,
|
BattleRewardView,
|
||||||
} from '../../apis/Battle';
|
} from '../../apis/Battle';
|
||||||
@@ -28,17 +28,17 @@ import {
|
|||||||
Pagination,
|
Pagination,
|
||||||
ViewTableInfo, ExcelDownButton,
|
ViewTableInfo, ExcelDownButton,
|
||||||
} from '../../components/common';
|
} from '../../components/common';
|
||||||
import { convertKTC, timeDiffMinute } from '../../utils';
|
import { convertKTC, convertKTCDate, convertUTC, timeDiffMinute } from '../../utils';
|
||||||
import { BattleEventModal, LandAuctionModal, LandAuctionSearchBar } from '../../components/ServiceManage';
|
import { BattleEventModal } from '../../components/ServiceManage';
|
||||||
import { INITIAL_PAGE_SIZE, INITIAL_PAGE_LIMIT } from '../../assets/data/adminConstants';
|
import { INITIAL_PAGE_SIZE, INITIAL_PAGE_LIMIT } from '../../assets/data/adminConstants';
|
||||||
import { useDataFetch, useModal, useTable, withAuth } from '../../utils/hook';
|
import { useDataFetch, useModal, useTable, withAuth } from '../../utils/hook';
|
||||||
import { useLandAuctionSearch } from '../../components/ServiceManage/searchBar/LandAuctionSearchBar';
|
|
||||||
import { StatusWapper, StatusLabel } from '../../styles/ModuleComponents';
|
import { StatusWapper, StatusLabel } from '../../styles/ModuleComponents';
|
||||||
import { battleEventStatus, battleRepeatType } from '../../assets/data/options';
|
import { battleEventStatus, battleRepeatType } from '../../assets/data/options';
|
||||||
import BattleEventSearchBar, {
|
import BattleEventSearchBar, {
|
||||||
useBattleEventSearch,
|
useBattleEventSearch,
|
||||||
} from '../../components/ServiceManage/searchBar/BattleEventSearchBar';
|
} from '../../components/ServiceManage/searchBar/BattleEventSearchBar';
|
||||||
import { getTimeOnly } from '../../utils/date';
|
import { getDateOnly, getTimeOnly, secondToMinutes } from '../../utils/date';
|
||||||
|
import { battleEventStatusType } from '../../assets/data/types';
|
||||||
|
|
||||||
const BattleEvent = () => {
|
const BattleEvent = () => {
|
||||||
const token = sessionStorage.getItem('token');
|
const token = sessionStorage.getItem('token');
|
||||||
@@ -53,6 +53,8 @@ const BattleEvent = () => {
|
|||||||
handleModalView,
|
handleModalView,
|
||||||
handleModalClose
|
handleModalClose
|
||||||
} = useModal({
|
} = useModal({
|
||||||
|
stopConfirm: 'hidden',
|
||||||
|
stopComplete: 'hidden',
|
||||||
detail: 'hidden',
|
detail: 'hidden',
|
||||||
deleteConfirm: 'hidden',
|
deleteConfirm: 'hidden',
|
||||||
deleteComplete: 'hidden'
|
deleteComplete: 'hidden'
|
||||||
@@ -85,6 +87,41 @@ const BattleEvent = () => {
|
|||||||
data: battleRewardData
|
data: battleRewardData
|
||||||
} = useDataFetch(() => BattleRewardView(token), [token]);
|
} = useDataFetch(() => BattleRewardView(token), [token]);
|
||||||
|
|
||||||
|
const endTime = (start_dt, operation_time) =>{
|
||||||
|
const startDate = new Date(start_dt);
|
||||||
|
|
||||||
|
startDate.setSeconds(startDate.getSeconds() + operation_time);
|
||||||
|
|
||||||
|
return startDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isStopMinutes = (time) => {
|
||||||
|
const givenDate = new Date(time);
|
||||||
|
|
||||||
|
const currentDate = convertUTC(new Date());
|
||||||
|
|
||||||
|
// 시간만 비교하기 위해 년,월,일을 동일하게 설정
|
||||||
|
givenDate.setFullYear(currentDate.getFullYear());
|
||||||
|
givenDate.setMonth(currentDate.getMonth());
|
||||||
|
givenDate.setDate(currentDate.getDate());
|
||||||
|
|
||||||
|
// 두 시간의 차이를 밀리초로 계산
|
||||||
|
const timeDifference = currentDate.getTime() - givenDate.getTime();
|
||||||
|
|
||||||
|
// 밀리초로 변환
|
||||||
|
const fiveMinutesInMs = 5 * 60 * 1000;
|
||||||
|
|
||||||
|
return timeDifference < 0 && Math.abs(timeDifference) <= fiveMinutesInMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isRunningTime = (time, operation_time) =>{
|
||||||
|
const startDate = new Date(time);
|
||||||
|
const endDate = new Date(startDate.getTime() + (operation_time * 1000));
|
||||||
|
const currentDate = convertUTC(new Date());
|
||||||
|
|
||||||
|
return currentDate >= startDate && currentDate <= endDate;
|
||||||
|
}
|
||||||
|
|
||||||
const handleModalSubmit = async (type, param = null) => {
|
const handleModalSubmit = async (type, param = null) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "regist":
|
case "regist":
|
||||||
@@ -112,6 +149,41 @@ const BattleEvent = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
handleModalView('deleteConfirm');
|
handleModalView('deleteConfirm');
|
||||||
|
break;
|
||||||
|
case "stop":
|
||||||
|
const select_item = selectedRows[0];
|
||||||
|
if(select_item.status === battleEventStatusType.running){
|
||||||
|
setAlertMsg(t('BATTLE_EVENT_STATUS_RUNNING_WARNING'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const isStopTimeCheck = isStopMinutes(select_item.event_start_dt);
|
||||||
|
if(isStopTimeCheck){
|
||||||
|
setAlertMsg(t('BATTLE_EVENT_STOP_5MINUTES_DATE_WARNING'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(isRunningTime(select_item.event_start_dt, select_item.event_operation_time)){
|
||||||
|
setAlertMsg(t('BATTLE_EVENT_STATUS_RUNNING_WARNING'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleModalView('stopConfirm');
|
||||||
|
break;
|
||||||
|
case "stopConfirm":
|
||||||
|
const stop_item = selectedRows[0];
|
||||||
|
|
||||||
|
await BattleEventStop(token, stop_item.id, stop_item).then(data => {
|
||||||
|
handleModalClose('stopConfirm');
|
||||||
|
if(data.result === "SUCCESS") {
|
||||||
|
handleModalView('stopComplete');
|
||||||
|
}else if(data.result === "ERROR_BATTLE_EVENT_STATUS_START_IMPOSSIBLE"){
|
||||||
|
setAlertMsg(t('BATTLE_EVENT_STATUS_RUNNING_WARNING'));
|
||||||
|
}else{
|
||||||
|
setAlertMsg(t('STOP_FAIL'));
|
||||||
|
}
|
||||||
|
}).catch(reason => {
|
||||||
|
setAlertMsg(t('API_FAIL'));
|
||||||
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "deleteConfirm":
|
case "deleteConfirm":
|
||||||
let list = [];
|
let list = [];
|
||||||
@@ -147,7 +219,10 @@ const BattleEvent = () => {
|
|||||||
break;
|
break;
|
||||||
case "deleteComplete":
|
case "deleteComplete":
|
||||||
handleModalClose('deleteComplete');
|
handleModalClose('deleteComplete');
|
||||||
// fetchData(option);
|
window.location.reload();
|
||||||
|
break;
|
||||||
|
case "stopComplete":
|
||||||
|
handleModalClose('stopComplete');
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
break;
|
break;
|
||||||
case "warning":
|
case "warning":
|
||||||
@@ -170,12 +245,17 @@ const BattleEvent = () => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onReset={handleReset}
|
onReset={handleReset}
|
||||||
|
configData={battleConfigData}
|
||||||
|
rewardData={battleRewardData}
|
||||||
/>
|
/>
|
||||||
</FormWrapper>
|
</FormWrapper>
|
||||||
<ViewTableInfo total={dataList?.total} total_all={dataList?.total_all} handleOrderBy={handleOrderByChange} handlePageSize={handlePageSizeChange}>
|
<ViewTableInfo total={dataList?.total} total_all={dataList?.total_all} handleOrderBy={handleOrderByChange} handlePageSize={handlePageSizeChange}>
|
||||||
<ExcelDownButton tableRef={tableRef} fileName={t('FILE_BATTLE_EVENT')} />
|
<ExcelDownButton tableRef={tableRef} fileName={t('FILE_BATTLE_EVENT')} />
|
||||||
|
{/*{userInfo.auth_list?.some(auth => auth.id === authType.battleEventDelete) && (*/}
|
||||||
|
{/* <Button theme={selectedRows.length === 0 ? 'disable' : 'line'} text="이벤트 삭제" handleClick={() => handleModalSubmit('delete')} />*/}
|
||||||
|
{/*)}*/}
|
||||||
{userInfo.auth_list?.some(auth => auth.id === authType.battleEventDelete) && (
|
{userInfo.auth_list?.some(auth => auth.id === authType.battleEventDelete) && (
|
||||||
<Button theme={selectedRows.length === 0 ? 'disable' : 'line'} text="이벤트 중단" handleClick={() => handleModalSubmit('delete')} />
|
<Button theme={selectedRows.length === 0 ? 'disable' : 'line'} text="이벤트 중단" handleClick={() => handleModalSubmit('stop')} />
|
||||||
)}
|
)}
|
||||||
{userInfo.auth_list?.some(auth => auth.id === authType.battleEventUpdate) && (
|
{userInfo.auth_list?.some(auth => auth.id === authType.battleEventUpdate) && (
|
||||||
<Button
|
<Button
|
||||||
@@ -193,17 +273,18 @@ const BattleEvent = () => {
|
|||||||
<tr>
|
<tr>
|
||||||
<th width="40"></th>
|
<th width="40"></th>
|
||||||
<th width="90">그룹</th>
|
<th width="90">그룹</th>
|
||||||
<th width="60">이벤트 ID</th>
|
<th width="70">이벤트 ID</th>
|
||||||
<th width="150">이벤트명</th>
|
<th width="200">이벤트명</th>
|
||||||
<th width="80">반복</th>
|
<th width="80">반복</th>
|
||||||
<th width="120">이벤트 시작시간</th>
|
<th width="100">기간 시작일(KST)</th>
|
||||||
<th width="120">이벤트 종료시간</th>
|
<th width="100">기간 종료일(KST)</th>
|
||||||
|
<th width="100">이벤트 시작시간(KST)</th>
|
||||||
|
<th width="100">이벤트 종료시간(KST)</th>
|
||||||
<th width="90">이벤트 상태</th>
|
<th width="90">이벤트 상태</th>
|
||||||
<th width="90">라운드 시간</th>
|
<th width="90">라운드 시간</th>
|
||||||
<th width="80">라운드 수</th>
|
<th width="90">배정포드</th>
|
||||||
<th width="80">핫타임</th>
|
<th width="70">라운드 수</th>
|
||||||
<th width="200">기간 시작일</th>
|
<th width="70">핫타임</th>
|
||||||
<th width="200">기간 종료일</th>
|
|
||||||
<th width="100">확인 / 수정</th>
|
<th width="100">확인 / 수정</th>
|
||||||
<th width="150">히스토리</th>
|
<th width="150">히스토리</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -217,25 +298,26 @@ const BattleEvent = () => {
|
|||||||
checked={isRowSelected(battle.id)} />
|
checked={isRowSelected(battle.id)} />
|
||||||
</td>
|
</td>
|
||||||
<td>{battle.group_id}</td>
|
<td>{battle.group_id}</td>
|
||||||
<td>{battle.id}</td>
|
<td>{battle.event_id}</td>
|
||||||
<td>{battle.event_name}</td>
|
<td>{battle.event_name}</td>
|
||||||
<StatusWapper>
|
<StatusWapper>
|
||||||
<StatusLabel $status={battle.repeat_type}>
|
<StatusLabel $status={battle.repeat_type}>
|
||||||
{battleRepeatType.find(data => data.value === battle.repeat_type).name}
|
{battleRepeatType.find(data => data.value === battle.repeat_type).name}
|
||||||
</StatusLabel>
|
</StatusLabel>
|
||||||
</StatusWapper>
|
</StatusWapper>
|
||||||
<td>{getTimeOnly(battle.event_start_dt)}</td>
|
<td>{getDateOnly(convertKTCDate(battle.event_start_dt))}</td>
|
||||||
<td>{battle.end_time}</td>
|
<td>{getDateOnly(battle.event_end_dt)}</td>
|
||||||
|
<td>{getTimeOnly(convertKTCDate(battle.event_start_dt))}</td>
|
||||||
|
<td>{getTimeOnly(endTime(convertKTCDate(battle.event_start_dt), battle.event_operation_time))}</td>
|
||||||
<StatusWapper>
|
<StatusWapper>
|
||||||
<StatusLabel $status={battle.status}>
|
<StatusLabel $status={battle.status}>
|
||||||
{battleEventStatus.find(data => data.value === battle.status).name}
|
{battleEventStatus.find(data => data.value === battle.status).name}
|
||||||
</StatusLabel>
|
</StatusLabel>
|
||||||
</StatusWapper>
|
</StatusWapper>
|
||||||
<td>{battle.round_time}</td>
|
<td>{secondToMinutes(battle.round_time)}분</td>
|
||||||
|
<td>{battle.reward_group_id}</td>
|
||||||
<td>{battle.round_count}</td>
|
<td>{battle.round_count}</td>
|
||||||
<td>{battle.hot_time}</td>
|
<td>{battle.hot_time}</td>
|
||||||
<td>{convertKTC(battle.event_start_dt)}</td>
|
|
||||||
<td>{convertKTC(battle.event_end_dt)}</td>
|
|
||||||
<td>
|
<td>
|
||||||
<Button theme="line" text="상세보기"
|
<Button theme="line" text="상세보기"
|
||||||
handleClick={e => handleModalSubmit('detail', battle.id)} />
|
handleClick={e => handleModalSubmit('detail', battle.id)} />
|
||||||
@@ -252,13 +334,28 @@ const BattleEvent = () => {
|
|||||||
{/*상세*/}
|
{/*상세*/}
|
||||||
<BattleEventModal modalType={modalType} detailView={modalState.detailModal} handleDetailView={() => handleModalClose('detail')} content={detailData} setDetailData={setDetailData} configData={battleConfigData} rewardData={battleRewardData} />
|
<BattleEventModal modalType={modalType} detailView={modalState.detailModal} handleDetailView={() => handleModalClose('detail')} content={detailData} setDetailData={setDetailData} configData={battleConfigData} rewardData={battleRewardData} />
|
||||||
|
|
||||||
|
{/*중단 확인*/}
|
||||||
|
<DynamicModal
|
||||||
|
modalType={modalTypes.confirmOkCancel}
|
||||||
|
view={modalState.stopConfirmModal}
|
||||||
|
handleCancel={() => handleModalClose('stopConfirm')}
|
||||||
|
handleSubmit={() => handleModalSubmit('stopConfirm')}
|
||||||
|
modalText={t('BATTLE_EVENT_SELECT_STOP')}
|
||||||
|
/>
|
||||||
|
{/*중단 완료*/}
|
||||||
|
<DynamicModal
|
||||||
|
modalType={modalTypes.completed}
|
||||||
|
view={modalState.stopCompleteModal}
|
||||||
|
handleSubmit={() => handleModalSubmit('stopComplete')}
|
||||||
|
modalText={t('STOP_COMPLETE')}
|
||||||
|
/>
|
||||||
{/*삭제 확인*/}
|
{/*삭제 확인*/}
|
||||||
<DynamicModal
|
<DynamicModal
|
||||||
modalType={modalTypes.confirmOkCancel}
|
modalType={modalTypes.confirmOkCancel}
|
||||||
view={modalState.deleteConfirmModal}
|
view={modalState.deleteConfirmModal}
|
||||||
handleCancel={() => handleModalClose('deleteConfirm')}
|
handleCancel={() => handleModalClose('deleteConfirm')}
|
||||||
handleSubmit={() => handleModalSubmit('deleteConfirm')}
|
handleSubmit={() => handleModalSubmit('deleteConfirm')}
|
||||||
modalText={t('LAND_AUCTION_SELECT_DELETE')}
|
modalText={t('BATTLE_EVENT_SELECT_DELETE')}
|
||||||
/>
|
/>
|
||||||
{/*삭제 완료*/}
|
{/*삭제 완료*/}
|
||||||
<DynamicModal
|
<DynamicModal
|
||||||
|
|||||||
@@ -140,7 +140,6 @@ const LandAuction = () => {
|
|||||||
break;
|
break;
|
||||||
case "deleteComplete":
|
case "deleteComplete":
|
||||||
handleModalClose('deleteComplete');
|
handleModalClose('deleteComplete');
|
||||||
// fetchData(option);
|
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
break;
|
break;
|
||||||
case "warning":
|
case "warning":
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import { Title, BtnWrapper, TextInput, SelectInput, Label, InputLabel, DatePicke
|
|||||||
import IconDelete from '../../assets/img/icon/icon-delete.png';
|
import IconDelete from '../../assets/img/icon/icon-delete.png';
|
||||||
import CloseIcon from '../../assets/img/icon/icon-close.png';
|
import CloseIcon from '../../assets/img/icon/icon-close.png';
|
||||||
|
|
||||||
import { HourList, MinuteList, wellType } from '../../assets/data';
|
import { HourList, MinuteList, modalTypes, wellType } from '../../assets/data';
|
||||||
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import MailRegistUploadBtn from '../../components/ServiceManage/MailRegistUploadBtn';
|
import MailRegistUploadBtn from '../../components/ServiceManage/MailRegistUploadBtn';
|
||||||
import DatePickerComponent from '../../components/common/Date/DatePickerComponent';
|
import DatePickerComponent from '../../components/common/Date/DatePickerComponent';
|
||||||
import Modal from '../../components/common/modal/Modal';
|
import Modal from '../../components/common/modal/Modal';
|
||||||
import { MailIsItem, MailMultiRegsit, MailSingleRegist } from '../../apis';
|
import { MailCaliumTotalView, MailIsItem, MailMultiRegsit, MailSingleRegist } from '../../apis';
|
||||||
|
|
||||||
import { authList } from '../../store/authList';
|
import { authList } from '../../store/authList';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
@@ -24,12 +24,17 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { MailReceiver, RegistInputRow } from '../../styles/ModuleComponents';
|
import { MailReceiver, RegistInputRow } from '../../styles/ModuleComponents';
|
||||||
import AuthModal from '../../components/common/modal/AuthModal';
|
import AuthModal from '../../components/common/modal/AuthModal';
|
||||||
import { authType } from '../../assets/data';
|
import { authType } from '../../assets/data';
|
||||||
|
import { useDataFetch } from '../../utils/hook';
|
||||||
|
import { BattleConfigView } from '../../apis/Battle';
|
||||||
|
import { currencyCodeTypes } from '../../assets/data/types';
|
||||||
|
import { DynamicModal } from '../../components/common';
|
||||||
|
|
||||||
const MailRegist = () => {
|
const MailRegist = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const userInfo = useRecoilValue(authList);
|
const userInfo = useRecoilValue(authList);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const environment = process.env.REACT_APP_ENV;
|
const environment = process.env.REACT_APP_ENV;
|
||||||
|
const token = sessionStorage.getItem('token');
|
||||||
|
|
||||||
const [doubleSubmitFlag, setDoubleSubmitFlag] = useState(false);
|
const [doubleSubmitFlag, setDoubleSubmitFlag] = useState(false);
|
||||||
|
|
||||||
@@ -55,6 +60,11 @@ const MailRegist = () => {
|
|||||||
const [confirmText, setConfirmText] = useState('');
|
const [confirmText, setConfirmText] = useState('');
|
||||||
const [alertMessage, setAlertMessage] = useState('');
|
const [alertMessage, setAlertMessage] = useState('');
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [alertMsg, setAlertMsg] = useState('');
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: caliumTotalData
|
||||||
|
} = useDataFetch(() => MailCaliumTotalView(token), [token]);
|
||||||
|
|
||||||
const [resultData, setResultData] = useState({
|
const [resultData, setResultData] = useState({
|
||||||
is_reserve: false,
|
is_reserve: false,
|
||||||
@@ -109,7 +119,7 @@ const MailRegist = () => {
|
|||||||
}
|
}
|
||||||
item.length === 0 || itemCount.length === 0 ? setIsItemNullValue(true) : setIsItemNullValue(false);
|
item.length === 0 || itemCount.length === 0 ? setIsItemNullValue(true) : setIsItemNullValue(false);
|
||||||
|
|
||||||
const token = sessionStorage.getItem('token');
|
// const token = sessionStorage.getItem('token');
|
||||||
const result = await MailIsItem(token, {item: item});
|
const result = await MailIsItem(token, {item: item});
|
||||||
|
|
||||||
if(result.data.result === "ERROR"){
|
if(result.data.result === "ERROR"){
|
||||||
@@ -183,8 +193,20 @@ const MailRegist = () => {
|
|||||||
|
|
||||||
if (itemIndex !== -1) {
|
if (itemIndex !== -1) {
|
||||||
const item_cnt = resultData.item_list[itemIndex].item_cnt;
|
const item_cnt = resultData.item_list[itemIndex].item_cnt;
|
||||||
|
if(resource === currencyCodeTypes.calium){
|
||||||
|
if((Number(resourceCount) + Number(item_cnt)) > caliumTotalData){
|
||||||
|
setAlertMsg(t('MAIL_ITEM_CALIUM_TOTAL_OVER_WARNING'))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
resultData.item_list[itemIndex].item_cnt = Number(item_cnt) + Number(resourceCount);
|
resultData.item_list[itemIndex].item_cnt = Number(item_cnt) + Number(resourceCount);
|
||||||
} else {
|
} else {
|
||||||
|
if(resource === currencyCodeTypes.calium){
|
||||||
|
if(Number(resourceCount) > caliumTotalData){
|
||||||
|
setAlertMsg(t('MAIL_ITEM_CALIUM_TOTAL_OVER_WARNING'))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
const name = wellType.find(well => well.value === resource).name;
|
const name = wellType.find(well => well.value === resource).name;
|
||||||
const newItem = { item: resource, item_cnt: resourceCount, item_name: name };
|
const newItem = { item: resource, item_cnt: resourceCount, item_name: name };
|
||||||
resultData.item_list.push(newItem);
|
resultData.item_list.push(newItem);
|
||||||
@@ -266,19 +288,33 @@ const MailRegist = () => {
|
|||||||
|
|
||||||
const handleRegistMail = async () => {
|
const handleRegistMail = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const token = sessionStorage.getItem('token');
|
await MailSingleRegist(token, resultData).then(data => {
|
||||||
const message = await MailSingleRegist(token, resultData);
|
|
||||||
|
|
||||||
if (message.data.data.message === t('EXCEL_SELECT')) {
|
|
||||||
setConfirmText('파일 내 중복된 유저 정보가 있습니다. \n 파일을 다시 확인 후 이용해주세요.');
|
|
||||||
} else if (message.data.data.message === '저장 하였습니다.') {
|
|
||||||
setConfirmText('우편이 정상 등록되었습니다.');
|
|
||||||
} else {
|
|
||||||
setConfirmText(message.data.data.message);
|
|
||||||
}
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
handleCompleteModal();
|
|
||||||
handleSubmitModal();
|
handleSubmitModal();
|
||||||
|
console.log(data);
|
||||||
|
if(data.result === "ERROR"){
|
||||||
|
if(data.data.message === "ERROR_MAIL_ITEM_CALIUM_OVER"){
|
||||||
|
setAlertMsg(t('MAIL_ITEM_CALIUM_TOTAL_OVER_WARNING'));
|
||||||
|
}else if(data.data.message === "NOT_EXIT_EXCEL"){
|
||||||
|
setAlertMsg(t('EXCEL_SELECT'));
|
||||||
|
}else if(data.data.message === "GUID_CHECK"){
|
||||||
|
setAlertMsg(t('WARNING_GUID_CHECK'));
|
||||||
|
}else if(data.data.message === "NICKNAME_CHECK"){
|
||||||
|
setAlertMsg(t('WARNING_NICKNAME_CHECK'));
|
||||||
|
}else if(data.data.message === "EMAIL_CHECK"){
|
||||||
|
setAlertMsg(t('WARNING_EMAIL_CHECK'));
|
||||||
|
}else if(data.data.message === "USERTYPE_CHECK_EXCEL") {
|
||||||
|
setAlertMsg(t('WARNING_TYPE_CHECK'));
|
||||||
|
}else{
|
||||||
|
setAlertMsg(data.data.message);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
setConfirmText('우편이 정상 등록되었습니다.');
|
||||||
|
handleCompleteModal();
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
setAlertMsg(t('API_FAIL'));
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSingleBtn = () => {
|
const handleSingleBtn = () => {
|
||||||
@@ -524,9 +560,11 @@ const MailRegist = () => {
|
|||||||
<option value="19010001">골드</option>
|
<option value="19010001">골드</option>
|
||||||
<option value="19010002">사파이어</option>
|
<option value="19010002">사파이어</option>
|
||||||
<option value="19010005">루비</option>
|
<option value="19010005">루비</option>
|
||||||
|
<option value="19010003">칼리움</option>
|
||||||
</SelectInput>
|
</SelectInput>
|
||||||
<TextInput placeholder="수량" type="number" value={resourceCount} onChange={e => handleResourceCount(e)} width="200px" />
|
<TextInput placeholder="수량" type="number" value={resourceCount} onChange={e => handleResourceCount(e)} width="200px" />
|
||||||
<Button text="추가" theme={resourceCount.length === 0 || resource.length === 0 ? 'disable' : 'search'} handleClick={handleResourceList} width="100px" height="35px" />
|
<Button text="추가" theme={resourceCount.length === 0 || resource.length === 0 ? 'disable' : 'search'} handleClick={handleResourceList} width="100px" height="35px" />
|
||||||
|
{resource === currencyCodeTypes.calium && <Label>(잔여 수량: {caliumTotalData})</Label>}
|
||||||
</InputItem>
|
</InputItem>
|
||||||
{isItemNullValue && <SearchBarAlert $marginTop="15px">필수값을 입력해주세요.</SearchBarAlert>}
|
{isItemNullValue && <SearchBarAlert $marginTop="15px">필수값을 입력해주세요.</SearchBarAlert>}
|
||||||
|
|
||||||
@@ -588,10 +626,7 @@ const MailRegist = () => {
|
|||||||
type="submit"
|
type="submit"
|
||||||
size="large"
|
size="large"
|
||||||
width="100%"
|
width="100%"
|
||||||
handleClick={() => {
|
handleClick={() => {handleRegistMail();}}
|
||||||
doubleSubmitFlag || handleRegistMail();
|
|
||||||
setDoubleSubmitFlag(true);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</BtnWrapper>
|
</BtnWrapper>
|
||||||
</Modal>
|
</Modal>
|
||||||
@@ -630,6 +665,13 @@ const MailRegist = () => {
|
|||||||
/>
|
/>
|
||||||
</BtnWrapper>
|
</BtnWrapper>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
{/* 경고 모달 */}
|
||||||
|
<DynamicModal
|
||||||
|
modalType={modalTypes.completed}
|
||||||
|
view={alertMsg ? 'view' : 'hidden'}
|
||||||
|
modalText={alertMsg}
|
||||||
|
handleSubmit={() => setAlertMsg('')}
|
||||||
|
/>
|
||||||
{loading && <Loading/>}
|
{loading && <Loading/>}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { Title, BtnWrapper, TextInput, SelectInput, DatePickerWrapper, ButtonClo
|
|||||||
import Modal from '../../components/common/modal/Modal';
|
import Modal from '../../components/common/modal/Modal';
|
||||||
import DatePickerComponent from '../../components/common/Date/DatePickerComponent';
|
import DatePickerComponent from '../../components/common/Date/DatePickerComponent';
|
||||||
|
|
||||||
import { blockPeriod, blockSanctions, blockType, HourList, MinuteList } from '../../assets/data';
|
import { authType, blockPeriod, blockSanctions, blockType, HourList, MinuteList } from '../../assets/data';
|
||||||
import DatePicker, { registerLocale } from 'react-datepicker';
|
import DatePicker, { registerLocale } from 'react-datepicker';
|
||||||
import { ko } from 'date-fns/esm/locale';
|
import { ko } from 'date-fns/esm/locale';
|
||||||
import 'react-datepicker/dist/react-datepicker.css';
|
import 'react-datepicker/dist/react-datepicker.css';
|
||||||
@@ -21,6 +21,7 @@ import { BlackListRegist, BlackListMultipleUpload } from '../../apis';
|
|||||||
|
|
||||||
import { authList } from '../../store/authList';
|
import { authList } from '../../store/authList';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import AuthModal from '../../components/common/modal/AuthModal';
|
||||||
|
|
||||||
registerLocale('ko', ko);
|
registerLocale('ko', ko);
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ const UserBlockRegist = () => {
|
|||||||
const [guidList, setGuidList] = useState([]);
|
const [guidList, setGuidList] = useState([]);
|
||||||
const [typeError, setTypeError] = useState(true);
|
const [typeError, setTypeError] = useState(true);
|
||||||
const [resultData, setResultData] = useState({
|
const [resultData, setResultData] = useState({
|
||||||
list: { guid: '' },
|
list: [{ guid: '' }],
|
||||||
type: '',
|
type: '',
|
||||||
sanctions: '',
|
sanctions: '',
|
||||||
period: '',
|
period: '',
|
||||||
@@ -66,7 +67,7 @@ const UserBlockRegist = () => {
|
|||||||
|
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
setResultData({
|
setResultData({
|
||||||
list: { guid: '' },
|
list: [{ guid: '' }],
|
||||||
type: '',
|
type: '',
|
||||||
sanctions: '',
|
sanctions: '',
|
||||||
period: '',
|
period: '',
|
||||||
@@ -124,7 +125,7 @@ const UserBlockRegist = () => {
|
|||||||
|
|
||||||
const result = new Date(sendDate.getFullYear(), sendDate.getMonth(), sendDate.getDate(), e.target.id === 'hour' ? e.target.value : sendHour, e.target.id === 'min' ? e.target.value : sendMin);
|
const result = new Date(sendDate.getFullYear(), sendDate.getMonth(), sendDate.getDate(), e.target.id === 'hour' ? e.target.value : sendHour, e.target.id === 'min' ? e.target.value : sendMin);
|
||||||
|
|
||||||
const blockDay = resultData.period.slice(1) > 0 ? Number(resultData.period.slice(1)) + 1 : 0;
|
const blockDay = resultData.period.slice(1) > 0 ? Number(resultData.period.slice(1)) : 0;
|
||||||
const permanentDay = 2999 - sendDate.getFullYear();
|
const permanentDay = 2999 - sendDate.getFullYear();
|
||||||
|
|
||||||
if (e.target.id === 'hour') setSendHour(e.target.value);
|
if (e.target.id === 'hour') setSendHour(e.target.value);
|
||||||
@@ -264,20 +265,8 @@ const UserBlockRegist = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{userInfo.auth_list && !userInfo.auth_list.some(auth => auth.id === 25) ? (
|
{userInfo.auth_list && !userInfo.auth_list.some(auth => auth.id === authType.blackListUpdate) ? (
|
||||||
<Modal min="440px" $padding="40px" $bgcolor="transparent" $view={'view'}>
|
<AuthModal/>
|
||||||
<BtnWrapper $justify="flex-end">
|
|
||||||
<ButtonClose onClick={() => navigate(-1)} />
|
|
||||||
</BtnWrapper>
|
|
||||||
<ModalText $align="center">
|
|
||||||
해당 메뉴에 대한 등록 권한이 없습니다.
|
|
||||||
<br />
|
|
||||||
권한 등급을 변경 후 다시 이용해주세요.
|
|
||||||
</ModalText>
|
|
||||||
<BtnWrapper $gap="10px">
|
|
||||||
<Button text="확인" theme="primary" type="submit" size="large" width="100%" handleClick={() => navigate(-1)} />
|
|
||||||
</BtnWrapper>
|
|
||||||
</Modal>
|
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Title>이용자 제재 등록</Title>
|
<Title>이용자 제재 등록</Title>
|
||||||
@@ -291,7 +280,7 @@ const UserBlockRegist = () => {
|
|||||||
placeholder="GUID 입력"
|
placeholder="GUID 입력"
|
||||||
width="400px"
|
width="400px"
|
||||||
disabled={selectSingle}
|
disabled={selectSingle}
|
||||||
value={resultData.list.guid}
|
value={resultData.list[0]?.guid || ''}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
let list = [];
|
let list = [];
|
||||||
list.push({ guid: e.target.value });
|
list.push({ guid: e.target.value });
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export const convertKTC = (dt, nation = true) => {
|
|||||||
timeZone: 'Asia/Seoul',
|
timeZone: 'Asia/Seoul',
|
||||||
};
|
};
|
||||||
|
|
||||||
return nation ? date.toLocaleString('ko-KR', options) + " KTC" : date.toLocaleString('ko-KR', options);
|
return nation ? date.toLocaleString('ko-KR', options) + " KST" : date.toLocaleString('ko-KR', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const convertKTCDate = (dt) => {
|
export const convertKTCDate = (dt) => {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { ONE_MINUTE_MS, ONE_MINUTE_SECOND } from '../assets/data/adminConstants';
|
||||||
|
|
||||||
export const convertStartDateToISO = (date) => {
|
export const convertStartDateToISO = (date) => {
|
||||||
if (!date) return null;
|
if (!date) return null;
|
||||||
const startDate = new Date(date);
|
const startDate = new Date(date);
|
||||||
@@ -28,3 +30,36 @@ export const getTimeOnly = (dateString) => {
|
|||||||
hour12: false
|
hour12: false
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getDateOnly = (dateString) => {
|
||||||
|
const date = new Date(dateString);
|
||||||
|
return date.toLocaleDateString('ko-KR', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
timeZone: 'Asia/Seoul'
|
||||||
|
}).replace(/\. /g, '-').replace('.', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
export const msToMinutes = (ms) => {
|
||||||
|
return ms / ONE_MINUTE_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const secondToMinutes = (second) => {
|
||||||
|
return second / ONE_MINUTE_SECOND;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isValidDayRange = (start_dt, end_dt) => {
|
||||||
|
const startDate = new Date(start_dt);
|
||||||
|
const endDate = new Date(end_dt);
|
||||||
|
|
||||||
|
// 시간을 00:00:00으로 설정하여 날짜만 비교
|
||||||
|
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||||
|
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||||
|
|
||||||
|
const diffTime = endDateOnly.getTime() - startDateOnly.getTime();
|
||||||
|
|
||||||
|
const oneDay = 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
|
return diffTime >= oneDay;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user