경제지표 재화 추가

게임 로그 재화지표 export api 추가
경제지표 재화 상세 > 재화 로그 페이지 이동 처리
This commit is contained in:
2025-06-16 15:45:36 +09:00
parent 7993f37e26
commit 495243a1a3
14 changed files with 459 additions and 143 deletions

View File

@@ -1,36 +1,31 @@
import React, { Fragment, useEffect, useMemo, useRef, useState } from 'react';
import { styled } from 'styled-components';
import Button from '../../components/common/button/Button';
import React, { Fragment, useMemo, useRef, useState } from 'react';
import { CurrencyIndexExport, CurrencyIndexView } from '../../apis';
import {
SelectInput,
TableStyle,
TableInfo,
ListOption,
InputLabel,
FormWrapper,
DownloadContainer, TableWrapper,
TableWrapper, CircularProgressWrapper, TotalRow,
} from '../../styles/Components';
import { CreditSearchBar, CurrencyLogSearchBar, useCurrencyLogSearch } from '../searchBar';
import { uniqBy } from 'lodash';
import { sumBy } from 'lodash';
import { TopButton, ViewTableInfo } from '../common';
import { useCurrencyIndexSearch } from '../searchBar';
import { Button, TopButton, ViewTableInfo } from '../common';
import { TableSkeleton } from '../Skeleton/TableSkeleton';
import { amountDeltaType, CurrencyType } from '../../assets/data';
import { numberFormatter } from '../../utils';
import Pagination from '../common/Pagination/Pagination';
import { INITIAL_PAGE_LIMIT } from '../../assets/data/adminConstants';
import { useAlert } from '../../context/AlertProvider';
import { useLoading } from '../../context/LoadingProvider';
import { alertTypes } from '../../assets/data/types';
import {STORAGE_GAME_LOG_CURRENCY_SEARCH, } from '../../assets/data/adminConstants';
import ExcelExportButton from '../common/button/ExcelExportButton';
import CircularProgress from '../common/CircularProgress';
import { useTranslation } from 'react-i18next';
import CurrencyIndexSearchBar from '../searchBar/CurrencyIndexSearchBar';
import { useNavigate } from 'react-router-dom';
const CreditContent = () => {
const { t } = useTranslation();
const token = sessionStorage.getItem('token');
const {showModal, showToast} = useAlert();
const {withLoading} = useLoading();
const navigate = useNavigate();
const tableRef = useRef(null);
const [downloadState, setDownloadState] = useState({
loading: false,
progress: 0
});
const {
searchParams,
@@ -38,52 +33,88 @@ const CreditContent = () => {
data: dataList,
handleSearch,
handleReset,
handlePageChange,
handleOrderByChange,
handlePageSizeChange,
updateSearchParams
} = useCurrencyLogSearch(token, 500);
} = useCurrencyIndexSearch(token);
const tableHeaders = useMemo(() => {
return [
// { id: 'logDay', label: '일자', width: '120px' },
{ id: 'logTime', label: '일시', width: '120px' },
{ id: 'logDay', label: '일자', width: '100px' },
{ id: 'accountId', label: 'account ID', width: '80px' },
{ id: 'userGuid', label: 'GUID', width: '200px' },
{ id: 'userNickname', label: '아바타명', width: '150px' },
{ id: 'tranId', label: '트랜잭션 ID', width: '200px' },
{ id: 'action', label: '액션', width: '150px' },
{ id: 'currencyType', label: '재화종류', width: '120px' },
{ id: 'amountDeltaType', label: '증감유형', width: '120px' },
{ id: 'deltaAmount', label: '량', width: '120px' },
{ id: 'sapphireAcquired', label: '사파이어 획득량', width: '80px' },
{ id: 'sapphireConsumed', label: '사파이어 소모량', width: '80px' },
{ id: 'goldAcquired', label: '골드 획득량', width: '80px' },
{ id: 'goldConsumed', label: '골드 소모량', width: '80px' },
{ id: 'caliumAcquired', label: '칼리움 획득량', width: '80px' },
{ id: 'caliumConsumed', label: '칼리움 소모량', width: '80px' },
{ id: 'beamAcquired', label: 'BEAM 획득량', width: '80px' },
{ id: 'beamConsumed', label: 'BEAM 소모량', width: '80px' },
{ id: 'rubyAcquired', label: '루비 획득량', width: '80px' },
{ id: 'rubyConsumed', label: '루비 소모량', width: '80px' },
{ id: 'sapphireNet', label: '사파이어 계', width: '80px' },
{ id: 'goldNet', label: '골드 계', width: '80px' },
{ id: 'caliumNet', label: '칼리움 계', width: '80px' },
{ id: 'beamNet', label: 'BEAM 계', width: '80px' },
{ id: 'rubyNet', label: '루비 계', width: '80px' },
{ id: 'totalCurrencies', label: '활동 수', width: '80px' },
{ id: 'detail', label: '상세', width: '100px' },
];
}, []);
const handleSubmit = async (type, param = null) => {
let params = {};
const totals = useMemo(() => {
if (!dataList?.currency_list?.length) return null;
return dataList.currency_list.reduce((acc, item) => {
return {
sapphireAcquired: (acc.sapphireAcquired || 0) + (item.sapphireAcquired || 0),
sapphireConsumed: (acc.sapphireConsumed || 0) + (item.sapphireConsumed || 0),
goldAcquired: (acc.goldAcquired || 0) + (item.goldAcquired || 0),
goldConsumed: (acc.goldConsumed || 0) + (item.goldConsumed || 0),
caliumAcquired: (acc.caliumAcquired || 0) + (item.caliumAcquired || 0),
caliumConsumed: (acc.caliumConsumed || 0) + (item.caliumConsumed || 0),
beamAcquired: (acc.beamAcquired || 0) + (item.beamAcquired || 0),
beamConsumed: (acc.beamConsumed || 0) + (item.beamConsumed || 0),
rubyAcquired: (acc.rubyAcquired || 0) + (item.rubyAcquired || 0),
rubyConsumed: (acc.rubyConsumed || 0) + (item.rubyConsumed || 0),
sapphireNet: (acc.sapphireNet || 0) + (item.sapphireNet || 0),
goldNet: (acc.goldNet || 0) + (item.goldNet || 0),
caliumNet: (acc.caliumNet || 0) + (item.caliumNet || 0),
beamNet: (acc.beamNet || 0) + (item.beamNet || 0),
rubyNet: (acc.rubyNet || 0) + (item.rubyNet || 0),
totalCurrencies: (acc.totalCurrencies || 0) + (item.totalCurrencies || 0),
};
}, {});
}, [dataList?.currency_list]);
const handleModalSubmit = async (type, param = null) => {
switch (type) {
case "gmLevelChangeSubmit":
showModal('USER_GM_CHANGE', {
type: alertTypes.confirm,
onConfirm: () => handleSubmit('gmLevelChange', param)
});
break;
case "detail":
const params = {
tab: "CURRENCY",
start_dt: (() => {
const date = new Date(param.logDay);
return date;
})(),
end_dt: (() => {
const date = new Date(param.logDay);
date.setDate(date.getDate() + 1);
return date;
})(),
guid: param.userGuid
};
case "userKickSubmit":
showModal('USER_KICK_CONFIRM', {
type: alertTypes.confirm,
onConfirm: () => handleSubmit('userKick')
});
// 복사한 데이터를 세션 스토리지에 저장
sessionStorage.setItem(STORAGE_GAME_LOG_CURRENCY_SEARCH, JSON.stringify(params));
navigate('/datamanage/gamelogview');
break;
}
}
return (
<>
<FormWrapper>
<CurrencyLogSearchBar
<CurrencyIndexSearchBar
searchParams={searchParams}
onSearch={(newParams, executeSearch = true) => {
if (executeSearch) {
@@ -95,9 +126,23 @@ const CreditContent = () => {
onReset={handleReset}
/>
</FormWrapper>
<ViewTableInfo orderType="asc" pageType="B" total={dataList?.total} total_all={dataList?.total_all}>
<DownloadContainer>
</DownloadContainer>
<ViewTableInfo >
<ExcelExportButton
functionName="GameCurrencyLogExport"
params={searchParams}
fileName={t('FILE_CURRENCY_INDEX')}
onLoadingChange={setDownloadState}
dataSize={dataList?.length}
/>
{downloadState.loading && (
<CircularProgressWrapper>
<CircularProgress
progress={downloadState.progress}
size={36}
progressColor="#4A90E2"
/>
</CircularProgressWrapper>
)}
</ViewTableInfo>
{dataLoading ? <TableSkeleton width='100%' count={15} /> :
<>
@@ -111,33 +156,61 @@ const CreditContent = () => {
</tr>
</thead>
<tbody>
{dataList?.currency_detail_list?.map((item, index) => (
{totals && (
<TotalRow>
<td colSpan="4">합계</td>
<td>{numberFormatter.formatCurrency(totals.sapphireAcquired)}</td>
<td>{numberFormatter.formatCurrency(totals.sapphireConsumed)}</td>
<td>{numberFormatter.formatCurrency(totals.goldAcquired)}</td>
<td>{numberFormatter.formatCurrency(totals.goldConsumed)}</td>
<td>{numberFormatter.formatCurrency(totals.caliumAcquired)}</td>
<td>{numberFormatter.formatCurrency(totals.caliumConsumed)}</td>
<td>{numberFormatter.formatCurrency(totals.beamAcquired)}</td>
<td>{numberFormatter.formatCurrency(totals.beamConsumed)}</td>
<td>{numberFormatter.formatCurrency(totals.rubyAcquired)}</td>
<td>{numberFormatter.formatCurrency(totals.rubyConsumed)}</td>
<td>{numberFormatter.formatCurrency(totals.sapphireNet)}</td>
<td>{numberFormatter.formatCurrency(totals.goldNet)}</td>
<td>{numberFormatter.formatCurrency(totals.caliumNet)}</td>
<td>{numberFormatter.formatCurrency(totals.beamNet)}</td>
<td>{numberFormatter.formatCurrency(totals.rubyNet)}</td>
<td>{totals.totalCurrencies}</td>
<td>-</td>
</TotalRow>
)}
{dataList?.currency_list?.map((item, index) => (
<Fragment key={index}>
<tr>
<td>{item.logTime}</td>
<td>{item.logDay}</td>
<td>{item.accountId}</td>
<td>{item.userGuid}</td>
<td>{item.userNickname}</td>
<td>{item.tranId}</td>
<td>{item.action}</td>
<td>{CurrencyType.find(data => data.value === item.currencyType).name}</td>
<td>{amountDeltaType.find(data => data.value === item.amountDeltaType).name}</td>
<td>{numberFormatter.formatCurrency(item.deltaAmount)}</td>
<td>{numberFormatter.formatCurrency(item.sapphireAcquired)}</td>
<td>{numberFormatter.formatCurrency(item.sapphireConsumed)}</td>
<td>{numberFormatter.formatCurrency(item.goldAcquired)}</td>
<td>{numberFormatter.formatCurrency(item.goldConsumed)}</td>
<td>{numberFormatter.formatCurrency(item.caliumAcquired)}</td>
<td>{numberFormatter.formatCurrency(item.caliumConsumed)}</td>
<td>{numberFormatter.formatCurrency(item.beamAcquired)}</td>
<td>{numberFormatter.formatCurrency(item.beamConsumed)}</td>
<td>{numberFormatter.formatCurrency(item.rubyAcquired)}</td>
<td>{numberFormatter.formatCurrency(item.rubyConsumed)}</td>
<td>{numberFormatter.formatCurrency(item.sapphireNet)}</td>
<td>{numberFormatter.formatCurrency(item.goldNet)}</td>
<td>{numberFormatter.formatCurrency(item.caliumNet)}</td>
<td>{numberFormatter.formatCurrency(item.beamNet)}</td>
<td>{numberFormatter.formatCurrency(item.rubyNet)}</td>
<td>{item.totalCurrencies}</td>
<td>
<Button theme="line" text="상세보기"
handleClick={e => handleModalSubmit('detail', item)} />
</td>
</tr>
</Fragment>
))}
</tbody>
</TableStyle>
</TableWrapper>
{dataList?.currency_detail_list &&
<Pagination
postsPerPage={searchParams.page_size}
totalPosts={dataList?.total_all}
setCurrentPage={handlePageChange}
currentPage={searchParams.page_no}
pageLimit={INITIAL_PAGE_LIMIT}
/>
}
<TopButton />
</>
}
@@ -145,4 +218,4 @@ const CreditContent = () => {
);
};
export default CreditContent;
export default CreditContent;