From f4b629df52db04316a4fbd8e6efe582841e0a738 Mon Sep 17 00:00:00 2001 From: bcjang Date: Mon, 4 Aug 2025 17:40:37 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B2=BD=EC=A0=9C=EC=A7=80=ED=91=9C=20?= =?UTF-8?q?=EC=9E=AC=ED=99=94=20=EB=B3=B4=EC=9C=A0=20=EA=B2=BD=EC=A0=9C?= =?UTF-8?q?=EC=A7=80=ED=91=9C=20=EC=95=84=EC=9D=B4=ED=85=9C=20=EB=B3=B4?= =?UTF-8?q?=EC=9C=A0=20=EA=B2=8C=EC=9E=84=EB=A1=9C=EA=B7=B8=20=EC=8A=A4?= =?UTF-8?q?=EB=83=85=EC=83=B7=20=ED=9E=88=EC=8A=A4=ED=86=A0=EB=A6=AC=20?= =?UTF-8?q?=EB=B9=84=EC=A6=88=EB=8B=88=EC=8A=A4=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=EA=B8=B0=EC=A4=80=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/Indicators.js | 243 ++--------- src/apis/Log.js | 38 +- src/assets/data/options.js | 66 ++- src/assets/data/pages/historyTable.json | 29 +- .../DataManage/UserSnapshotLogContent.js | 153 +++++++ src/components/IndexManage/CreditContent.js | 4 +- .../IndexManage/CurrencyAcquireContent.js | 126 ++++++ .../IndexManage/CurrencyAssetsContent.js | 109 +++++ .../IndexManage/CurrencyConsumeContent.js | 128 ++++++ .../IndexManage/DailyActiveUserContent.js | 110 ----- .../IndexManage/DailyCaliumDashBoard.js | 141 +++++++ src/components/IndexManage/DailyDashBoard.js | 1 - .../IndexManage/DailyMedalContent.js | 111 ----- .../IndexManage/ItemAcquireContent.js | 152 +++++++ .../IndexManage/ItemAssetsContent.js | 119 ++++++ .../IndexManage/ItemConsumeContent.js | 143 +++++++ src/components/IndexManage/PlayTimeContent.js | 112 ----- .../IndexManage/RetentionContent.js | 4 +- src/components/IndexManage/SegmentContent.js | 90 ---- src/components/IndexManage/UserContent.js | 12 +- src/components/IndexManage/VBPContent.js | 219 ---------- src/components/IndexManage/index.js | 28 +- src/components/common/button/CsvDownButton.js | 390 ++++++++++++++++++ src/components/common/modal/LogDetailModal.js | 14 +- .../searchBar/AssetsIndexSearchBar.js | 150 +++++++ .../CurrencyAcquireIndexSearchBar.js | 165 ++++++++ .../CurrencyConsumeIndexSearchBar.js | 165 ++++++++ ...chBar.js => CurrencyUserIndexSearchBar.js} | 4 +- .../searchBar/ItemAcquireIndexSearchBar.js | 171 ++++++++ .../searchBar/ItemConsumeIndexSearchBar.js | 171 ++++++++ .../searchBar/UserSnapshotLogSearchBar.js | 175 ++++++++ src/components/searchBar/index.js | 38 +- src/i18n.js | 12 +- src/pages/DataManage/GameLogView.js | 2 + src/pages/IndexManage/EconomicIndex.js | 39 +- src/pages/IndexManage/UserIndex.js | 8 +- src/pages/UserManage/CaliumRequest.js | 5 +- src/pages/UserManage/LogView.js | 2 +- src/pages/UserManage/LogView_bak.js | 170 -------- src/styles/Components.js | 22 + 40 files changed, 2710 insertions(+), 1131 deletions(-) create mode 100644 src/components/DataManage/UserSnapshotLogContent.js create mode 100644 src/components/IndexManage/CurrencyAcquireContent.js create mode 100644 src/components/IndexManage/CurrencyAssetsContent.js create mode 100644 src/components/IndexManage/CurrencyConsumeContent.js delete mode 100644 src/components/IndexManage/DailyActiveUserContent.js create mode 100644 src/components/IndexManage/DailyCaliumDashBoard.js delete mode 100644 src/components/IndexManage/DailyMedalContent.js create mode 100644 src/components/IndexManage/ItemAcquireContent.js create mode 100644 src/components/IndexManage/ItemAssetsContent.js create mode 100644 src/components/IndexManage/ItemConsumeContent.js delete mode 100644 src/components/IndexManage/PlayTimeContent.js delete mode 100644 src/components/IndexManage/SegmentContent.js delete mode 100644 src/components/IndexManage/VBPContent.js create mode 100644 src/components/common/button/CsvDownButton.js create mode 100644 src/components/searchBar/AssetsIndexSearchBar.js create mode 100644 src/components/searchBar/CurrencyAcquireIndexSearchBar.js create mode 100644 src/components/searchBar/CurrencyConsumeIndexSearchBar.js rename src/components/searchBar/{CurrencyIndexSearchBar.js => CurrencyUserIndexSearchBar.js} (96%) create mode 100644 src/components/searchBar/ItemAcquireIndexSearchBar.js create mode 100644 src/components/searchBar/ItemConsumeIndexSearchBar.js create mode 100644 src/components/searchBar/UserSnapshotLogSearchBar.js delete mode 100644 src/pages/UserManage/LogView_bak.js diff --git a/src/apis/Indicators.js b/src/apis/Indicators.js index 27f24d3..e623724 100644 --- a/src/apis/Indicators.js +++ b/src/apis/Indicators.js @@ -36,6 +36,19 @@ export const userTotalIndex = async token => { } }; +export const dashboardCaliumIndex = async token => { + try { + const res = await Axios.get(`/api/v1/indicators/dashboard/calium/converter`, { + headers: { Authorization: `Bearer ${token}` }, + }); + return res.data.data; + } catch (e) { + if (e instanceof Error) { + throw new Error('dashboardCaliumIndex', e); + } + } +}; + // 유저 지표 다운로드 export const userIndexExport = async (token, filename, sendDate, endDate) => { try { @@ -187,10 +200,10 @@ export const PlaytimeIndexExport = async (token, filename, sendDate, endDate) => // 2. 경제 지표 -// 재화 조회 (currency) -export const CurrencyIndexView = async (token, start_dt, end_dt, currency_type) => { +// 재화 획득 조회 +export const CurrencyAcquireIndexView = async (token, start_dt, end_dt, currencyType, deltaType) => { try { - const res = await Axios.get(`/api/v1/indicators/currency/use?start_dt=${start_dt}&end_dt=${end_dt}¤cy_type=${currency_type}`, { + const res = await Axios.get(`/api/v1/indicators/currency/list?start_dt=${start_dt}&end_dt=${end_dt}¤cy_type=${currencyType}&delta_type=${deltaType}`, { headers: { Authorization: `Bearer ${token}` }, }); @@ -202,75 +215,10 @@ export const CurrencyIndexView = async (token, start_dt, end_dt, currency_type) } }; -// 재화 지표 다운로드 -export const CurrencyIndexExport = async (token, filename, sendDate, endDate, currencyType) => { - try { - await Axios.get(`/api/v1/indicators/currency/excel-down?file=${filename}&start_dt=${sendDate}&end_dt=${endDate}¤cy_type=${currencyType}`, { - headers: { Authorization: `Bearer ${token}` }, - responseType: 'blob', - }).then(response => { - const href = URL.createObjectURL(response.data); - - const link = document.createElement('a'); - link.href = href; - link.setAttribute('download', `${filename}`); - document.body.appendChild(link); - link.click(); - - document.body.removeChild(link); - URL.revokeObjectURL(href); - }); - } catch (e) { - if (e instanceof Error) { - throw new Error('CurrencyIndexExport Error', e); - } - } -}; - -// VBP -export const VbpIndexView = async (token, start_dt, end_dt) => { - try { - const res = await Axios.get(`/api/v1/indicators/currency/vbp?start_dt=${start_dt}&end_dt=${end_dt}`, { - headers: { Authorization: `Bearer ${token}` }, - }); - - return res.data.data; - } catch (e) { - if (e instanceof Error) { - throw new Error('VbpIndexView Error', e); - } - } -}; - -// VBP 다운로드 -export const VBPIndexExport = async (token, filename, sendDate, endDate) => { - try { - await Axios.get(`/api/v1/indicators/currency/excel-down?file=${filename}&start_dt=${sendDate}&end_dt=${endDate}`, { - headers: { Authorization: `Bearer ${token}` }, - responseType: 'blob', - }).then(response => { - const href = URL.createObjectURL(response.data); - - const link = document.createElement('a'); - link.href = href; - link.setAttribute('download', `${filename}`); - document.body.appendChild(link); - link.click(); - - document.body.removeChild(link); - URL.revokeObjectURL(href); - }); - } catch (e) { - if (e instanceof Error) { - throw new Error('VBPIndexExport Error', e); - } - } -}; - // Item -export const ItemIndexView = async (token, start_dt, end_dt) => { +export const ItemIndexView = async (token, start_dt, end_dt, itemId, deltaType) => { try { - const res = await Axios.get(`/api/v1/indicators/currency/item?start_dt=${start_dt}&end_dt=${end_dt}`, { + const res = await Axios.get(`/api/v1/indicators/item/list?start_dt=${start_dt}&end_dt=${end_dt}&item_id=${itemId}&delta_type=${deltaType}`, { headers: { Authorization: `Bearer ${token}` }, }); @@ -282,27 +230,17 @@ export const ItemIndexView = async (token, start_dt, end_dt) => { } }; -// Item 다운로드 -export const ItemIndexExport = async (token, filename, sendDate, endDate) => { +// Assets +export const AssetsIndexView = async (token, start_dt, end_dt, itemId, deltaType) => { try { - await Axios.get(`/api/v1/indicators/currency/excel-down?file=${filename}&start_dt=${sendDate}&end_dt=${endDate}`, { + const res = await Axios.get(`/api/v1/indicators/assets/list?start_dt=${start_dt}&end_dt=${end_dt}`, { headers: { Authorization: `Bearer ${token}` }, - responseType: 'blob', - }).then(response => { - const href = URL.createObjectURL(response.data); - - const link = document.createElement('a'); - link.href = href; - link.setAttribute('download', `${filename}`); - document.body.appendChild(link); - link.click(); - - document.body.removeChild(link); - URL.revokeObjectURL(href); }); + + return res.data.data; } catch (e) { if (e instanceof Error) { - throw new Error('ItemIndexExport Error', e); + throw new Error('AssetsIndexView Error', e); } } }; @@ -324,137 +262,4 @@ export const InstanceIndexView = async (token, data, start_dt, end_dt) => { throw new Error('InstanceIndexView Error', e); } } -}; - -// Instance 다운로드 -export const InstanceIndexExport = async (token, filename, data, sendDate, endDate) => { - try { - await Axios.get( - `/api/v1/indicators/currency/excel-down?file=${filename}&search_key=${data ? data : ''} - &start_dt=${sendDate}&end_dt=${endDate}`, - { - headers: { Authorization: `Bearer ${token}` }, - responseType: 'blob', - }, - ).then(response => { - const href = URL.createObjectURL(response.data); - - const link = document.createElement('a'); - link.href = href; - link.setAttribute('download', `${filename}`); - document.body.appendChild(link); - link.click(); - - document.body.removeChild(link); - URL.revokeObjectURL(href); - }); - } catch (e) { - if (e instanceof Error) { - throw new Error('InstanceIndexExport Error', e); - } - } -}; - -// Clothes -export const ClothesIndexView = async (token, data, start_dt, end_dt) => { - try { - const res = await Axios.get(`/api/v1/indicators/currency/clothes?search_key=${data ? data : ''}&start_dt=${start_dt}&end_dt=${end_dt}`, { - headers: { Authorization: `Bearer ${token}` }, - }); - - return res.data.data; - } catch (e) { - if (e instanceof Error) { - throw new Error('ClothesIndexView Error', e); - } - } -}; - -// Clothes 다운로드 -export const ClothesIndexExport = async (token, filename, data, sendDate, endDate) => { - try { - await Axios.get( - `/api/v1/indicators/currency/excel-down?file=${filename}&search_key=${data ? data : ''} - &start_dt=${sendDate}&end_dt=${endDate}`, - { - headers: { Authorization: `Bearer ${token}` }, - responseType: 'blob', - }, - ).then(response => { - const href = URL.createObjectURL(response.data); - - const link = document.createElement('a'); - link.href = href; - link.setAttribute('download', `${filename}`); - document.body.appendChild(link); - link.click(); - - document.body.removeChild(link); - URL.revokeObjectURL(href); - }); - } catch (e) { - if (e instanceof Error) { - throw new Error('ClothesIndexExport Error', e); - } - } -}; - - -// DAU -export const DailyActiveUserView = async (token, start_dt, end_dt) => { - try { - const res = await Axios.get(`/api/v1/indicators/dau/list?start_dt=${start_dt}&end_dt=${end_dt}`, { - headers: { Authorization: `Bearer ${token}` }, - }); - - return res.data.data.dau_list; - } catch (e) { - if (e instanceof Error) { - throw new Error('DailyActiveUserView Error', e); - } - } -}; - - - -// DAU 다운로드 -export const DailyActiveUserExport = async (token, filename, sendDate, endDate) => { - try { - await Axios.get(`/api/v1/indicators/dau/excel-down?file=${filename}&start_dt=${sendDate}&end_dt=${endDate}`, { - headers: { Authorization: `Bearer ${token}` }, - responseType: 'blob', - }).then(response => { - const href = URL.createObjectURL(response.data); - - const link = document.createElement('a'); - link.href = href; - link.setAttribute('download', `${filename}`); - document.body.appendChild(link); - link.click(); - - document.body.removeChild(link); - URL.revokeObjectURL(href); - }); - } catch (e) { - if (e instanceof Error) { - throw new Error('PlaytimeIndexExport Error', e); - } - } -}; - - - -// Daily Medal -export const DailyMedalView = async (token, start_dt, end_dt) => { - try { - const res = await Axios.get(`/api/v1/indicators/daily-medal/list?start_dt=${start_dt}&end_dt=${end_dt}`, { - headers: { Authorization: `Bearer ${token}` }, - }); - - return res.data.data.daily_medal_list; - } catch (e) { - if (e instanceof Error) { - throw new Error('DailyMedalView Error', e); - } - } }; \ No newline at end of file diff --git a/src/apis/Log.js b/src/apis/Log.js index bf569ca..4f2ceea 100644 --- a/src/apis/Log.js +++ b/src/apis/Log.js @@ -242,7 +242,6 @@ export const getUserLoginDetailList = async (token, searchType, searchData, tran export const GameUserCreateLogExport = async (token, params, fileName) => { try { - console.log(params); await Axios.post(`/api/v1/log/user/create/excel-export`, params, { headers: { Authorization: `Bearer ${token}` }, responseType: 'blob', @@ -262,7 +261,6 @@ export const GameUserCreateLogExport = async (token, params, fileName) => { export const GameUserLoginLogExport = async (token, params, fileName) => { try { - console.log(params); await Axios.post(`/api/v1/log/user/login/excel-export`, params, { headers: { Authorization: `Bearer ${token}` }, responseType: 'blob', @@ -278,4 +276,40 @@ export const GameUserLoginLogExport = async (token, params, fileName) => { throw new Error('GameUserLoginLogExport Error', e); } } +}; + +export const getUserSnapshotList = async (token, searchType, searchData, startDate, endDate, order, size, currentPage) => { + try { + const response = await Axios.get(`/api/v1/log/user/snapshot/list?search_type=${searchType}&search_data=${searchData}&start_dt=${startDate}&end_dt=${endDate} + &orderby=${order}&page_no=${currentPage}&page_size=${size}`, { + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + }); + + return response.data; + } catch (error) { + console.error('getUserSnapshotList API error:', error); + throw error; + } +}; + +export const GameUserSnapshotLogExport = async (token, params, fileName) => { + try { + await Axios.post(`/api/v1/log/user/snapshot/excel-export`, params, { + headers: { Authorization: `Bearer ${token}` }, + responseType: 'blob', + timeout: 300000 + }).then(response => { + + responseFileDownload(response, { + defaultFileName: fileName + }); + }); + } catch (e) { + if (e instanceof Error) { + throw new Error('GameUserSnapshotLogExport Error', e); + } + } }; \ No newline at end of file diff --git a/src/assets/data/options.js b/src/assets/data/options.js index 13c7e64..ce078bb 100644 --- a/src/assets/data/options.js +++ b/src/assets/data/options.js @@ -10,19 +10,22 @@ export const TabGameLogList = [ { value: 'CURRENCYITEM', name: '재화(아이템) 로그' }, { value: 'USERCREATE', name: '유저생성 로그' }, { value: 'USERLOGIN', name: '유저로그인 로그' }, + { value: 'SNAPSHOT', name: '스냅샷 로그' }, ]; export const TabEconomicIndexList = [ - { value: 'CURRENCY', name: '재화(유저)' }, - // { value: 'ITEM', name: '아이템' }, - // { value: 'VBP', name: 'VBP' }, - // { value: 'deco', name: '의상/타투' }, - // { value: 'instance', name: '인스턴스' }, + { value: 'CURRENCY_ACQUIRE', name: '재화 획득' }, + { value: 'CURRENCY_CONSUME', name: '재화 소모' }, + { value: 'ITEM_ACQUIRE', name: '아이템 획득' }, + { value: 'ITEM_CONSUME', name: '아이템 소모' }, + { value: 'CURRENCY_ASSETS', name: '재화 보유' }, + { value: 'ITEM_ASSETS', name: '아이템 보유' }, ]; export const TabUserIndexList = [ { value: 'USER', name: '이용자 지표' }, { value: 'RETENTION', name: '잔존율' }, + { value: 'CURRENCY', name: '재화' }, // { value: 'SEGMENT', name: 'Segment' }, // { value: 'PLAYTIME', name: '플레이타임' }, ]; @@ -468,6 +471,59 @@ export const opDBType = [ { value: 'MySql', name: 'MySql'}, ] +export const opLogCategory = [ + { value: 'SCHEDULER', name: '스케줄러'}, + { value: 'DYNAMODB', name: 'DynamoDB'}, + { value: 'MARIADB', name: 'MariaDB'}, + { value: 'MESSAGE_QUEUE', name: '메시지큐'}, + { value: 'REDIS', name: 'Redis'}, + { value: 'S3', name: 'S3'}, + { value: 'BATCH_JOB', name: '배치잡'}, +] + +export const opLogAction = [ + { value: 'KICK_USER', name: '유저킥' }, + { value: 'ADMIN_LEVEL', name: 'GM 레벨' }, + { value: 'NICKNAME_CHANGE', name: '아바타명 변경' }, + { value: 'MAIL_ITEM', name: '메일 아이템' }, + { value: 'QUEST_TASK', name: '퀘스트 Task' }, + { value: 'SCHEDULE_CLEANUP', name: '스케줄 캐시정리' }, + { value: 'SCHEDULE_DATA_INIT', name: '스케줄 데이터 초기화' }, + { value: 'SCHEDULE_LAND_OWNER_CHANGE', name: '스케줄 랜드 소유자 변경' }, + { value: 'SCHEDULE_BLACK_LIST', name: '스케줄 이용자 제재' }, + { value: 'SCHEDULE_NOTICE', name: '스케줄 인게임메시지' }, + { value: 'SCHEDULE_MAIL', name: '스케줄 우편' }, + { value: 'SCHEDULE_EVENT', name: '스케줄 이벤트' }, + { value: 'SCHEDULE_BATTLE_EVENT', name: '스케줄 전투 이벤트' }, + { value: 'SCHEDULE_LAND_AUCTION', name: '스케줄 랜드 경매' }, + { value: 'BANNER', name: '메뉴 배너' }, + { value: 'BATTLE_EVENT', name: '전투 이벤트' }, + { value: 'BUILDING', name: '빌딩' }, + { value: 'LAND_OWNER_CHANGE', name: '랜드 소유자 변경' }, + { value: 'LAND_AUCTION', name: '랜드 경매' }, + { value: 'GROUP', name: '그룹' }, + { value: 'ADMIN', name: '운영자' }, + { value: 'ADMIN_GROUP', name: '운영자 그룹' }, + { value: 'ADMIN_DELETE', name: '운영자 삭제' }, + { value: 'AUTH_ADMIN', name: '운영자 권한' }, + { value: 'PASSWORD_INIT', name: '비밀번호 초기화' }, + { value: 'PASSWORD_CHANGE', name: '비밀번호 변경' }, + { value: 'BLACK_LIST', name: '이용자 제재' }, + { value: 'CALIUM_REQUEST', name: '칼리움 요청' }, + { value: 'EVENT', name: '이벤트' }, + { value: 'MAIL', name: '우편' }, + { value: 'NOTICE', name: '인게임메시지' }, + { value: 'DATA_INIT', name: '데이터 초기화' }, + { value: 'DATA', name: '데이터' }, + { value: 'USER', name: '사용자' }, + { value: 'ITEM', name: '아이템' } +] + +export const opCommonStatus = [ + { value: 'SUCCESS', name: '성공' }, + { value: 'FAIL', name: '실패' } +] + // export const logAction = [ // { value: "None", name: "ALL" }, // { value: "AIChatDeleteCharacter", name: "NPC 삭제" }, diff --git a/src/assets/data/pages/historyTable.json b/src/assets/data/pages/historyTable.json index 458ce7e..3aad83f 100644 --- a/src/assets/data/pages/historyTable.json +++ b/src/assets/data/pages/historyTable.json @@ -12,7 +12,7 @@ }, "columns": [ { - "id": "timestamp", + "id": "logTime", "type": "date", "width": "200px", "title": "일시(KST)", @@ -22,25 +22,38 @@ } }, { - "id": "dbType", + "id": "category", "type": "option", "width": "100px", - "title": "DB타입", - "option_name": "opDBType" + "title": "로그종류", + "option_name": "opLogCategory" }, { - "id": "historyType", + "id": "action", "type": "option", "width": "150px", - "title": "이력종류", - "option_name": "opHistoryType" + "title": "로그액션", + "option_name": "opLogAction" }, { - "id": "userId", + "id": "status", + "type": "option", + "width": "100px", + "title": "상태", + "option_name": "opCommonStatus" + }, + { + "id": "worker", "type": "text", "width": "100px", "title": "작업자" }, + { + "id": "message", + "type": "text", + "width": "100px", + "title": "비고" + }, { "id": "detail", "type": "button", diff --git a/src/components/DataManage/UserSnapshotLogContent.js b/src/components/DataManage/UserSnapshotLogContent.js new file mode 100644 index 0000000..301d133 --- /dev/null +++ b/src/components/DataManage/UserSnapshotLogContent.js @@ -0,0 +1,153 @@ +import React, { Fragment, useMemo, useRef, useState } from 'react'; + +import { + CircularProgressWrapper, + FormWrapper, + TableStyle, + TableWrapper, +} from '../../styles/Components'; +import { useTranslation } from 'react-i18next'; +import { TableSkeleton } from '../Skeleton/TableSkeleton'; +import { UserSnapshotLogSearchBar, useUserSnapshotLogSearch } from '../searchBar'; +import { TopButton, ViewTableInfo } from '../common'; +import Pagination from '../common/Pagination/Pagination'; +import { + INITIAL_PAGE_LIMIT, +} from '../../assets/data/adminConstants'; +import ExcelExportButton from '../common/button/ExcelExportButton'; +import CircularProgress from '../common/CircularProgress'; +import { AnimatedPageWrapper } from '../common/Layout'; +import { numberFormatter } from '../../utils'; + +const UserSnapshotLogContent = ({ active }) => { + const { t } = useTranslation(); + const token = sessionStorage.getItem('token'); + const tableRef = useRef(null); + const [downloadState, setDownloadState] = useState({ + loading: false, + progress: 0 + }); + + const { + searchParams, + loading: dataLoading, + data: dataList, + handleSearch, + handleReset, + handlePageChange, + updateSearchParams + } = useUserSnapshotLogSearch(token, 500); + + const tableHeaders = useMemo(() => { + return [ + { id: 'logDay', label: '일자', width: '80px' }, + { id: 'accountId', label: 'account ID', width: '80px' }, + { id: 'userGuid', label: 'GUID', width: '180px' }, + { id: 'userNickname', label: '아바타명', width: '150px' }, + { id: 'gold', label: '골드', width: '80px' }, + { id: 'sapphire', label: '사파이어', width: '80px' }, + { id: 'calium', label: '칼리움', width: '80px' }, + { id: 'ruby', label: '루비', width: '80px' }, + { id: 'item_13080002', label: '퀘스트 메달', width: '80px' }, + { id: 'item_13080004', label: '보급품 메달', width: '80px' }, + { id: 'item_13080005', label: '제작 메달', width: '80px' }, + { id: 'item_13080006', label: '에테론 315 포드', width: '80px' }, + { id: 'item_13080007', label: '에테론 316 포드', width: '80px' }, + { id: 'item_13080008', label: '에테론 317 포드', width: '80px' }, + { id: 'item_13080009', label: '에테론 318 포드', width: '80px' }, + { id: 'item_11570001', label: '강화잉크', width: '80px' }, + { id: 'item_11570002', label: '연성잉크', width: '80px' }, + { id: 'lastLogoutTime', label: '마지막 로그아웃 일자', width: '150px' }, + ]; + }, []); + + if(!active) return null; + + return ( + + + { + if (executeSearch) { + handleSearch(newParams); + } else { + updateSearchParams(newParams); + } + }} + onReset={handleReset} + /> + + + + {downloadState.loading && ( + + + + )} + + {dataLoading ? : + <> + + + + + {tableHeaders.map(header => ( + {header.label} + ))} + + + + {dataList?.snapshot_list?.map((item, index) => ( + + + {item.logDay} + {item.accountId} + {item.userGuid} + {item.userNickname} + {numberFormatter.formatCurrency(item.gold)} + {numberFormatter.formatCurrency(item.sapphire)} + {numberFormatter.formatCurrency(item.calium)} + {numberFormatter.formatCurrency(item.ruby)} + {item.item_13080002} + {item.item_13080004} + {item.item_13080005} + {item.item_13080006} + {item.item_13080007} + {item.item_13080008} + {item.item_13080009} + {item.item_11570001} + {item.item_11570002} + {item.lastLogoutTime} + + + ))} + + + + {dataList?.snapshot_list && + + } + + + } + + ); +}; +export default UserSnapshotLogContent; \ No newline at end of file diff --git a/src/components/IndexManage/CreditContent.js b/src/components/IndexManage/CreditContent.js index 80185f9..f91bdd2 100644 --- a/src/components/IndexManage/CreditContent.js +++ b/src/components/IndexManage/CreditContent.js @@ -14,7 +14,7 @@ import {STORAGE_GAME_LOG_CURRENCY_SEARCH, } from '../../assets/data/adminConstan import ExcelExportButton from '../common/button/ExcelExportButton'; import CircularProgress from '../common/CircularProgress'; import { useTranslation } from 'react-i18next'; -import CurrencyIndexSearchBar from '../searchBar/CurrencyIndexSearchBar'; +import CurrencyUserIndexSearchBar from '../searchBar/CurrencyUserIndexSearchBar'; import { useNavigate } from 'react-router-dom'; import { AnimatedPageWrapper } from '../common/Layout'; @@ -132,7 +132,7 @@ const CreditContent = () => { return ( - { if (executeSearch) { diff --git a/src/components/IndexManage/CurrencyAcquireContent.js b/src/components/IndexManage/CurrencyAcquireContent.js new file mode 100644 index 0000000..0a26c40 --- /dev/null +++ b/src/components/IndexManage/CurrencyAcquireContent.js @@ -0,0 +1,126 @@ +import React, { Fragment, useMemo, useRef } from 'react'; + +import { + TableStyle, + FormWrapper, + TableWrapper, ListOption, +} from '../../styles/Components'; + +import { useCurrencyAcquireIndexSearch, CurrencyAcquireIndexSearchBar } from '../searchBar'; +import { TopButton, ViewTableInfo } from '../common'; +import { TableSkeleton } from '../Skeleton/TableSkeleton'; +import { numberFormatter } from '../../utils'; +import { useTranslation } from 'react-i18next'; +import { AnimatedPageWrapper } from '../common/Layout'; +import CSVDownloadButton from '../common/button/CsvDownButton'; + +const CurrencyAcquireContent = () => { + const { t } = useTranslation(); + const token = sessionStorage.getItem('token'); + const tableRef = useRef(null); + + const { + searchParams, + loading: dataLoading, + data: dataList, + handleSearch, + handleReset, + updateSearchParams + } = useCurrencyAcquireIndexSearch(token); + + const tableHeaders = useMemo(() => { + return [ + { id: 'logDay', label: '일자', width: '100px' }, + { id: 'mail', label: '우편', width: '80px' }, + { id: 'ShopSell', label: '상점 판매', width: '80px' }, + { id: 'ShopPurchase', label: '상점 구매', width: '80px' }, + { id: 'seasonPass', label: '시즌 패스', width: '80px' }, + { id: 'claim', label: '클레임', width: '80px' }, + { id: 'quest', label: '퀘스트', width: '80px' }, + { id: 'ugq', label: 'UGQ', width: '80px' }, + { id: 'battleObject', label: '보급품 상자', width: '80px' }, + { id: 'randomBox', label: '랜덤박스', width: '80px' }, + { id: 'landRent', label: '랜드 임대', width: '80px' }, + { id: 'caliumExchange', label: '칼리움 교환소', width: '80px' }, + { id: 'caliumConverter', label: '칼리움 컨버터', width: '80px' }, + { id: 'beaconShop', label: '비컨 상점', width: '80px' }, + { id: 'etc', label: '기타', width: '80px' }, + { id: 'summary', label: '합계', width: '80px' }, + ]; + + }, []); + + return ( + + + { + if (executeSearch) { + handleSearch(newParams); + } else { + updateSearchParams(newParams); + } + }} + onReset={handleReset} + /> + + + + + + + {dataLoading ? : + <> + + + + + {tableHeaders.map(header => { + return ( + + {header.label} + + ); + })} + + + + + {dataList?.currency_list?.map((item, index) => ( + + + {item.logDay} + {numberFormatter.formatCurrency(item.actionSummary.MailTaken)} + {numberFormatter.formatCurrency(item.actionSummary.ShopSell)} + {numberFormatter.formatCurrency(item.actionSummary.ShopPurchase)} + {numberFormatter.formatCurrency(item.actionSummary.SeasonPassTakeReward)} + {numberFormatter.formatCurrency(item.actionSummary.ClaimReward)} + {numberFormatter.formatCurrency((item.actionSummary.QuestMainReward || 0) + (item.actionSummary.QuestTaskUpdate || 0))} + {numberFormatter.formatCurrency(item.actionSummary.UgqAbort)} + {numberFormatter.formatCurrency(item.actionSummary.RewardProp)} + {numberFormatter.formatCurrency(item.actionSummary.ItemRandomBoxUse)} + {numberFormatter.formatCurrency(item.actionSummary.GainLandProfit)} + {numberFormatter.formatCurrency(item.actionSummary.ConvertExchangeCalium)} + {numberFormatter.formatCurrency(item.actionSummary.ConvertCalium)} + {numberFormatter.formatCurrency((item.actionSummary.BeaconSell || 0) + (item.actionSummary.BeaconShopReceivePaymentForSales || 0))} + {numberFormatter.formatCurrency(item.actionSummary.MoneyChange)} + {numberFormatter.formatCurrency(item.totalDeltaAmount)} + + + ))} + + + + + + } + + ); +}; + +export default CurrencyAcquireContent; diff --git a/src/components/IndexManage/CurrencyAssetsContent.js b/src/components/IndexManage/CurrencyAssetsContent.js new file mode 100644 index 0000000..e813b1f --- /dev/null +++ b/src/components/IndexManage/CurrencyAssetsContent.js @@ -0,0 +1,109 @@ +import React, { Fragment, useMemo, useRef } from 'react'; + +import { + TableStyle, + FormWrapper, + TableWrapper, ListOption +} from '../../styles/Components'; + +import { + AssetsIndexSearchBar, useAssetsIndexSearch, +} from '../searchBar'; +import { TopButton, ViewTableInfo } from '../common'; +import { TableSkeleton } from '../Skeleton/TableSkeleton'; +import { numberFormatter } from '../../utils'; +import { useTranslation } from 'react-i18next'; +import { AnimatedPageWrapper } from '../common/Layout'; +import CSVDownloadButton from '../common/button/CsvDownButton'; +import DailyDashBoard from './DailyCaliumDashBoard'; + +const CurrencyAssetsContent = () => { + const { t } = useTranslation(); + const token = sessionStorage.getItem('token'); + const tableRef = useRef(null); + + const { + searchParams, + loading: dataLoading, + data: dataList, + handleSearch, + handleReset, + updateSearchParams + } = useAssetsIndexSearch(token); + + const tableHeaders = useMemo(() => { + return [ + { id: 'logDay', label: '일자', width: '100px' }, + { id: 'userCount', label: '유저수', width: '100px' }, + { id: 'gold', label: '골드', width: '100px' }, + { id: 'sapphire', label: '사파이어', width: '100px' }, + { id: 'calium', label: '칼리움', width: '100px' }, + { id: 'ruby', label: '루비', width: '100px' } + ]; + }, []); + + return ( + + + + { + if (executeSearch) { + handleSearch(newParams); + } else { + updateSearchParams(newParams); + } + }} + onReset={handleReset} + /> + + + + + + + {dataLoading ? : + <> + + + + + {tableHeaders.map(header => { + return ( + + {header.label} + + ); + })} + + + + + {dataList?.assets_list?.map((data, index) => ( + + + {data.logDay} + {numberFormatter.formatCurrency(data.userCount)} + {numberFormatter.formatCurrency(data.gold)} + {numberFormatter.formatCurrency(data.sapphire)} + {numberFormatter.formatCurrency(data.calium)} + {numberFormatter.formatCurrency(data.ruby)} + + + ))} + + + + + + } + + ); +}; + +export default CurrencyAssetsContent; diff --git a/src/components/IndexManage/CurrencyConsumeContent.js b/src/components/IndexManage/CurrencyConsumeContent.js new file mode 100644 index 0000000..b6280f4 --- /dev/null +++ b/src/components/IndexManage/CurrencyConsumeContent.js @@ -0,0 +1,128 @@ +import React, { Fragment, useMemo, useRef } from 'react'; + +import { + TableStyle, + FormWrapper, + TableWrapper, ListOption, +} from '../../styles/Components'; + +import { + useCurrencyConsumeIndexSearch, CurrencyConsumeIndexSearchBar, +} from '../searchBar'; +import { TopButton, ViewTableInfo } from '../common'; +import { TableSkeleton } from '../Skeleton/TableSkeleton'; +import { numberFormatter } from '../../utils'; +import { useTranslation } from 'react-i18next'; +import { AnimatedPageWrapper } from '../common/Layout'; +import CSVDownloadButton from '../common/button/CsvDownButton'; + +const CurrencyConsumeContent = () => { + const { t } = useTranslation(); + const token = sessionStorage.getItem('token'); + const tableRef = useRef(null); + + const { + searchParams, + loading: dataLoading, + data: dataList, + handleSearch, + handleReset, + updateSearchParams + } = useCurrencyConsumeIndexSearch(token); + + const tableHeaders = useMemo(() => { + return [ + { id: 'logDay', label: '일자', width: '100px' }, + { id: 'itemBuy', label: '아이템 구매', width: '80px' }, + { id: 'ShopPurchase', label: '상점 구매', width: '80px' }, + { id: 'ShopRePurchase', label: '상점 재구매', width: '80px' }, + { id: 'beaconShop', label: '비컨상점', width: '80px' }, + { id: 'beacon', label: '비컨', width: '80px' }, + { id: 'taxi', label: '택시', width: '80px' }, + { id: 'farming', label: '파밍', width: '80px' }, + { id: 'seasonPass', label: '시즌 패스', width: '80px' }, + { id: 'caliumExchange', label: '칼리움 교환소', width: '80px' }, + { id: 'caliumConverter', label: '칼리움 컨버터', width: '80px' }, + { id: 'rent', label: '랜드 렌탈', width: '80px' }, + { id: 'landAuction', label: '랜드 경매', width: '80px' }, + { id: 'ugq', label: 'UGQ', width: '80px' }, + { id: 'etc', label: '기타', width: '80px' }, + { id: 'summary', label: '합계', width: '80px' }, + ]; + + }, []); + + return ( + + + { + if (executeSearch) { + handleSearch(newParams); + } else { + updateSearchParams(newParams); + } + }} + onReset={handleReset} + /> + + + + + + + {dataLoading ? : + <> + + + + + {tableHeaders.map(header => { + return ( + + {header.label} + + ); + })} + + + + + {dataList?.currency_list?.map((item, index) => ( + + + {item.logDay} + {numberFormatter.formatCurrency(item.actionSummary.ItemBuy)} + {numberFormatter.formatCurrency(item.actionSummary.ShopPurchase)} + {numberFormatter.formatCurrency(item.actionSummary.ShopRePurchase)} + {numberFormatter.formatCurrency((item.actionSummary.BeaconShopRegisterItem || 0) + (item.actionSummary.BeaconShopPurchaseItem || 0))} + {numberFormatter.formatCurrency((item.actionSummary.BeaconCreate || 0) + (item.actionSummary.BeaconEdit || 0) + (item.actionSummary.BeaconAppearanceCustomize || 0))} + {numberFormatter.formatCurrency(item.actionSummary.TaxiMove)} + {numberFormatter.formatCurrency(item.actionSummary.FarmingStart)} + {numberFormatter.formatCurrency(item.actionSummary.SeasonPassBuyCharged)} + {numberFormatter.formatCurrency(item.actionSummary.ConvertExchangeCalium)} + {numberFormatter.formatCurrency(item.actionSummary.ConvertCalium)} + {numberFormatter.formatCurrency(item.actionSummary.RentFloor)} + {numberFormatter.formatCurrency(item.actionSummary.LandAuctionBid)} + {numberFormatter.formatCurrency(item.actionSummary.UgqAssign)} + {numberFormatter.formatCurrency((item.actionSummary.MoneyChange ||0) + (item.actionSummary.RenewalShopProducts ||0) + (item.actionSummary.CharacterAppearanceCustomize ||0))} + {numberFormatter.formatCurrency(item.totalDeltaAmount)} + + + ))} + + + + + + } + + ); +}; + +export default CurrencyConsumeContent; diff --git a/src/components/IndexManage/DailyActiveUserContent.js b/src/components/IndexManage/DailyActiveUserContent.js deleted file mode 100644 index 566d421..0000000 --- a/src/components/IndexManage/DailyActiveUserContent.js +++ /dev/null @@ -1,110 +0,0 @@ -import { useEffect, useState } from 'react'; - -import Button from '../../components/common/button/Button'; - -import { TableStyle, TableInfo, ListOption, IndexTableWrap } from '../../styles/Components'; -import { DailySearchBar } from '../../components/IndexManage/index'; -import { DailyActiveUserExport, DailyActiveUserView } from '../../apis'; - -const PlayTimeContent = () => { - const token = sessionStorage.getItem('token'); - 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 [dataList, setDataList] = useState([]); - const [resultData, setResultData] = useState([]); - - const [sendDate, setSendDate] = useState(START_DATE); - const [finishDate, setFinishDate] = useState(END_DATE); - - useEffect(() => { - fetchData(START_DATE, END_DATE); - }, []); - - // DAU 데이터 - const fetchData = async (startDate, endDate) => { - const startDateToLocal = - startDate.getFullYear() + - '-' + - (startDate.getMonth() + 1 < 9 ? '0' + (startDate.getMonth() + 1) : startDate.getMonth() + 1) + - '-' + - (startDate.getDate() < 9 ? '0' + startDate.getDate() : startDate.getDate()); - - const endDateToLocal = - endDate.getFullYear() + - '-' + - (endDate.getMonth() + 1 < 9 ? '0' + (endDate.getMonth() + 1) : endDate.getMonth() + 1) + - '-' + - (endDate.getDate() < 9 ? '0' + endDate.getDate() : endDate.getDate()); - - // await DailyActiveUserView(token, startDateToLocal, endDateToLocal).then(data => { - // console.log(data); - // setDataList(data); - // }); - - setSendDate(startDateToLocal); - setFinishDate(endDateToLocal); - }; - - // 검색 함수 - const handleSearch = (send_dt, end_dt) => { - fetchData(send_dt, end_dt); - }; - - // 엑셀 다운로드 - const handleXlsxExport = () => { - const fileName = 'Caliverse_Dau.xlsx'; - DailyActiveUserExport(token, fileName, sendDate, finishDate); - }; - - return ( - <> - - - -