diff --git a/src/apis/Dictionary.js b/src/apis/Dictionary.js index a1ddcd1..f4bea94 100644 --- a/src/apis/Dictionary.js +++ b/src/apis/Dictionary.js @@ -1,6 +1,6 @@ //운영 정보 관리 - 백과사전 api 연결 -import { Axios } from '../utils'; +import { Axios, responseFileDownload } from '../utils'; // 아이템 백과사전 조회 export const getItemDictionaryList = async (token, searchType, searchData, largeType, smallType, brand, gender, order, size, currentPage) => { @@ -21,6 +21,25 @@ export const getItemDictionaryList = async (token, searchType, searchData, large } }; +export const ItemDictionaryExport = async (token, params) => { + try { + await Axios.get(`/api/v1/dictionary/item/excel-export?search_type=${params.search_type}&search_data=${params.search_data} + &large_type=${params.large_type}&small_type=${params.small_type}&brand=${params.brand}&gender=${params.gender} + &lang=${params.lang}&task_id=${params.taskId}`, { + headers: { Authorization: `Bearer ${token}` }, + responseType: 'blob' + }).then(response => { + responseFileDownload(response, { + defaultFileName: 'itemDictionary' + }); + }); + } catch (e) { + if (e instanceof Error) { + throw new Error('ItemDictionaryExport Error', e); + } + } +}; + export const BrandView = async (token) => { try { const res = await Axios.get( diff --git a/src/assets/data/options.js b/src/assets/data/options.js index 7013dc1..c380a07 100644 --- a/src/assets/data/options.js +++ b/src/assets/data/options.js @@ -4,6 +4,20 @@ export const languageType = [ { value: 'JA', name: '일본어' }, ]; +export const TabUserList = [ + { value: 'BASIC', name: '기본정보' }, + { value: 'AVATAR', name: '아바타' }, + { value: 'CLOTH', name: '의상' }, + { value: 'TOOL', name: '도구' }, + { value: 'INVENTORY', name: '인벤토리' }, + { value: 'MAIL', name: '우편' }, + { value: 'MYHOME', name: '마이홈' }, + { value: 'FRIEND', name: '친구목록' }, + { value: 'TATTOO', name: '타투' }, + { value: 'QUEST', name: '퀘스트' } + // { value: 'CLAIM', name: '클레임' } +]; + export const TabGameLogList = [ { value: 'CURRENCY', name: '재화 로그' }, { value: 'ITEM', name: '아이템 로그' }, @@ -30,6 +44,12 @@ export const TabUserIndexList = [ // { value: 'PLAYTIME', name: '플레이타임' }, ]; +export const TabRankManageList = [ + { value: 'PIONEER', name: '개척자 랭킹 보드' }, + { value: 'RUN_RACE', name: '점프 러너 랭킹 보드' }, + { value: 'BATTLE_OBJECT', name: '컴뱃 존 랭킹 보드' } +]; + export const mailSendType = [ { value: 'ALL', name: '전체' }, { value: 'RESERVE_SEND', name: '예약 발송' }, @@ -615,7 +635,10 @@ export const opLogAction = [ export const opCommonStatus = [ { value: 'SUCCESS', name: '성공' }, - { value: 'FAIL', name: '실패' } + { value: 'FAIL', name: '실패' }, + { value: 'WAIT', name: '대기' }, + { value: 'END', name: '종료' }, + { value: 'RUNNING', name: '진행중' }, ] // export const logAction = [ diff --git a/src/assets/data/types.js b/src/assets/data/types.js index 7070779..41e99ae 100644 --- a/src/assets/data/types.js +++ b/src/assets/data/types.js @@ -53,6 +53,14 @@ export const authType = { menuBannerUpdate: 51, menuBannerDelete: 52, itemDictionaryRead: 53, + rankManagerRead: 54, + rankManagerUpdate: 55, + rankingRead: 56, + rankingUpdate: 57, + rankingDelete: 58, + worldEventRead: 59, + worldEventUpdate: 60, + worldEventDelete: 61, levelReader: 999, @@ -76,20 +84,6 @@ export const adminAuthLevel = { DEVELOPER: "Developer", } -export const TabUserList = [ - { title: '기본정보' }, - { title: '아바타' }, - { title: '의상' }, - { title: '도구' }, - { title: '인벤토리' }, - { title: '우편' }, - { title: '마이홈' }, - { title: '친구목록' }, - { title: '타투' }, - { title: '퀘스트' }, - // { title: '클레임' }, -]; - export const ivenTabType = { CLOTH: "cloth", PROP: "prop", diff --git a/src/components/searchBar/BusinessLogSearchBar.js b/src/components/searchBar/BusinessLogSearchBar.js index 9e8dd5d..0b318de 100644 --- a/src/components/searchBar/BusinessLogSearchBar.js +++ b/src/components/searchBar/BusinessLogSearchBar.js @@ -1,11 +1,15 @@ import { TextInput, InputLabel, SelectInput, InputGroup } from '../../styles/Components'; import { SearchBarLayout, SearchPeriod } from '../common/SearchBar'; -import { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { logAction, logDomain, userSearchType2 } from '../../assets/data/options'; import { BusinessLogList } from '../../apis/Log'; import {SearchFilter} from '../ServiceManage'; import { useAlert } from '../../context/AlertProvider'; import { alertTypes } from '../../assets/data/types'; +import dayjs from 'dayjs'; +import { DatePicker } from 'antd'; +import DateRangePicker from '../common/Date/DateRangePicker'; +const { RangePicker } = DatePicker; export const useBusinessLogSearch = (token, initialPageSize) => { const {showToast} = useAlert(); @@ -16,16 +20,8 @@ export const useBusinessLogSearch = (token, initialPageSize) => { log_action: 'None', log_domain: 'BASE', tran_id: '', - start_dt: (() => { - const date = new Date(); - date.setDate(date.getDate() - 1); - return date; - })(), - end_dt: (() => { - const date = new Date(); - date.setDate(date.getDate() - 1); - return date; - })(), + start_dt: dayjs().subtract(1, 'day').startOf('day'), + end_dt: dayjs().subtract(1, 'day').endOf('day'), filters: [], order_by: 'ASC', page_size: initialPageSize, @@ -92,16 +88,14 @@ export const useBusinessLogSearch = (token, initialPageSize) => { }, [searchParams, fetchData]); const handleReset = useCallback(async () => { - const now = new Date(); - now.setDate(now.getDate() - 1); const resetParams = { search_type: 'GUID', search_data: '', log_action: 'None', log_domain: 'BASE', tran_id: '', - start_dt: now, - end_dt: now, + start_dt: dayjs().subtract(1, 'day').startOf('day'), + end_dt: dayjs().subtract(1, 'day').endOf('day'), filters: [], order_by: 'ASC', page_size: initialPageSize, @@ -197,11 +191,11 @@ const BusinessLogSearchBar = ({ searchParams, onSearch, onReset }) => { , <> 일자 - onSearch({ start_dt: date }, false)} - endDate={searchParams.end_dt} - handleEndDate={date => onSearch({ end_dt: date }, false)} + { + onSearch({ start_dt: dates[0], end_dt: dates[1] }, false); + }} /> , ]; diff --git a/src/hooks/useCommonSearch.js b/src/hooks/useCommonSearch.js index 12a29d2..f3db923 100644 --- a/src/hooks/useCommonSearch.js +++ b/src/hooks/useCommonSearch.js @@ -4,6 +4,7 @@ import { useAlert } from '../context/AlertProvider'; import { alertTypes } from '../assets/data/types'; import * as APIConfigs from '../assets/data/apis' import { callAPI } from '../utils/apiService'; +import dayjs from 'dayjs'; export const useCommonSearch = (configPath) => { const [config, setConfig] = useState(null); @@ -24,7 +25,9 @@ export const useCommonSearch = (configPath) => { // 초기 검색 파라미터 설정 if (configData.initialSearchParams) { - setSearchParams(configData.initialSearchParams); + const processedParams = processTodayValues(configData.initialSearchParams); + setSearchParams(processedParams); + } // API 엔드포인트 설정 가져오기 @@ -50,6 +53,27 @@ export const useCommonSearch = (configPath) => { fetchConfig(); }, [configPath]); + const processTodayValues = useCallback((params) => { + const processedParams = { ...params }; + + Object.keys(processedParams).forEach(key => { + if (processedParams[key] === 'today') { + if (key.toLowerCase().includes('start')) { + // start가 포함된 키는 00:00:00으로 설정 + processedParams[key] = dayjs().startOf('day').format('YYYY-MM-DD HH:mm:ss'); + } else if (key.toLowerCase().includes('end')) { + // end가 포함된 키는 23:59:59로 설정 + processedParams[key] = dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss'); + } else { + // 그 외는 현재 시간으로 설정 + processedParams[key] = dayjs().format('YYYY-MM-DD HH:mm:ss'); + } + } + }); + + return processedParams; + }, []); + // 파라미터 값 변환 (날짜 등) const transformParams = useCallback((params) => { if (!config || !config.apiInfo || !config.apiInfo.paramTransforms) { diff --git a/src/hooks/useRDSPagination.js b/src/hooks/useRDSPagination.js index 21303db..54c9209 100644 --- a/src/hooks/useRDSPagination.js +++ b/src/hooks/useRDSPagination.js @@ -40,8 +40,8 @@ export const useRDSPagination = (fetchFunction, initialState = {}) => { setPagination(prev => ({ ...prev, currentPage: page, - totalItems: response.total_all || response.total || 0, - totalPages: response.total_pages || Math.ceil((response.total_all || response.total || 0) / pagination.pageSize) + totalItems: response?.total_all || response?.total || 0, + totalPages: response?.total_pages || Math.ceil((response?.total_all || response?.total || 0) / pagination.pageSize) })); return response; diff --git a/src/i18n.js b/src/i18n.js index 76d8599..0c04af8 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -141,6 +141,13 @@ const resources = { BATTLE_EVENT_STOP_5MINUTES_DATE_WARNING: "이벤트 시작 5분 전에는 중단할 수 없습니다.", BATTLE_EVENT_STATUS_RUNNING_WARNING: "이벤트 진행중에는 중단할 수 없습니다.", BATTLE_EVENT_MODAL_STATUS_WARNING: "이벤트가 중단일때만 수정이 가능합니다.", + //이벤트 + EVENT_MODAL_STATUS_WARNING: "이벤트가 대기일때만 수정이 가능합니다.", + //랭킹 스케줄 + SCHEDULE_MODAL_STATUS_WARNING: "스케줄이 대기일때만 수정이 가능합니다.", + SCHEDULE_SELECT_DELETE: "선택된 스케줄을 삭제하시겠습니까?", + SCHEDULE_REGIST_CONFIRM: "스케줄을 등록하시겠습니까?", + SCHEDULE_UPDATE_CONFIRM: "스케줄을 수정하시겠습니까?", //메뉴 배너 MENU_BANNER_TITLE: "메뉴 배너 관리", MENU_BANNER_CREATE: "메뉴 배너 등록", @@ -188,6 +195,7 @@ const resources = { FILE_DICTIONARY_ITEM: 'Caliverse_Dictionary_Item', //서버 에러메시지 DYNAMODB_NOT_USER: '유저 정보를 확인해주세요.', + NOT_USER: '유저 정보를 확인해주세요.', NICKNAME_EXIT_ERROR: '해당 닉네임이 존재합니다.', NICKNAME_NUMBER_ERROR: '닉네임은 첫번째 글자에 숫자를 허용하지 않습니다.', NICKNAME_SPECIALCHAR_ERROR: '닉네임은 특수문자를 사용할 수 없습니다.', diff --git a/src/pages/DataManage/MetaItemView.js b/src/pages/DataManage/MetaItemView.js index dcb3137..80a6b96 100644 --- a/src/pages/DataManage/MetaItemView.js +++ b/src/pages/DataManage/MetaItemView.js @@ -21,7 +21,6 @@ import { import { useTranslation } from 'react-i18next'; import { AnimatedTabs, - TopButton, ViewTableInfo, } from '../../components/common'; import { TableSkeleton } from '../../components/Skeleton/TableSkeleton'; @@ -34,11 +33,11 @@ import ExcelExportButton from '../../components/common/button/ExcelExportButton' import Pagination from '../../components/common/Pagination/Pagination'; import { useItemDictionarySearch, ItemDictionarySearchBar } from '../../components/searchBar'; import { numberFormatter } from '../../utils'; -import { BrandView } from '../../apis'; +import { BrandView, ItemDictionaryExport } from '../../apis'; import { opGender, opItemLargeType, opItemSmallType } from '../../assets/data/options'; import { languageNames } from '../../assets/data/types'; -const BusinessLogView = () => { +const MetaItemView = () => { const token = sessionStorage.getItem('token'); const { t } = useTranslation(); const tableRef = useRef(null); @@ -232,6 +231,11 @@ const BusinessLogView = () => { setActiveLanguage(key); }; + const excelParams = useMemo(() => ({ + ...searchParams, + lang: activeLanguage + }), [searchParams, activeLanguage]); + return ( 아이템 백과사전 조회 @@ -252,12 +256,8 @@ const BusinessLogView = () => { { - const params = searchParams; - params.lang = activeLanguage; - return params; - }} + functionName="ItemDictionaryExport" + params={excelParams} fileName={t('FILE_DICTIONARY_ITEM')} onLoadingChange={setDownloadState} dataSize={dataList?.total_all} @@ -282,78 +282,8 @@ const BusinessLogView = () => { tabPosition="left" /> } - - - {/*{dataLoading ? :*/} - {/* <>*/} - {/* */} - {/* */} - {/* */} - {/* */} - {/* {tableHeaders.map(header => (*/} - {/* {header.label}*/} - {/* ))}*/} - {/* */} - {/* */} - {/* */} - {/* {dataList?.item_list?.map((item, index) => (*/} - {/* */} - {/* */} - {/* {opItemLargeType.find(data => data.value === item.type_large)?.name}*/} - {/* {opItemSmallType.find(data => data.value === item.type_small)?.name}*/} - {/* {item.item_name}*/} - {/* {item.item_id}*/} - {/* {item.brand === '' ? '-' : item.brand}*/} - {/* {opGender.find(data => data.value === item.gender)?.name || '남녀공용'}*/} - {/* {item.sell_type}*/} - {/* {numberFormatter.formatCurrency(item.sell_price)}*/} - {/* {item.buy_type}*/} - {/* {numberFormatter.formatCurrency(item.buy_price)}*/} - {/* {item.buy_discount_rate}*/} - {/* */} - {/* toggleRowExpand(index)}>*/} - {/* {expandedRows[index] ? '접기' : '상세보기'}*/} - {/* */} - {/* */} - {/* */} - {/* {expandedRows[index] && (*/} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* {renderDetailInfo(item.country, "Count 정보", "country", index)}*/} - {/* {renderDetailInfo(item.expire, "아이템 만료 정보", "expire", index)}*/} - {/* {renderDetailInfo(item.trade, "Trade 정보", "trade", index)}*/} - {/* */} - {/* */} - {/* {renderDetailInfo(item.attrib, "속성 정보", "attrib", index)}*/} - {/* {renderDetailInfo(item.etc, "기타 정보", "etc", index)}*/} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* )}*/} - {/* */} - {/* ))}*/} - {/* */} - {/* */} - {/* */} - {/* {dataList?.item_list &&*/} - {/* */} - {/* }*/} - {/* */} - {/* */} - {/*}*/} ); }; -export default withAuth(authType.businessLogRead)(BusinessLogView); \ No newline at end of file +export default withAuth(authType.itemDictionaryRead)(MetaItemView); \ No newline at end of file diff --git a/src/styles/Components.js b/src/styles/Components.js index 51cdab8..6cce53f 100644 --- a/src/styles/Components.js +++ b/src/styles/Components.js @@ -727,11 +727,13 @@ export const SearchRow = styled.div` flex-wrap: wrap; gap: 20px 0; - &:last-child { - border-top: 1px solid #e0e0e0; - padding-top: 15px; - margin-top: 15px; - } + ${props => props.direction === 'column' && css` + &:last-child { + border-top: 1px solid #e0e0e0; + padding-top: 15px; + margin-top: 15px; + } + `} `; export const TabScroll = styled.div`