배너 detailGrid 적용
배너 수정 및 삭제
This commit is contained in:
1744
package-lock.json
generated
1744
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -67,11 +67,10 @@ export const MenuBannerModify = async (token, id, params) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 삭제
|
// 삭제
|
||||||
export const MenuBannerDelete = async (token, params) => {
|
export const MenuBannerDelete = async (token, id) => {
|
||||||
try {
|
try {
|
||||||
const res = await Axios.delete(`/api/v1/menu/banner/delete`, {
|
const res = await Axios.delete(`/api/v1/menu/banner/delete?id=${id}`, {
|
||||||
headers: { Authorization: `Bearer ${token}` },
|
headers: { Authorization: `Bearer ${token}` }
|
||||||
data: { list: params },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export * from './Event';
|
|||||||
export * from './Calium';
|
export * from './Calium';
|
||||||
export * from './Land';
|
export * from './Land';
|
||||||
export * from './Menu';
|
export * from './Menu';
|
||||||
export * from './OpenAI';
|
// export * from './OpenAI';
|
||||||
export * from './Log';
|
export * from './Log';
|
||||||
|
|
||||||
const apiModules = {};
|
const apiModules = {};
|
||||||
|
|||||||
@@ -66,11 +66,11 @@ export const STATUS_STYLES = {
|
|||||||
color: 'white'
|
color: 'white'
|
||||||
},
|
},
|
||||||
WAIT: {
|
WAIT: {
|
||||||
background: '#DEBB46',
|
background: '#FAAD14',
|
||||||
color: 'black'
|
color: 'black'
|
||||||
},
|
},
|
||||||
FAIL: {
|
FAIL: {
|
||||||
background: '#D33B27',
|
background: '#ff4d4f',
|
||||||
color: 'white'
|
color: 'white'
|
||||||
},
|
},
|
||||||
FINISH: {
|
FINISH: {
|
||||||
@@ -78,11 +78,11 @@ export const STATUS_STYLES = {
|
|||||||
color: 'black'
|
color: 'black'
|
||||||
},
|
},
|
||||||
REJECT: {
|
REJECT: {
|
||||||
background: '#D33B27',
|
background: '#ff4d4f',
|
||||||
color: 'white'
|
color: 'white'
|
||||||
},
|
},
|
||||||
CANCEL: {
|
CANCEL: {
|
||||||
background: '#D33B27',
|
background: '#ff4d4f',
|
||||||
color: 'white'
|
color: 'white'
|
||||||
},
|
},
|
||||||
RESV_START: {
|
RESV_START: {
|
||||||
@@ -106,7 +106,7 @@ export const STATUS_STYLES = {
|
|||||||
color: 'white'
|
color: 'white'
|
||||||
},
|
},
|
||||||
REGISTER: {
|
REGISTER: {
|
||||||
background: '#DEBB46',
|
background: '#FAAD14',
|
||||||
color: 'black'
|
color: 'black'
|
||||||
},
|
},
|
||||||
STOP: {
|
STOP: {
|
||||||
@@ -192,4 +192,5 @@ export const historyTables = {
|
|||||||
notice: 'notice',
|
notice: 'notice',
|
||||||
battleEvent: 'battle_event',
|
battleEvent: 'battle_event',
|
||||||
caliumRequest: 'calium_request',
|
caliumRequest: 'calium_request',
|
||||||
|
menuBanner: 'menu_banner',
|
||||||
}
|
}
|
||||||
@@ -14,14 +14,14 @@
|
|||||||
"text": "선택 삭제",
|
"text": "선택 삭제",
|
||||||
"theme": "line",
|
"theme": "line",
|
||||||
"disableWhen": "noSelection",
|
"disableWhen": "noSelection",
|
||||||
"requiredAuth": "battleEventDelete",
|
"requiredAuth": "menuBannerDelete",
|
||||||
"action": "delete"
|
"action": "delete"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "register",
|
"id": "register",
|
||||||
"text": "이미지 등록",
|
"text": "이미지 등록",
|
||||||
"theme": "primary",
|
"theme": "primary",
|
||||||
"requiredAuth": "battleEventUpdate",
|
"requiredAuth": "menuBannerUpdate",
|
||||||
"action": "navigate",
|
"action": "navigate",
|
||||||
"navigateTo": "/servicemanage/menubanner/menubannerregist"
|
"navigateTo": "/servicemanage/menubanner/menubannerregist"
|
||||||
}
|
}
|
||||||
@@ -40,6 +40,12 @@
|
|||||||
"width": "70px",
|
"width": "70px",
|
||||||
"title": "번호"
|
"title": "번호"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "order_id",
|
||||||
|
"type": "text",
|
||||||
|
"width": "70px",
|
||||||
|
"title": "순서"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "status",
|
"id": "status",
|
||||||
"type": "status",
|
"type": "status",
|
||||||
@@ -94,10 +100,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "update_by",
|
"id": "history",
|
||||||
"type": "text",
|
"type": "button",
|
||||||
"width": "150px",
|
"width": "120px",
|
||||||
"title": "히스토리"
|
"title": "히스토리",
|
||||||
|
"text": "히스토리"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sort": {
|
"sort": {
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ export const currencyCodeTypes = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const languageNames = {
|
export const languageNames = {
|
||||||
'KO': '한국어',
|
'Ko': '한국어',
|
||||||
'EN': '영어',
|
'En': '영어',
|
||||||
'JA': '일본어',
|
'Ja': '일본어',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { MenuImageDelete, MenuImageUpload } from '../../apis';
|
|||||||
import { IMAGE_MAX_SIZE } from '../../assets/data/adminConstants';
|
import { IMAGE_MAX_SIZE } from '../../assets/data/adminConstants';
|
||||||
import { useAlert } from '../../context/AlertProvider';
|
import { useAlert } from '../../context/AlertProvider';
|
||||||
import { alertTypes } from '../../assets/data/types';
|
import { alertTypes } from '../../assets/data/types';
|
||||||
|
import { ImagePreview } from '../../styles/Components';
|
||||||
|
|
||||||
const ImageUploadBtn = ({ disabled,
|
const ImageUploadBtn = ({ disabled,
|
||||||
onImageUpload,
|
onImageUpload,
|
||||||
@@ -220,14 +221,6 @@ const PreviewContainer = styled.div`
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ImagePreview = styled.img`
|
|
||||||
width: 100%;
|
|
||||||
height: 180px;
|
|
||||||
object-fit: contain;
|
|
||||||
border-radius: 4px 4px 0 0;
|
|
||||||
background-color: #f6f6f6;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const PreviewInfo = styled.div`
|
const PreviewInfo = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
@@ -1,38 +1,19 @@
|
|||||||
import React, { useState, useEffect, Fragment } from 'react';
|
import React, { useState, useEffect, Fragment } from 'react';
|
||||||
import styled, { css, keyframes } from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import {
|
import { Title, ButtonGroupWrapper, } from '../../styles/Components';
|
||||||
Title,
|
|
||||||
SelectInput,
|
|
||||||
BtnWrapper,
|
|
||||||
TextInput,
|
|
||||||
Label,
|
|
||||||
InputLabel,
|
|
||||||
Textarea,
|
|
||||||
SearchBarAlert,
|
|
||||||
ButtonGroupWrapper,
|
|
||||||
} from '../../styles/Components';
|
|
||||||
import Button from '../common/button/Button';
|
|
||||||
import Modal from '../common/modal/Modal';
|
import Modal from '../common/modal/Modal';
|
||||||
import { EventIsItem, EventModify, MenuBannerModify } from '../../apis';
|
import { MenuBannerModify } from '../../apis';
|
||||||
|
|
||||||
import { authList } from '../../store/authList';
|
import { authList } from '../../store/authList';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { authType, commonStatus } from '../../assets/data';
|
||||||
import { authType, benItems, commonStatus, currencyItemCode } from '../../assets/data';
|
import { convertKTCDate } from '../../utils';
|
||||||
import {
|
|
||||||
DetailInputItem, DetailInputRow,
|
|
||||||
DetailModalWrapper, RegistGroup, DetailRegistInfo, DetailState, FormRowGroup, FormLabel, FormInput,
|
|
||||||
} from '../../styles/ModuleComponents';
|
|
||||||
import { convertKTC, combineDateTime, timeDiffMinute, convertKTCDate } from '../../utils';
|
|
||||||
import DateTimeInput from '../common/input/DateTimeInput';
|
|
||||||
import { useLoading } from '../../context/LoadingProvider';
|
import { useLoading } from '../../context/LoadingProvider';
|
||||||
import { useAlert } from '../../context/AlertProvider';
|
import { useAlert } from '../../context/AlertProvider';
|
||||||
import { alertTypes, battleEventStatusType, languageNames } from '../../assets/data/types';
|
import { alertTypes, languageNames } from '../../assets/data/types';
|
||||||
import { Tabs, Image as AntImage, Spin } from 'antd';
|
import { Image as AntImage } from 'antd';
|
||||||
import { TYPE_MODIFY, TYPE_REGISTRY } from '../../assets/data/adminConstants';
|
import { AntButton, DetailLayout } from '../common';
|
||||||
import { AntButton, DateTimeRangePicker, DetailLayout, SingleTimePicker } from '../common';
|
|
||||||
import AnimatedTabs from '../common/control/AnimatedTabs';
|
|
||||||
|
|
||||||
function renderImageContent(imageData) {
|
function renderImageContent(imageData) {
|
||||||
if (!imageData) {
|
if (!imageData) {
|
||||||
@@ -77,7 +58,6 @@ function renderImageContent(imageData) {
|
|||||||
|
|
||||||
const MenuBannerDetailModal = ({ detailView, handleDetailView, content, setDetailData }) => {
|
const MenuBannerDetailModal = ({ detailView, handleDetailView, content, setDetailData }) => {
|
||||||
const userInfo = useRecoilValue(authList);
|
const userInfo = useRecoilValue(authList);
|
||||||
const { t } = useTranslation();
|
|
||||||
const token = sessionStorage.getItem('token');
|
const token = sessionStorage.getItem('token');
|
||||||
const {withLoading} = useLoading();
|
const {withLoading} = useLoading();
|
||||||
const {showModal, showToast} = useAlert();
|
const {showModal, showToast} = useAlert();
|
||||||
@@ -94,17 +74,12 @@ const MenuBannerDetailModal = ({ detailView, handleDetailView, content, setDetai
|
|||||||
|
|
||||||
const [resultData, setResultData] = useState(initData);
|
const [resultData, setResultData] = useState(initData);
|
||||||
const [activeLanguage, setActiveLanguage] = useState('KO');
|
const [activeLanguage, setActiveLanguage] = useState('KO');
|
||||||
// 이미지 프리로드를 위한 상태
|
|
||||||
const [allImagesLoaded, setAllImagesLoaded] = useState(false);
|
|
||||||
const [showTabContent, setShowTabContent] = useState(false);
|
|
||||||
const [loadedImages, setLoadedImages] = useState([]);
|
|
||||||
const [totalImageCount, setTotalImageCount] = useState(0);
|
|
||||||
|
|
||||||
const [tabItems, setTabItems] = useState([]);
|
const [tabItems, setTabItems] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(content){
|
if(content){
|
||||||
console.log(content);
|
// console.log(content);
|
||||||
const start_dt_KTC = convertKTCDate(content.start_dt);
|
const start_dt_KTC = convertKTCDate(content.start_dt);
|
||||||
const end_dt_KTC = convertKTCDate(content.end_dt);
|
const end_dt_KTC = convertKTCDate(content.end_dt);
|
||||||
|
|
||||||
@@ -131,13 +106,6 @@ const MenuBannerDetailModal = ({ detailView, handleDetailView, content, setDetai
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (content && content.image_list) {
|
if (content && content.image_list) {
|
||||||
// 초기화
|
|
||||||
setAllImagesLoaded(false);
|
|
||||||
setShowTabContent(false);
|
|
||||||
setLoadedImages([]);
|
|
||||||
|
|
||||||
// 이미지 개수 설정
|
|
||||||
setTotalImageCount(content.image_list ? content.image_list.length : 0);
|
|
||||||
|
|
||||||
// 첫 번째 언어를 활성 언어로 설정
|
// 첫 번째 언어를 활성 언어로 설정
|
||||||
if (content.image_list && content.image_list.length > 0) {
|
if (content.image_list && content.image_list.length > 0) {
|
||||||
@@ -156,105 +124,9 @@ const MenuBannerDetailModal = ({ detailView, handleDetailView, content, setDetai
|
|||||||
})) : [];
|
})) : [];
|
||||||
|
|
||||||
setTabItems(newTabItems);
|
setTabItems(newTabItems);
|
||||||
|
|
||||||
// 모든 이미지 프리로딩 시작
|
|
||||||
setTimeout(() => {
|
|
||||||
preloadAllImages();
|
|
||||||
}, 100);
|
|
||||||
}
|
}
|
||||||
}, [content]);
|
}, [content]);
|
||||||
|
|
||||||
const preloadAllImages = () => {
|
|
||||||
if (!content || !content.image_list || content.image_list.length === 0) {
|
|
||||||
// 이미지가 없는 경우 바로 로딩 완료 처리
|
|
||||||
// console.log('이미지가 없습니다. 로딩 완료 처리합니다.');
|
|
||||||
setAllImagesLoaded(true);
|
|
||||||
setShowTabContent(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// console.log(`총 ${content.image_list.length}개의 이미지 로딩을 시작합니다.`);
|
|
||||||
|
|
||||||
// 이미지 개수가 0이면 로딩 완료 처리
|
|
||||||
if (content.image_list.length === 0) {
|
|
||||||
setAllImagesLoaded(true);
|
|
||||||
setShowTabContent(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let loadedCount = 0;
|
|
||||||
|
|
||||||
// 이미지 로드 완료 이벤트 핸들러
|
|
||||||
const handleImageLoad = (url) => {
|
|
||||||
loadedCount++;
|
|
||||||
// console.log(`이미지 로드 완료 (${loadedCount}/${content.image_list.length}): ${url}`);
|
|
||||||
|
|
||||||
// 모든 이미지가 로드되었는지 확인
|
|
||||||
if (loadedCount >= content.image_list.length) {
|
|
||||||
// console.log('모든 이미지 로딩 완료!');
|
|
||||||
setAllImagesLoaded(true);
|
|
||||||
setShowTabContent(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 각 이미지에 대해 프리로드 객체 생성
|
|
||||||
content.image_list.forEach(img => {
|
|
||||||
if (img.title) {
|
|
||||||
// console.log(`이미지 로딩 시작: ${img.title}`);
|
|
||||||
const image = new Image();
|
|
||||||
image.onload = () => handleImageLoad(img.title);
|
|
||||||
image.onerror = () => {
|
|
||||||
console.log(`이미지 로드 실패: ${img.title}`);
|
|
||||||
handleImageLoad(img.title); // 오류 시에도 카운트
|
|
||||||
};
|
|
||||||
image.src = img.title; // src 속성은 onload/onerror 핸들러 설정 후에 설정
|
|
||||||
} else {
|
|
||||||
// console.log('이미지 URL이 없습니다.');
|
|
||||||
handleImageLoad('empty'); // URL이 없는 경우에도 카운트
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 안전장치: 5초 후에도 로딩이 완료되지 않으면 강제로 완료 처리
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!allImagesLoaded) {
|
|
||||||
// console.log('시간 초과로 로딩 강제 완료');
|
|
||||||
setAllImagesLoaded(true);
|
|
||||||
setShowTabContent(true);
|
|
||||||
}
|
|
||||||
}, 5000);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 날짜 처리
|
|
||||||
// const handleDateChange = (data, type) => {
|
|
||||||
// const date = new Date(data);
|
|
||||||
// setResultData({
|
|
||||||
// ...resultData,
|
|
||||||
// [`${type}_dt`]: combineDateTime(date, time[`${type}_hour`], time[`${type}_min`]),
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
// 시간 처리
|
|
||||||
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`]),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDateChange = {
|
|
||||||
start: (date) => {
|
|
||||||
setResultData(prev => ({ ...prev, start_dt: date }));
|
|
||||||
},
|
|
||||||
end: (date) => {
|
|
||||||
setResultData(prev => ({ ...prev, end_dt: date }));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 확인 버튼 후 다 초기화
|
// 확인 버튼 후 다 초기화
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
@@ -279,6 +151,7 @@ const MenuBannerDetailModal = ({ detailView, handleDetailView, content, setDetai
|
|||||||
case "submit":
|
case "submit":
|
||||||
if (!checkCondition()) return;
|
if (!checkCondition()) return;
|
||||||
|
|
||||||
|
// console.log(resultData);
|
||||||
showModal('MENU_BANNER_UPDATE_SAVE', {
|
showModal('MENU_BANNER_UPDATE_SAVE', {
|
||||||
type: alertTypes.confirm,
|
type: alertTypes.confirm,
|
||||||
onConfirm: () => handleSubmit('updateConfirm')
|
onConfirm: () => handleSubmit('updateConfirm')
|
||||||
@@ -287,50 +160,43 @@ const MenuBannerDetailModal = ({ detailView, handleDetailView, content, setDetai
|
|||||||
case "updateConfirm":
|
case "updateConfirm":
|
||||||
withLoading( async () => {
|
withLoading( async () => {
|
||||||
return await MenuBannerModify(token, id, resultData);
|
return await MenuBannerModify(token, id, resultData);
|
||||||
|
}).then(result => {
|
||||||
|
if(result.result === 'ERROR'){
|
||||||
|
showToast(result.data.message, {
|
||||||
|
type: alertTypes.error
|
||||||
|
});
|
||||||
|
}else if(result.result === 'SUCCESS'){
|
||||||
|
showToast('UPDATE_COMPLETED', {type: alertTypes.success, duration: 4000});
|
||||||
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
showToast('API_FAIL', {type: alertTypes.error});
|
showToast('API_FAIL', {type: alertTypes.error});
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
showToast('UPDATE_COMPLETED', {type: alertTypes.success});
|
|
||||||
handleDetailView();
|
handleDetailView();
|
||||||
});
|
});
|
||||||
break;
|
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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//true 수정불가, false 수정가능
|
|
||||||
const isView = (fieldName) => {
|
const isView = (fieldName) => {
|
||||||
if (!updateAuth) return false;
|
|
||||||
|
|
||||||
if (fieldName === 'editButton') {
|
if (fieldName === 'editButton') {
|
||||||
// updateAuth가 없거나 FINISH 상태면 수정 버튼 숨김 (false 반환)
|
// updateAuth가 없거나 FINISH 상태면 수정 버튼 숨김
|
||||||
return !updateAuth || content?.status === commonStatus.finish;
|
return !updateAuth || content?.status === commonStatus.finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (content?.status) {
|
if (!updateAuth) return false;
|
||||||
case commonStatus.running:
|
|
||||||
// RUNNING 상태일 때는 end_dt와 order_id만 수정 가능
|
if(content.status === commonStatus.wait){
|
||||||
return fieldName !== 'date' && fieldName !== 'order_id';
|
return true;
|
||||||
case commonStatus.wait:
|
}else if(content.status === commonStatus.running){
|
||||||
return true;
|
switch(fieldName){
|
||||||
default:
|
case 'order_id':
|
||||||
return false;
|
case 'end_dt':
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,12 +237,35 @@ const MenuBannerDetailModal = ({ detailView, handleDetailView, content, setDetai
|
|||||||
row: 2,
|
row: 2,
|
||||||
col: 0,
|
col: 0,
|
||||||
colSpan: 2,
|
colSpan: 2,
|
||||||
type: 'dateRange',
|
type: 'date',
|
||||||
key: 'dateRange',
|
key: 'start_dt',
|
||||||
keys: {start: 'start_dt', end: 'end_dt'},
|
label: '시작일',
|
||||||
label: '기간',
|
disabled: !isView('start_dt'),
|
||||||
disabled: !isView('date'),
|
format: 'YYYY-MM-DD HH:mm',
|
||||||
format: 'YYYY-MM-DD HH:mm'
|
width: '250px',
|
||||||
|
showTime: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
row: 2,
|
||||||
|
col: 2,
|
||||||
|
colSpan: 2,
|
||||||
|
type: 'date',
|
||||||
|
key: 'end_dt',
|
||||||
|
label: '종료일',
|
||||||
|
disabled: !isView('end_dt'),
|
||||||
|
format: 'YYYY-MM-DD HH:mm',
|
||||||
|
width: '250px',
|
||||||
|
showTime: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
row: 3,
|
||||||
|
col: 0,
|
||||||
|
colSpan: 4,
|
||||||
|
type: 'tab',
|
||||||
|
key: 'languageTabs',
|
||||||
|
tabItems: tabItems,
|
||||||
|
activeKey: activeLanguage,
|
||||||
|
onTabChange: handleTabChange
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -393,76 +282,6 @@ const MenuBannerDetailModal = ({ detailView, handleDetailView, content, setDetai
|
|||||||
disabled={!updateAuth}
|
disabled={!updateAuth}
|
||||||
columnCount={4}
|
columnCount={4}
|
||||||
/>
|
/>
|
||||||
{/*<DetailModalWrapper>*/}
|
|
||||||
{/* {content &&*/}
|
|
||||||
{/* <RegistGroup>*/}
|
|
||||||
{/* <FormRowGroup>*/}
|
|
||||||
{/* <DetailInputItem>*/}
|
|
||||||
{/* <FormLabel>제목</FormLabel>*/}
|
|
||||||
{/* <FormInput*/}
|
|
||||||
{/* type="text"*/}
|
|
||||||
{/* value={content.title}*/}
|
|
||||||
{/* disabled={isView('title')}*/}
|
|
||||||
{/* onChange={e => setResultData({ ...resultData, title: e.target.value })}*/}
|
|
||||||
{/* width="300px"*/}
|
|
||||||
{/* />*/}
|
|
||||||
{/* </DetailInputItem>*/}
|
|
||||||
{/* <DetailInputItem>*/}
|
|
||||||
{/* <FormLabel>순서</FormLabel>*/}
|
|
||||||
{/* <FormInput*/}
|
|
||||||
{/* placeholder="순서번호"*/}
|
|
||||||
{/* type="number"*/}
|
|
||||||
{/* value={content.order_id}*/}
|
|
||||||
{/* disabled={isView('order_id')}*/}
|
|
||||||
{/* onChange={e => setResultData({ ...resultData, order_id: e.target.value })}*/}
|
|
||||||
{/* width="200px"*/}
|
|
||||||
{/* />*/}
|
|
||||||
{/* </DetailInputItem>*/}
|
|
||||||
{/* </FormRowGroup>*/}
|
|
||||||
{/* <FormRowGroup>*/}
|
|
||||||
{/* <DateTimeRangePicker*/}
|
|
||||||
{/* label="예약기간"*/}
|
|
||||||
{/* startDate={resultData.start_dt}*/}
|
|
||||||
{/* endDate={resultData.end_dt}*/}
|
|
||||||
{/* onStartDateChange={handleDateChange.start}*/}
|
|
||||||
{/* onEndDateChange={handleDateChange.end}*/}
|
|
||||||
{/* pastDate={new Date()}*/}
|
|
||||||
{/* disabled={isView('date')}*/}
|
|
||||||
{/* startLabel="시작 일자"*/}
|
|
||||||
{/* endLabel="종료 일자"*/}
|
|
||||||
{/* // reset={resetDateTime}*/}
|
|
||||||
{/* />*/}
|
|
||||||
{/* </FormRowGroup>*/}
|
|
||||||
{/* <FormRowGroup>*/}
|
|
||||||
{/* <DetailInputItem>*/}
|
|
||||||
{/* <FormLabel>상태</FormLabel>*/}
|
|
||||||
{/* <div>{detailState(content.status)}</div>*/}
|
|
||||||
{/* </DetailInputItem>*/}
|
|
||||||
{/* </FormRowGroup>*/}
|
|
||||||
{/* {content.image_list && content.image_list.length > 0 && (*/}
|
|
||||||
{/* <FormRowGroup style={{display: 'flex', justifyContent: 'center', width: '100%'}}>*/}
|
|
||||||
{/* <DetailInputItem style={{width: '100%'}}>*/}
|
|
||||||
{/* {!showTabContent ? (*/}
|
|
||||||
{/* <LoadingContainer>*/}
|
|
||||||
{/* <Spin size="large" tip="이미지 로딩 중..." />*/}
|
|
||||||
{/* </LoadingContainer>*/}
|
|
||||||
{/* ) : (*/}
|
|
||||||
{/* <ContentWrapper $isLoaded={showTabContent}>*/}
|
|
||||||
{/* <AnimatedTabs*/}
|
|
||||||
{/* items={tabItems}*/}
|
|
||||||
{/* activeKey={activeLanguage}*/}
|
|
||||||
{/* onChange={handleTabChange}*/}
|
|
||||||
{/* />*/}
|
|
||||||
{/* </ContentWrapper>*/}
|
|
||||||
{/* )}*/}
|
|
||||||
|
|
||||||
{/* </DetailInputItem>*/}
|
|
||||||
{/* </FormRowGroup>*/}
|
|
||||||
{/* )}*/}
|
|
||||||
|
|
||||||
{/* </RegistGroup>*/}
|
|
||||||
{/* }*/}
|
|
||||||
{/*</DetailModalWrapper>*/}
|
|
||||||
<ButtonGroupWrapper $justify="flex-end" $gap="10px" $paddingTop="20px">
|
<ButtonGroupWrapper $justify="flex-end" $gap="10px" $paddingTop="20px">
|
||||||
<AntButton
|
<AntButton
|
||||||
text="확인"
|
text="확인"
|
||||||
@@ -503,43 +322,6 @@ const initData = {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyledTabs = styled(Tabs)`
|
|
||||||
margin-top: 20px;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.ant-tabs-nav {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-tabs-nav-wrap {
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-tabs-tab {
|
|
||||||
padding: 8px 16px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
transition: all 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn {
|
|
||||||
color: #1890ff;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-tabs-ink-bar {
|
|
||||||
background-color: #1890ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-tabs-content-holder {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ImageContainer = styled.div`
|
const ImageContainer = styled.div`
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -590,22 +372,3 @@ const NoImagePlaceholder = styled.div`
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// 로딩 인디케이터를 위한 컨테이너
|
|
||||||
const LoadingContainer = styled.div`
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 300px;
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
// 컨텐츠 래퍼 - 로딩 상태에 따라 가시성 설정
|
|
||||||
const ContentWrapper = styled.div`
|
|
||||||
width: 100%;
|
|
||||||
opacity: ${props => props.$isLoaded ? 1 : 0};
|
|
||||||
transition: opacity 0.3s ease-in-out;
|
|
||||||
height: ${props => props.$isLoaded ? 'auto' : '0'};
|
|
||||||
overflow: hidden;
|
|
||||||
`;
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ const resources = {
|
|||||||
EXCEL_EXPORT_LENGTH_LIMIT_WARNING: '엑셀 다운은 10만건 이하까지만 가능합니다.\r\n조건을 조정 후 다시 시도해주세요.',
|
EXCEL_EXPORT_LENGTH_LIMIT_WARNING: '엑셀 다운은 10만건 이하까지만 가능합니다.\r\n조건을 조정 후 다시 시도해주세요.',
|
||||||
DOWNLOAD_COMPLETE: '다운이 완료되었습니다.',
|
DOWNLOAD_COMPLETE: '다운이 완료되었습니다.',
|
||||||
DOWNLOAD_FAIL: '다운이 실패하였습니다.',
|
DOWNLOAD_FAIL: '다운이 실패하였습니다.',
|
||||||
|
DELETE_STATUS_ONLY_WAIT: '대기상태의 데이터만 삭제가 가능합니다.',
|
||||||
//user
|
//user
|
||||||
NICKNAME_CHANGES_CONFIRM: '닉네임을 변경하시겠습니까?',
|
NICKNAME_CHANGES_CONFIRM: '닉네임을 변경하시겠습니까?',
|
||||||
NICKNAME_CHANGES_COMPLETE: '닉네임 변경이 완료되었습니다.',
|
NICKNAME_CHANGES_COMPLETE: '닉네임 변경이 완료되었습니다.',
|
||||||
@@ -168,7 +169,8 @@ const resources = {
|
|||||||
NICKNAME_EXIT_ERROR: '해당 닉네임이 존재합니다.',
|
NICKNAME_EXIT_ERROR: '해당 닉네임이 존재합니다.',
|
||||||
NICKNAME_NUMBER_ERROR: '닉네임은 첫번째 글자에 숫자를 허용하지 않습니다.',
|
NICKNAME_NUMBER_ERROR: '닉네임은 첫번째 글자에 숫자를 허용하지 않습니다.',
|
||||||
NICKNAME_SPECIALCHAR_ERROR: '닉네임은 특수문자를 사용할 수 없습니다.',
|
NICKNAME_SPECIALCHAR_ERROR: '닉네임은 특수문자를 사용할 수 없습니다.',
|
||||||
NICKNAME_LANGTH_ERROR: '닉네임은 최소 2글자에서 최대 12글자까지 허용 합니다.'
|
NICKNAME_LANGTH_ERROR: '닉네임은 최소 2글자에서 최대 12글자까지 허용 합니다.',
|
||||||
|
dynamoDB_connection_error: '운영DB 작업중 에러가 발생하였습니다.'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
|
|||||||
@@ -1,26 +1,27 @@
|
|||||||
import { useState, Fragment, useRef } from 'react';
|
import React, { useState, Fragment, useRef } from 'react';
|
||||||
import 'react-datepicker/dist/react-datepicker.css';
|
import 'react-datepicker/dist/react-datepicker.css';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
authType,
|
authType, commonStatus as CommonStatus,
|
||||||
} from '../../assets/data';
|
} from '../../assets/data';
|
||||||
import { Title, FormWrapper} from '../../styles/Components';
|
import { Title, FormWrapper} from '../../styles/Components';
|
||||||
import {
|
import {
|
||||||
Pagination,
|
Pagination,
|
||||||
CaliTable, TableHeader,
|
CaliTable, TableHeader,
|
||||||
} from '../../components/common';
|
} from '../../components/common';
|
||||||
import { convertKTC, timeDiffMinute } from '../../utils';
|
|
||||||
import { INITIAL_PAGE_LIMIT } from '../../assets/data/adminConstants';
|
import { INITIAL_PAGE_LIMIT } from '../../assets/data/adminConstants';
|
||||||
import { useModal, useTable, withAuth } from '../../hooks/hook';
|
import { useModal, useTable, withAuth } from '../../hooks/hook';
|
||||||
import { MenuBannerDelete, MenuBannerDetailView } from '../../apis';
|
import { LogHistory, MenuBannerDelete, MenuBannerDetailView } from '../../apis';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import tableInfo from '../../assets/data/pages/menuBannerTable.json'
|
import tableInfo from '../../assets/data/pages/menuBannerTable.json'
|
||||||
import { CommonSearchBar, useCommonSearch } from '../../components/ServiceManage';
|
import { CommonSearchBar } from '../../components/ServiceManage';
|
||||||
import { useAlert } from '../../context/AlertProvider';
|
import { useAlert } from '../../context/AlertProvider';
|
||||||
import { alertTypes } from '../../assets/data/types';
|
import { alertTypes } from '../../assets/data/types';
|
||||||
import { useLoading } from '../../context/LoadingProvider';
|
import { useLoading } from '../../context/LoadingProvider';
|
||||||
import useEnhancedCommonSearch from '../../hooks/useEnhancedCommonSearch';
|
import useEnhancedCommonSearch from '../../hooks/useEnhancedCommonSearch';
|
||||||
import MenuBannerDetailModal from '../../components/modal/MenuBannerDetailModal';
|
import MenuBannerDetailModal from '../../components/modal/MenuBannerDetailModal';
|
||||||
|
import { historyTables } from '../../assets/data/data';
|
||||||
|
import LogDetailModal from '../../components/common/modal/LogDetailModal';
|
||||||
|
|
||||||
const MenuBanner = () => {
|
const MenuBanner = () => {
|
||||||
const tableRef = useRef(null);
|
const tableRef = useRef(null);
|
||||||
@@ -30,6 +31,7 @@ const MenuBanner = () => {
|
|||||||
const token = sessionStorage.getItem('token');
|
const token = sessionStorage.getItem('token');
|
||||||
|
|
||||||
const [detailData, setDetailData] = useState({});
|
const [detailData, setDetailData] = useState({});
|
||||||
|
const [historyData, setHistoryData] = useState({});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
modalState,
|
modalState,
|
||||||
@@ -37,6 +39,7 @@ const MenuBanner = () => {
|
|||||||
handleModalClose
|
handleModalClose
|
||||||
} = useModal({
|
} = useModal({
|
||||||
detail: 'hidden',
|
detail: 'hidden',
|
||||||
|
history: 'hidden',
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -49,10 +52,6 @@ const MenuBanner = () => {
|
|||||||
updateSearchParams,
|
updateSearchParams,
|
||||||
loading,
|
loading,
|
||||||
configLoaded,
|
configLoaded,
|
||||||
paginationType,
|
|
||||||
pagination,
|
|
||||||
goToNextPage,
|
|
||||||
goToPrevPage,
|
|
||||||
handlePageChange,
|
handlePageChange,
|
||||||
handlePageSizeChange
|
handlePageSizeChange
|
||||||
} = useEnhancedCommonSearch("menuBannerSearch");
|
} = useEnhancedCommonSearch("menuBannerSearch");
|
||||||
@@ -65,6 +64,17 @@ const MenuBanner = () => {
|
|||||||
|
|
||||||
const handleAction = async (action, item = null) => {
|
const handleAction = async (action, item = null) => {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
case "history":
|
||||||
|
const params = {};
|
||||||
|
params.db_type = "MYSQL"
|
||||||
|
params.sql_id = item.id;
|
||||||
|
params.table_name = historyTables.menuBanner
|
||||||
|
|
||||||
|
await LogHistory(token, params).then(data => {
|
||||||
|
setHistoryData(data);
|
||||||
|
handleModalView('history');
|
||||||
|
});
|
||||||
|
break;
|
||||||
case "detail":
|
case "detail":
|
||||||
await MenuBannerDetailView(token, item.id).then(data => {
|
await MenuBannerDetailView(token, item.id).then(data => {
|
||||||
setDetailData(data.detail);
|
setDetailData(data.detail);
|
||||||
@@ -72,38 +82,22 @@ const MenuBanner = () => {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "delete":
|
case "delete":
|
||||||
const date_check = selectedRows.every(row => {
|
|
||||||
const timeDiff = timeDiffMinute(convertKTC(row.auction_start_dt), (new Date));
|
|
||||||
return timeDiff < 3;
|
|
||||||
});
|
|
||||||
if(date_check){
|
|
||||||
showToast('LAND_AUCTION_DELETE_DATE_WARNING', {type: alertTypes.warning});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
showModal('MENU_BANNER_SELECT_DELETE', {
|
showModal('MENU_BANNER_SELECT_DELETE', {
|
||||||
type: alertTypes.confirm,
|
type: alertTypes.confirm,
|
||||||
onConfirm: () => handleAction('deleteConfirm')
|
onConfirm: () => handleAction('deleteConfirm')
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "deleteConfirm":
|
case "deleteConfirm":
|
||||||
let list = [];
|
const low = selectedRows[0];
|
||||||
let isChecked = false;
|
|
||||||
|
|
||||||
selectedRows.map(data => {
|
if(low.status !== CommonStatus.wait) {
|
||||||
// const row = dataList.list.find(row => row.id === Number(data.id));
|
showToast('DELETE_STATUS_ONLY_WAIT', {type: alertTypes.warning});
|
||||||
// if(row.status !== commonStatus.wait) isChecked = true;
|
|
||||||
list.push({
|
|
||||||
id: data.id,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if(isChecked) {
|
|
||||||
showToast('LAND_AUCTION_WARNING_DELETE', {type: alertTypes.warning});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await withLoading(async () => {
|
await withLoading(async () => {
|
||||||
return await MenuBannerDelete(token, list);
|
return await MenuBannerDelete(token, low.id);
|
||||||
}).then(data => {
|
}).then(data => {
|
||||||
if(data.result === "SUCCESS") {
|
if(data.result === "SUCCESS") {
|
||||||
showToast('DEL_COMPLETE', {type: alertTypes.success});
|
showToast('DEL_COMPLETE', {type: alertTypes.success});
|
||||||
@@ -119,7 +113,6 @@ const MenuBanner = () => {
|
|||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
handleSearch(updateSearchParams);
|
handleSearch(updateSearchParams);
|
||||||
});
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -183,13 +176,24 @@ const MenuBanner = () => {
|
|||||||
{/* 상세 */}
|
{/* 상세 */}
|
||||||
<MenuBannerDetailModal
|
<MenuBannerDetailModal
|
||||||
detailView={modalState.detailModal}
|
detailView={modalState.detailModal}
|
||||||
handleDetailView={() => handleModalClose('detail')}
|
handleDetailView={() => {
|
||||||
|
handleModalClose('detail');
|
||||||
|
handleSearch(updateSearchParams);
|
||||||
|
}}
|
||||||
content={detailData}
|
content={detailData}
|
||||||
setDetailData={setDetailData}
|
setDetailData={setDetailData}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<LogDetailModal
|
||||||
|
viewMode="changed"
|
||||||
|
detailView={modalState.historyModal}
|
||||||
|
handleDetailView={() => handleModalClose('history')}
|
||||||
|
changedData={historyData}
|
||||||
|
title="히스토리"
|
||||||
|
/>
|
||||||
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withAuth(authType.battleEventRead)(MenuBanner);
|
export default withAuth(authType.menuBannerRead)(MenuBanner);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { useRecoilValue } from 'recoil';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import Button from '../../components/common/button/Button';
|
import Button from '../../components/common/button/Button';
|
||||||
import Loading from '../../components/common/Loading';
|
|
||||||
import {
|
import {
|
||||||
Title,
|
Title,
|
||||||
BtnWrapper,
|
BtnWrapper,
|
||||||
@@ -19,14 +18,14 @@ import {
|
|||||||
FormInput, FormInputSuffix, FormInputSuffixWrapper, FormLabel, FormRowGroup,RegistGroup,
|
FormInput, FormInputSuffix, FormInputSuffixWrapper, FormLabel, FormRowGroup,RegistGroup,
|
||||||
} from '../../styles/ModuleComponents';
|
} from '../../styles/ModuleComponents';
|
||||||
import AuthModal from '../../components/common/modal/AuthModal';
|
import AuthModal from '../../components/common/modal/AuthModal';
|
||||||
import { authType, modalTypes } from '../../assets/data';
|
import { authType } from '../../assets/data';
|
||||||
import { loadConfig, timeDiffMinute } from '../../utils';
|
import { loadConfig } from '../../utils';
|
||||||
import { SingleDatePicker, SingleTimePicker } from '../../components/common';
|
import { SingleDatePicker, SingleTimePicker } from '../../components/common';
|
||||||
import CheckBox from '../../components/common/input/CheckBox';
|
import CheckBox from '../../components/common/input/CheckBox';
|
||||||
import ImageUploadBtn from '../../components/ServiceManage/ImageUploadBtn';
|
import ImageUploadBtn from '../../components/ServiceManage/ImageUploadBtn';
|
||||||
import CaliForm from '../../components/common/Custom/CaliForm';
|
|
||||||
import { useAlert } from '../../context/AlertProvider';
|
import { useAlert } from '../../context/AlertProvider';
|
||||||
import { alertTypes } from '../../assets/data/types';
|
import { alertTypes } from '../../assets/data/types';
|
||||||
|
import { useLoading } from '../../context/LoadingProvider';
|
||||||
|
|
||||||
const MenuBannerRegist = () => {
|
const MenuBannerRegist = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -34,8 +33,7 @@ const MenuBannerRegist = () => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const token = sessionStorage.getItem('token');
|
const token = sessionStorage.getItem('token');
|
||||||
const { showToast, showModal } = useAlert();
|
const { showToast, showModal } = useAlert();
|
||||||
|
const {withLoading} = useLoading();
|
||||||
const [loading, setLoading] = useState(false); // 로딩 창
|
|
||||||
|
|
||||||
const [isNullValue, setIsNullValue] = useState(false); // 데이터 값 체크
|
const [isNullValue, setIsNullValue] = useState(false); // 데이터 값 체크
|
||||||
const [alertMsg, setAlertMsg] = useState('');
|
const [alertMsg, setAlertMsg] = useState('');
|
||||||
@@ -45,7 +43,6 @@ const MenuBannerRegist = () => {
|
|||||||
|
|
||||||
const [pageConfig, setPageConfig] = useState(null);
|
const [pageConfig, setPageConfig] = useState(null);
|
||||||
const [formData, setFormData] = useState({});
|
const [formData, setFormData] = useState({});
|
||||||
const [isFormValid, setIsFormValid] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(alertMsg){
|
if(alertMsg){
|
||||||
@@ -69,19 +66,6 @@ const MenuBannerRegist = () => {
|
|||||||
loadPageConfig();
|
loadPageConfig();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleFieldValidation = (isValid, errors) => {
|
|
||||||
setIsFormValid(isValid);
|
|
||||||
|
|
||||||
if (errors._form) {
|
|
||||||
setAlertMsg(t(errors._form));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 폼 제출 핸들러
|
|
||||||
const handleFormSubmit = (data) => {
|
|
||||||
setFormData(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (checkCondition()) {
|
if (checkCondition()) {
|
||||||
@@ -109,7 +93,7 @@ const MenuBannerRegist = () => {
|
|||||||
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(t('DATE_START_DIFF_END_WARNING'));
|
showToast('DATE_START_DIFF_END_WARNING', {type: alertTypes.warning} );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +137,7 @@ const MenuBannerRegist = () => {
|
|||||||
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(t('DATE_START_DIFF_END_WARNING'));
|
showToast('DATE_START_DIFF_END_WARNING', {type: alertTypes.warning} );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,27 +210,43 @@ const MenuBannerRegist = () => {
|
|||||||
navigate('/servicemanage/menubanner');
|
navigate('/servicemanage/menubanner');
|
||||||
break;
|
break;
|
||||||
case "registConfirm":
|
case "registConfirm":
|
||||||
setLoading(true);
|
|
||||||
|
|
||||||
const result = await MenuBannerSingleRegist(token, resultData);
|
await withLoading(async () => {
|
||||||
|
return await MenuBannerSingleRegist(token, resultData);
|
||||||
|
}).then(result => {
|
||||||
|
// console.log(result);
|
||||||
|
if(result.result === 'ERROR'){
|
||||||
|
setResultData(prevData => ({
|
||||||
|
...prevData,
|
||||||
|
image_list: prevData.image_list.map(img => ({
|
||||||
|
...img,
|
||||||
|
content: ''
|
||||||
|
}))
|
||||||
|
}));
|
||||||
|
|
||||||
setLoading(false);
|
showToast(result.data.message, {
|
||||||
showToast('REGIST_COMPLTE', {
|
type: alertTypes.error
|
||||||
type: alertTypes.success,
|
});
|
||||||
duration: 4000,
|
}else if(result.result === 'SUCCESS'){
|
||||||
});
|
showToast('REGIST_COMPLTE', {
|
||||||
navigate('/servicemanage/menubanner');
|
type: alertTypes.success,
|
||||||
break;
|
duration: 4000,
|
||||||
case "warning":
|
});
|
||||||
setAlertMsg('');
|
navigate('/servicemanage/menubanner');
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
showToast(error, {type: alertTypes.error} );
|
||||||
|
}).finally(() => {
|
||||||
|
|
||||||
|
})
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkCondition = () => {
|
const checkCondition = () => {
|
||||||
return (
|
return (
|
||||||
(resultData.start_dt.length !== 0) &&
|
(resultData.start_dt && resultData.start_dt.length !== 0) &&
|
||||||
(resultData.end_dt.length !== 0) &&
|
(resultData.end_dt && resultData.end_dt.length !== 0) &&
|
||||||
resultData.title !== '' &&
|
resultData.title !== '' &&
|
||||||
resultData.image_list.every(data => data.content !== '') &&
|
resultData.image_list.every(data => data.content !== '') &&
|
||||||
(resultData.is_link === false || (resultData.is_link === true && resultData.link_list.every(data => data.content !== '')))
|
(resultData.is_link === false || (resultData.is_link === true && resultData.link_list.every(data => data.content !== '')))
|
||||||
@@ -315,12 +315,11 @@ const MenuBannerRegist = () => {
|
|||||||
/>
|
/>
|
||||||
</FormRowGroup>
|
</FormRowGroup>
|
||||||
{resultData?.is_link &&
|
{resultData?.is_link &&
|
||||||
<>
|
|
||||||
<FormRowGroup>
|
<FormRowGroup>
|
||||||
<FormLabel>웹 링크</FormLabel>
|
<FormLabel>웹 링크</FormLabel>
|
||||||
<LanguageWrapper width="50%" >
|
<LanguageWrapper width="50%" >
|
||||||
{resultData.link_list.map((data, idx) => (
|
{resultData.link_list.map((data, idx) => (
|
||||||
<FormInputSuffixWrapper>
|
<FormInputSuffixWrapper key={idx}>
|
||||||
<FormInput
|
<FormInput
|
||||||
type="text"
|
type="text"
|
||||||
value={resultData?.link_list[idx].content}
|
value={resultData?.link_list[idx].content}
|
||||||
@@ -336,7 +335,6 @@ const MenuBannerRegist = () => {
|
|||||||
))}
|
))}
|
||||||
</LanguageWrapper>
|
</LanguageWrapper>
|
||||||
</FormRowGroup>
|
</FormRowGroup>
|
||||||
</>
|
|
||||||
}
|
}
|
||||||
</RegistGroup>
|
</RegistGroup>
|
||||||
|
|
||||||
@@ -367,8 +365,6 @@ const MenuBannerRegist = () => {
|
|||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</BtnWrapper>
|
</BtnWrapper>
|
||||||
|
|
||||||
{loading && <Loading/>}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
@@ -381,14 +377,14 @@ const initData = {
|
|||||||
start_dt: '',
|
start_dt: '',
|
||||||
end_dt: '',
|
end_dt: '',
|
||||||
image_list: [
|
image_list: [
|
||||||
{ language: 'KO', content: '' },
|
{ language: 'Ko', content: '' },
|
||||||
{ language: 'EN', content: '' },
|
{ language: 'En', content: '' },
|
||||||
{ language: 'JA', content: '' },
|
{ language: 'Ja', content: '' },
|
||||||
],
|
],
|
||||||
link_list: [
|
link_list: [
|
||||||
{ language: 'KO', content: '' },
|
{ language: 'Ko', content: '' },
|
||||||
{ language: 'EN', content: '' },
|
{ language: 'En', content: '' },
|
||||||
{ language: 'JA', content: '' },
|
{ language: 'Ja', content: '' },
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,433 +0,0 @@
|
|||||||
import React, { useState, Fragment, useEffect } from 'react';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
import Button from '../../components/common/button/Button';
|
|
||||||
import Loading from '../../components/common/Loading';
|
|
||||||
import {
|
|
||||||
Title,
|
|
||||||
BtnWrapper,
|
|
||||||
SearchBarAlert,
|
|
||||||
} from '../../styles/Components';
|
|
||||||
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import { MenuBannerSingleRegist } from '../../apis';
|
|
||||||
|
|
||||||
import { authList } from '../../store/authList';
|
|
||||||
import {
|
|
||||||
FormInput, FormInputSuffix, FormInputSuffixWrapper, FormLabel, FormRowGroup,RegistGroup,
|
|
||||||
} from '../../styles/ModuleComponents';
|
|
||||||
import AuthModal from '../../components/common/modal/AuthModal';
|
|
||||||
import { authType, modalTypes } from '../../assets/data';
|
|
||||||
import DynamicModal from '../../components/common/modal/DynamicModal';
|
|
||||||
import { loadConfig, timeDiffMinute } from '../../utils';
|
|
||||||
import { SingleDatePicker, SingleTimePicker } from '../../components/common';
|
|
||||||
import CheckBox from '../../components/common/input/CheckBox';
|
|
||||||
import ImageUploadBtn from '../../components/ServiceManage/ImageUploadBtn';
|
|
||||||
import { useModal } from '../../hooks/hook';
|
|
||||||
|
|
||||||
const MenuBannerRegist = () => {
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const userInfo = useRecoilValue(authList);
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const token = sessionStorage.getItem('token');
|
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false); // 로딩 창
|
|
||||||
const {
|
|
||||||
modalState,
|
|
||||||
handleModalView,
|
|
||||||
handleModalClose
|
|
||||||
} = useModal({
|
|
||||||
cancel: 'hidden',
|
|
||||||
registConfirm: 'hidden',
|
|
||||||
registComplete: 'hidden'
|
|
||||||
});
|
|
||||||
|
|
||||||
const [isNullValue, setIsNullValue] = useState(false); // 데이터 값 체크
|
|
||||||
const [alertMsg, setAlertMsg] = useState('');
|
|
||||||
|
|
||||||
const [resultData, setResultData] = useState(initData); //데이터 정보
|
|
||||||
const [resetDateTime, setResetDateTime] = useState(false);
|
|
||||||
|
|
||||||
const [pageConfig, setPageConfig] = useState(null);
|
|
||||||
const [formData, setFormData] = useState({});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const loadPageConfig = async () => {
|
|
||||||
try {
|
|
||||||
const config = await loadConfig('menuBannerRegist');
|
|
||||||
setPageConfig(config);
|
|
||||||
setFormData(config.initData);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to load page configuration', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
loadPageConfig();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (checkCondition()) {
|
|
||||||
setIsNullValue(false);
|
|
||||||
} else {
|
|
||||||
setIsNullValue(true);
|
|
||||||
}
|
|
||||||
}, [resultData]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (resetDateTime) {
|
|
||||||
setResetDateTime(false);
|
|
||||||
}
|
|
||||||
}, [resetDateTime]);
|
|
||||||
|
|
||||||
// 시작 날짜 변경 핸들러
|
|
||||||
const handleStartDateChange = (date) => {
|
|
||||||
if (!date) return;
|
|
||||||
|
|
||||||
const newDate = new Date(date);
|
|
||||||
|
|
||||||
if(resultData.end_dt){
|
|
||||||
const endDate = new Date(resultData.end_dt);
|
|
||||||
const startDay = new Date(newDate.getFullYear(), newDate.getMonth(), newDate.getDate());
|
|
||||||
const endDay = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
|
||||||
|
|
||||||
if (endDay <= startDay) {
|
|
||||||
setAlertMsg(t('DATE_START_DIFF_END_WARNING'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setResultData(prev => ({
|
|
||||||
...prev,
|
|
||||||
start_dt: newDate
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
// 시작 시간 변경 핸들러
|
|
||||||
const handleStartTimeChange = (time) => {
|
|
||||||
if (!time) return;
|
|
||||||
|
|
||||||
const newDateTime = resultData.start_dt
|
|
||||||
? new Date(resultData.start_dt)
|
|
||||||
: new Date();
|
|
||||||
|
|
||||||
newDateTime.setHours(
|
|
||||||
time.getHours(),
|
|
||||||
time.getMinutes(),
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
setResultData(prev => ({
|
|
||||||
...prev,
|
|
||||||
start_dt: newDateTime
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
// 종료 날짜 변경 핸들러
|
|
||||||
const handleEndDateChange = (date) => {
|
|
||||||
if (!date || !resultData.start_dt) return;
|
|
||||||
|
|
||||||
const startDate = new Date(resultData.start_dt);
|
|
||||||
const endDate = new Date(date);
|
|
||||||
|
|
||||||
// 일자만 비교하기 위해 년/월/일만 추출
|
|
||||||
const startDay = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
|
||||||
const endDay = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
|
||||||
|
|
||||||
if (endDay <= startDay) {
|
|
||||||
setAlertMsg(t('DATE_START_DIFF_END_WARNING'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setResultData(prev => ({
|
|
||||||
...prev,
|
|
||||||
end_dt: endDate
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
// 종료 시간 변경 핸들러
|
|
||||||
const handleEndTimeChange = (time) => {
|
|
||||||
if (!time) return;
|
|
||||||
|
|
||||||
const newDateTime = resultData.end_dt
|
|
||||||
? new Date(resultData.end_dt)
|
|
||||||
: new Date();
|
|
||||||
|
|
||||||
newDateTime.setHours(
|
|
||||||
time.getHours(),
|
|
||||||
time.getMinutes(),
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
setResultData(prev => ({
|
|
||||||
...prev,
|
|
||||||
end_dt: newDateTime
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
// 이미지 업로드
|
|
||||||
const handleImageUpload = (language, file, fileName) => {
|
|
||||||
const imageIndex = resultData.image_list.findIndex(img => img.language === language);
|
|
||||||
|
|
||||||
if (imageIndex !== -1) {
|
|
||||||
const updatedImageList = [...resultData.image_list];
|
|
||||||
updatedImageList[imageIndex] = {
|
|
||||||
...updatedImageList[imageIndex],
|
|
||||||
content: fileName,
|
|
||||||
};
|
|
||||||
|
|
||||||
setResultData({
|
|
||||||
...resultData,
|
|
||||||
image_list: updatedImageList
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 이미지 삭제
|
|
||||||
const handleImageDelete = (language) => {
|
|
||||||
const imageIndex = resultData.image_list.findIndex(img => img.language === language);
|
|
||||||
|
|
||||||
if (imageIndex !== -1) {
|
|
||||||
const updatedImageList = [...resultData.image_list];
|
|
||||||
updatedImageList[imageIndex] = {
|
|
||||||
...updatedImageList[imageIndex],
|
|
||||||
content: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
setResultData({
|
|
||||||
...resultData,
|
|
||||||
image_list: updatedImageList
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = async (type, param = null) => {
|
|
||||||
switch (type) {
|
|
||||||
case "submit":
|
|
||||||
if (!checkCondition()) return;
|
|
||||||
const timeDiff = timeDiffMinute(resultData.start_dt, (new Date))
|
|
||||||
if(timeDiff < 60) {
|
|
||||||
setAlertMsg(t('EVENT_TIME_LIMIT_ADD'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
handleModalView('registConfirm');
|
|
||||||
break;
|
|
||||||
case "cancel":
|
|
||||||
|
|
||||||
handleModalClose('cancel');
|
|
||||||
navigate('/servicemanage/menubanner');
|
|
||||||
break;
|
|
||||||
case "registConfirm":
|
|
||||||
setLoading(true);
|
|
||||||
|
|
||||||
const result = await MenuBannerSingleRegist(token, resultData);
|
|
||||||
|
|
||||||
setLoading(false);
|
|
||||||
handleModalClose('registConfirm');
|
|
||||||
handleModalView('registComplete');
|
|
||||||
break;
|
|
||||||
case "registComplete":
|
|
||||||
handleModalClose('registComplete');
|
|
||||||
|
|
||||||
navigate('/servicemanage/menubanner');
|
|
||||||
break;
|
|
||||||
case "warning":
|
|
||||||
setAlertMsg('');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkCondition = () => {
|
|
||||||
return (
|
|
||||||
(resultData.start_dt.length !== 0) &&
|
|
||||||
(resultData.end_dt.length !== 0) &&
|
|
||||||
resultData.title !== '' &&
|
|
||||||
resultData.image_list.every(data => data.content !== '') &&
|
|
||||||
(resultData.is_link === false || (resultData.is_link === true && resultData.link_list.every(data => data.content !== '')))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{userInfo.auth_list && !userInfo.auth_list.some(auth => auth.id === authType.eventUpdate) ? (
|
|
||||||
<AuthModal/>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<Title>메뉴배너 등록</Title>
|
|
||||||
<RegistGroup>
|
|
||||||
<FormRowGroup>
|
|
||||||
<FormLabel>등록기간</FormLabel>
|
|
||||||
<SingleDatePicker
|
|
||||||
label="시작일자"
|
|
||||||
dateLabel="시작 일자"
|
|
||||||
onDateChange={handleStartDateChange}
|
|
||||||
selectedDate={resultData?.start_dt}
|
|
||||||
/>
|
|
||||||
<SingleTimePicker
|
|
||||||
selectedTime={resultData?.start_dt}
|
|
||||||
onTimeChange={handleStartTimeChange}
|
|
||||||
/>
|
|
||||||
<SingleDatePicker
|
|
||||||
label="종료일자"
|
|
||||||
dateLabel="종료 일자"
|
|
||||||
onDateChange={handleEndDateChange}
|
|
||||||
selectedDate={resultData?.end_dt}
|
|
||||||
/>
|
|
||||||
<SingleTimePicker
|
|
||||||
selectedTime={resultData?.end_dt}
|
|
||||||
onTimeChange={handleEndTimeChange}
|
|
||||||
/>
|
|
||||||
</FormRowGroup>
|
|
||||||
|
|
||||||
<FormRowGroup>
|
|
||||||
<FormLabel>배너 제목</FormLabel>
|
|
||||||
<FormInput
|
|
||||||
type="text"
|
|
||||||
width='50%'
|
|
||||||
value={resultData?.title}
|
|
||||||
onChange={e => setResultData({ ...resultData, title: e.target.value })}
|
|
||||||
/>
|
|
||||||
</FormRowGroup>
|
|
||||||
<FormLabel>이미지 첨부</FormLabel>
|
|
||||||
{resultData.image_list.map((data, idx) => (
|
|
||||||
<LanguageWrapper key={idx}>
|
|
||||||
<LanguageLabel>{data.language}</LanguageLabel>
|
|
||||||
<ImageUploadBtn
|
|
||||||
onImageUpload={(file, fileName) => handleImageUpload(data.language, file, fileName)}
|
|
||||||
onFileDelete={() => handleImageDelete(data.language)}
|
|
||||||
fileName={data.content}
|
|
||||||
setAlertMessage={setAlertMsg}
|
|
||||||
/>
|
|
||||||
</LanguageWrapper>
|
|
||||||
))}
|
|
||||||
<FormRowGroup>
|
|
||||||
<CheckBox
|
|
||||||
label="이미지 링크 여부"
|
|
||||||
id="reserve"
|
|
||||||
checked={resultData.is_link}
|
|
||||||
setData={e => setResultData({ ...resultData, is_link: e.target.checked })}
|
|
||||||
/>
|
|
||||||
</FormRowGroup>
|
|
||||||
{resultData?.is_link &&
|
|
||||||
<>
|
|
||||||
<FormRowGroup>
|
|
||||||
<FormLabel>웹 링크</FormLabel>
|
|
||||||
<LanguageWrapper width="50%" >
|
|
||||||
{resultData.link_list.map((data, idx) => (
|
|
||||||
<FormInputSuffixWrapper>
|
|
||||||
<FormInput
|
|
||||||
type="text"
|
|
||||||
value={resultData?.link_list[idx].content}
|
|
||||||
onChange={e => {
|
|
||||||
const updatedLinkList = [...resultData.link_list];
|
|
||||||
updatedLinkList[idx] = { ...updatedLinkList[idx], content: e.target.value };
|
|
||||||
setResultData({ ...resultData, link_list: updatedLinkList });
|
|
||||||
}}
|
|
||||||
suffix="true"
|
|
||||||
/>
|
|
||||||
<FormInputSuffix>{data.language}</FormInputSuffix>
|
|
||||||
</FormInputSuffixWrapper>
|
|
||||||
))}
|
|
||||||
</LanguageWrapper>
|
|
||||||
</FormRowGroup>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
</RegistGroup>
|
|
||||||
|
|
||||||
{isNullValue && (
|
|
||||||
<SearchBarAlert $align="right" $padding="0 0 15px">
|
|
||||||
{t('NULL_MSG')}
|
|
||||||
</SearchBarAlert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<BtnWrapper $justify="flex-end" $gap="10px">
|
|
||||||
<Button text="취소" theme="line" handleClick={() => handleModalView('cancel')} />
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
text="등록"
|
|
||||||
theme={checkCondition() ? 'primary' : 'disable'}
|
|
||||||
handleClick={() => handleSubmit('submit')}
|
|
||||||
/>
|
|
||||||
</BtnWrapper>
|
|
||||||
|
|
||||||
{/* 등록 모달 */}
|
|
||||||
<DynamicModal
|
|
||||||
modalType={modalTypes.confirmOkCancel}
|
|
||||||
view={modalState.registConfirmModal}
|
|
||||||
modalText={t('MENU_BANNER_REGIST_CONFIRM')}
|
|
||||||
handleSubmit={() => handleSubmit('registConfirm')}
|
|
||||||
handleCancel={() => handleModalClose('registConfirm')}
|
|
||||||
/>
|
|
||||||
{/* 완료 모달 */}
|
|
||||||
<DynamicModal
|
|
||||||
modalType={modalTypes.completed}
|
|
||||||
view={modalState.registCompleteModal}
|
|
||||||
modalText={t('REGIST_COMPLTE')}
|
|
||||||
handleSubmit={() => handleSubmit('registComplete')}
|
|
||||||
/>
|
|
||||||
{/* 취소 모달 */}
|
|
||||||
<DynamicModal
|
|
||||||
modalType={modalTypes.confirmOkCancel}
|
|
||||||
view={modalState.cancelModal}
|
|
||||||
modalText={t('MENU_BANNER_REGIST_CANCEL')}
|
|
||||||
handleCancel={() => handleModalClose('cancel')}
|
|
||||||
handleSubmit={() => handleSubmit('cancel')}
|
|
||||||
/>
|
|
||||||
{/* 경고 모달 */}
|
|
||||||
<DynamicModal
|
|
||||||
modalType={modalTypes.completed}
|
|
||||||
view={alertMsg ? 'view' : 'hidden'}
|
|
||||||
modalText={alertMsg}
|
|
||||||
handleSubmit={() => handleSubmit('warning')}
|
|
||||||
/>
|
|
||||||
{loading && <Loading/>}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const initData = {
|
|
||||||
title: '',
|
|
||||||
is_link: false,
|
|
||||||
start_dt: '',
|
|
||||||
end_dt: '',
|
|
||||||
image_list: [
|
|
||||||
{ language: 'KO', content: '' },
|
|
||||||
{ language: 'EN', content: '' },
|
|
||||||
{ language: 'JA', content: '' },
|
|
||||||
],
|
|
||||||
link_list: [
|
|
||||||
{ language: 'KO', content: '' },
|
|
||||||
{ language: 'EN', content: '' },
|
|
||||||
{ language: 'JA', content: '' },
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
export default MenuBannerRegist;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const LanguageWrapper = styled.div`
|
|
||||||
width: ${props => props.width || '100%'};
|
|
||||||
//margin-bottom: 20px;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
padding-left: 90px;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border-bottom: none;
|
|
||||||
margin-bottom: 0;
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const LanguageLabel = styled.h4`
|
|
||||||
color: #444;
|
|
||||||
margin: 0 0 10px 20px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
`;
|
|
||||||
@@ -1,341 +0,0 @@
|
|||||||
import { useState, Fragment, useRef } from 'react';
|
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import 'react-datepicker/dist/react-datepicker.css';
|
|
||||||
|
|
||||||
import { authList } from '../../store/authList';
|
|
||||||
import {
|
|
||||||
authType,
|
|
||||||
modalTypes,
|
|
||||||
landAuctionStatusType, opYNType,
|
|
||||||
} from '../../assets/data';
|
|
||||||
import { Title, FormWrapper, TableStyle, TableWrapper} from '../../styles/Components';
|
|
||||||
import {
|
|
||||||
CheckBox,
|
|
||||||
Button,
|
|
||||||
DynamicModal,
|
|
||||||
Pagination,
|
|
||||||
ViewTableInfo, CaliTable, TableHeader,
|
|
||||||
} from '../../components/common';
|
|
||||||
import { convertKTC, timeDiffMinute } from '../../utils';
|
|
||||||
import { INITIAL_PAGE_SIZE, INITIAL_PAGE_LIMIT } from '../../assets/data/adminConstants';
|
|
||||||
import { useModal, useTable, withAuth } from '../../hooks/hook';
|
|
||||||
import { StatusWapper, StatusLabel } from '../../styles/ModuleComponents';
|
|
||||||
import { opMenuBannerStatus } from '../../assets/data/options';
|
|
||||||
import MenuBannerSearchBar, { useMenuBannerSearch } from '../../components/searchBar/MenuBannerSearchBar';
|
|
||||||
import { MenuBannerDelete, MenuBannerDetailView } from '../../apis';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import MenuBannerModal from '../../components/modal/MenuBannerModal';
|
|
||||||
import tableInfo from '../../assets/data/pages/menuBannerTable.json'
|
|
||||||
|
|
||||||
const MenuBanner = () => {
|
|
||||||
const token = sessionStorage.getItem('token');
|
|
||||||
const userInfo = useRecoilValue(authList);
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const tableRef = useRef(null);
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const [detailData, setDetailData] = useState({});
|
|
||||||
|
|
||||||
const {
|
|
||||||
modalState,
|
|
||||||
handleModalView,
|
|
||||||
handleModalClose
|
|
||||||
} = useModal({
|
|
||||||
detail: 'hidden',
|
|
||||||
deleteConfirm: 'hidden',
|
|
||||||
deleteComplete: 'hidden'
|
|
||||||
});
|
|
||||||
const [alertMsg, setAlertMsg] = useState('');
|
|
||||||
const [modalType, setModalType] = useState('regist');
|
|
||||||
|
|
||||||
const {
|
|
||||||
searchParams,
|
|
||||||
data: dataList,
|
|
||||||
handleSearch,
|
|
||||||
handleReset,
|
|
||||||
handlePageChange,
|
|
||||||
handlePageSizeChange,
|
|
||||||
handleOrderByChange,
|
|
||||||
updateSearchParams
|
|
||||||
} = useMenuBannerSearch(token, INITIAL_PAGE_SIZE);
|
|
||||||
|
|
||||||
const {
|
|
||||||
selectedRows,
|
|
||||||
handleSelectRow,
|
|
||||||
isRowSelected
|
|
||||||
} = useTable(dataList?.event_list || [], {mode: 'single'});
|
|
||||||
|
|
||||||
|
|
||||||
const handleModalSubmit = async (type, param = null) => {
|
|
||||||
switch (type) {
|
|
||||||
case "regist":
|
|
||||||
setModalType('regist');
|
|
||||||
handleModalView('detail');
|
|
||||||
break;
|
|
||||||
case "detail":
|
|
||||||
await MenuBannerDetailView(token, param).then(data => {
|
|
||||||
setDetailData(data.event_detail);
|
|
||||||
setModalType('modify');
|
|
||||||
handleModalView('detail');
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "delete":
|
|
||||||
const date_check = selectedRows.every(row => {
|
|
||||||
const timeDiff = timeDiffMinute(convertKTC(row.auction_start_dt), (new Date));
|
|
||||||
return timeDiff < 3;
|
|
||||||
});
|
|
||||||
if(date_check){
|
|
||||||
setAlertMsg(t('LAND_AUCTION_DELETE_DATE_WARNING'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(selectedRows[0].status === landAuctionStatusType.auction_start || selectedRows[0].status === landAuctionStatusType.stl_end){
|
|
||||||
setAlertMsg(t('LAND_AUCTION_DELETE_STATUS_WARNING'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
handleModalView('deleteConfirm');
|
|
||||||
break;
|
|
||||||
case "deleteConfirm":
|
|
||||||
let list = [];
|
|
||||||
let isChecked = false;
|
|
||||||
|
|
||||||
selectedRows.map(data => {
|
|
||||||
// const row = dataList.list.find(row => row.id === Number(data.id));
|
|
||||||
// if(row.status !== commonStatus.wait) isChecked = true;
|
|
||||||
list.push({
|
|
||||||
id: data.id,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if(isChecked) {
|
|
||||||
setAlertMsg(t('LAND_AUCTION_WARNING_DELETE'))
|
|
||||||
handleModalClose('deleteConfirm');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await MenuBannerDelete(token, list).then(data => {
|
|
||||||
handleModalClose('deleteConfirm');
|
|
||||||
if(data.result === "SUCCESS") {
|
|
||||||
handleModalView('deleteComplete');
|
|
||||||
}else if(data.result === "ERROR_AUCTION_STATUS_IMPOSSIBLE"){
|
|
||||||
setAlertMsg(t('LAND_AUCTION_ERROR_DELETE_STATUS'));
|
|
||||||
}else{
|
|
||||||
setAlertMsg(t('DELETE_FAIL'));
|
|
||||||
}
|
|
||||||
}).catch(reason => {
|
|
||||||
setAlertMsg(t('API_FAIL'));
|
|
||||||
});
|
|
||||||
|
|
||||||
break;
|
|
||||||
case "deleteComplete":
|
|
||||||
handleModalClose('deleteComplete');
|
|
||||||
window.location.reload();
|
|
||||||
break;
|
|
||||||
case "warning":
|
|
||||||
setAlertMsg('')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleAction = async (action, item = null) => {
|
|
||||||
switch (action) {
|
|
||||||
case "regist":
|
|
||||||
setModalType('regist');
|
|
||||||
handleModalView('detail');
|
|
||||||
break;
|
|
||||||
case "detail":
|
|
||||||
await MenuBannerDetailView(token, item).then(data => {
|
|
||||||
setDetailData(data.event_detail);
|
|
||||||
setModalType('modify');
|
|
||||||
handleModalView('detail');
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "delete":
|
|
||||||
const date_check = selectedRows.every(row => {
|
|
||||||
const timeDiff = timeDiffMinute(convertKTC(row.auction_start_dt), (new Date));
|
|
||||||
return timeDiff < 3;
|
|
||||||
});
|
|
||||||
if(date_check){
|
|
||||||
setAlertMsg(t('LAND_AUCTION_DELETE_DATE_WARNING'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(selectedRows[0].status === landAuctionStatusType.auction_start || selectedRows[0].status === landAuctionStatusType.stl_end){
|
|
||||||
setAlertMsg(t('LAND_AUCTION_DELETE_STATUS_WARNING'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
handleModalView('deleteConfirm');
|
|
||||||
break;
|
|
||||||
case "deleteConfirm":
|
|
||||||
let list = [];
|
|
||||||
let isChecked = false;
|
|
||||||
|
|
||||||
selectedRows.map(data => {
|
|
||||||
// const row = dataList.list.find(row => row.id === Number(data.id));
|
|
||||||
// if(row.status !== commonStatus.wait) isChecked = true;
|
|
||||||
list.push({
|
|
||||||
id: data.id,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if(isChecked) {
|
|
||||||
setAlertMsg(t('LAND_AUCTION_WARNING_DELETE'))
|
|
||||||
handleModalClose('deleteConfirm');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await MenuBannerDelete(token, list).then(data => {
|
|
||||||
handleModalClose('deleteConfirm');
|
|
||||||
if(data.result === "SUCCESS") {
|
|
||||||
handleModalView('deleteComplete');
|
|
||||||
}else if(data.result === "ERROR_AUCTION_STATUS_IMPOSSIBLE"){
|
|
||||||
setAlertMsg(t('LAND_AUCTION_ERROR_DELETE_STATUS'));
|
|
||||||
}else{
|
|
||||||
setAlertMsg(t('DELETE_FAIL'));
|
|
||||||
}
|
|
||||||
}).catch(reason => {
|
|
||||||
setAlertMsg(t('API_FAIL'));
|
|
||||||
});
|
|
||||||
|
|
||||||
break;
|
|
||||||
case "deleteComplete":
|
|
||||||
handleModalClose('deleteComplete');
|
|
||||||
window.location.reload();
|
|
||||||
break;
|
|
||||||
case "warning":
|
|
||||||
setAlertMsg('')
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Title>메뉴 배너 관리</Title>
|
|
||||||
<FormWrapper>
|
|
||||||
<MenuBannerSearchBar
|
|
||||||
searchParams={searchParams}
|
|
||||||
onSearch={(newParams, executeSearch = true) => {
|
|
||||||
if (executeSearch) {
|
|
||||||
handleSearch(newParams);
|
|
||||||
} else {
|
|
||||||
updateSearchParams(newParams);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onReset={handleReset}
|
|
||||||
/>
|
|
||||||
</FormWrapper>
|
|
||||||
{/*<ViewTableInfo total={dataList?.total} total_all={dataList?.total_all} handleOrderBy={handleOrderByChange} handlePageSize={handlePageSizeChange}>*/}
|
|
||||||
{/* {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.battleEventUpdate) && (*/}
|
|
||||||
{/* <Button*/}
|
|
||||||
{/* theme="primary"*/}
|
|
||||||
{/* text="이미지 등록"*/}
|
|
||||||
{/* type="button"*/}
|
|
||||||
{/* handleClick={e => {*/}
|
|
||||||
{/* e.preventDefault();*/}
|
|
||||||
{/* navigate('/servicemanage/menubanner/menubannerregist');*/}
|
|
||||||
{/* }}*/}
|
|
||||||
{/* />*/}
|
|
||||||
{/* )}*/}
|
|
||||||
{/*</ViewTableInfo>*/}
|
|
||||||
<TableHeader
|
|
||||||
config={tableInfo.header}
|
|
||||||
total={dataList?.total}
|
|
||||||
total_all={dataList?.total_all}
|
|
||||||
handleOrderBy={handleOrderByChange}
|
|
||||||
handlePageSize={handlePageSizeChange}
|
|
||||||
selectedRows={selectedRows}
|
|
||||||
onAction={handleAction}
|
|
||||||
navigate={navigate}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<CaliTable
|
|
||||||
columns={tableInfo.columns}
|
|
||||||
data={dataList?.list}
|
|
||||||
selectedRows={selectedRows}
|
|
||||||
onSelectRow={handleSelectRow}
|
|
||||||
onAction={handleAction}
|
|
||||||
refProp={tableRef}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/*<TableWrapper>*/}
|
|
||||||
{/* <TableStyle ref={tableRef}>*/}
|
|
||||||
{/* <caption></caption>*/}
|
|
||||||
{/* <thead>*/}
|
|
||||||
{/* <tr>*/}
|
|
||||||
{/* <th width="40"></th>*/}
|
|
||||||
{/* <th width="70">번호</th>*/}
|
|
||||||
{/* <th width="80">등록 상태</th>*/}
|
|
||||||
{/* <th width="150">시작일(KST)</th>*/}
|
|
||||||
{/* <th width="150">종료일(KST)</th>*/}
|
|
||||||
{/* <th width="300">설명 제목</th>*/}
|
|
||||||
{/* <th width="90">링크여부</th>*/}
|
|
||||||
{/* <th width="100">상세보기</th>*/}
|
|
||||||
{/* <th width="150">히스토리</th>*/}
|
|
||||||
{/* </tr>*/}
|
|
||||||
{/* </thead>*/}
|
|
||||||
{/* <tbody>*/}
|
|
||||||
{/* {dataList?.list?.map(banner => (*/}
|
|
||||||
{/* <tr key={banner.row_num}>*/}
|
|
||||||
{/* <td>*/}
|
|
||||||
{/* <CheckBox name={'select'} id={banner.id}*/}
|
|
||||||
{/* setData={(e) => handleSelectRow(e, banner)}*/}
|
|
||||||
{/* checked={isRowSelected(banner.id)} />*/}
|
|
||||||
{/* </td>*/}
|
|
||||||
{/* <td>{banner.row_num}</td>*/}
|
|
||||||
{/* <StatusWapper>*/}
|
|
||||||
{/* <StatusLabel $status={banner.status}>*/}
|
|
||||||
{/* {opMenuBannerStatus.find(data => data.value === banner.status)?.name}*/}
|
|
||||||
{/* </StatusLabel>*/}
|
|
||||||
{/* </StatusWapper>*/}
|
|
||||||
{/* <td>{convertKTC(banner.start_dt)}</td>*/}
|
|
||||||
{/* <td>{convertKTC(banner.end_dt)}</td>*/}
|
|
||||||
{/* <td>{banner.title}</td>*/}
|
|
||||||
{/* <td>{opYNType.find(data => data.value === banner.is_link)?.name}</td>*/}
|
|
||||||
{/* <td>*/}
|
|
||||||
{/* <Button theme="line" text="상세보기"*/}
|
|
||||||
{/* handleClick={e => handleModalSubmit('detail', banner.id)} />*/}
|
|
||||||
{/* </td>*/}
|
|
||||||
{/* <td>{banner.update_by}</td>*/}
|
|
||||||
{/* </tr>*/}
|
|
||||||
{/* ))}*/}
|
|
||||||
{/* </tbody>*/}
|
|
||||||
{/* </TableStyle>*/}
|
|
||||||
{/*</TableWrapper>*/}
|
|
||||||
|
|
||||||
<Pagination postsPerPage={searchParams.pageSize} totalPosts={dataList?.total_all} setCurrentPage={handlePageChange} currentPage={searchParams.currentPage} pageLimit={INITIAL_PAGE_LIMIT} />
|
|
||||||
|
|
||||||
{/*상세*/}
|
|
||||||
<MenuBannerModal modalType={modalType} detailView={modalState.detailModal} handleDetailView={() => handleModalClose('detail')} content={detailData} setDetailData={setDetailData} />
|
|
||||||
|
|
||||||
{/*삭제 확인*/}
|
|
||||||
<DynamicModal
|
|
||||||
modalType={modalTypes.confirmOkCancel}
|
|
||||||
view={modalState.deleteConfirmModal}
|
|
||||||
handleCancel={() => handleModalClose('deleteConfirm')}
|
|
||||||
handleSubmit={() => handleModalSubmit('deleteConfirm')}
|
|
||||||
modalText={t('MENU_BANNER_SELECT_DELETE')}
|
|
||||||
/>
|
|
||||||
{/*삭제 완료*/}
|
|
||||||
<DynamicModal
|
|
||||||
modalType={modalTypes.completed}
|
|
||||||
view={modalState.deleteCompleteModal}
|
|
||||||
handleSubmit={() => handleModalSubmit('deleteComplete')}
|
|
||||||
modalText={t('DEL_COMPLETE')}
|
|
||||||
/>
|
|
||||||
{/* 경고 모달 */}
|
|
||||||
<DynamicModal
|
|
||||||
modalType={modalTypes.completed}
|
|
||||||
view={alertMsg ? 'view' : 'hidden'}
|
|
||||||
modalText={alertMsg}
|
|
||||||
handleSubmit={() => handleModalSubmit('warning')}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
export default withAuth(authType.battleEventRead)(MenuBanner);
|
|
||||||
Reference in New Issue
Block a user