경제지표 재화 보유

경제지표 아이템 보유
게임로그 스냅샷
히스토리 비즈니스로그 기준 변경
This commit is contained in:
2025-08-04 17:40:37 +09:00
parent 2ba8594e6b
commit f4b629df52
40 changed files with 2710 additions and 1131 deletions

View File

@@ -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 (
<AnimatedPageWrapper>
<FormWrapper>
<CurrencyIndexSearchBar
<CurrencyUserIndexSearchBar
searchParams={searchParams}
onSearch={(newParams, executeSearch = true) => {
if (executeSearch) {

View File

@@ -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 (
<AnimatedPageWrapper>
<FormWrapper>
<CurrencyAcquireIndexSearchBar
searchParams={searchParams}
onSearch={(newParams, executeSearch = true) => {
if (executeSearch) {
handleSearch(newParams);
} else {
updateSearchParams(newParams);
}
}}
onReset={handleReset}
/>
</FormWrapper>
<ViewTableInfo >
<ListOption>
<CSVDownloadButton tableRef={tableRef} fileName={t('FILE_INDEX_CURRENCY_ACQUIRE')} />
</ListOption>
</ViewTableInfo>
{dataLoading ? <TableSkeleton width='100%' count={15} /> :
<>
<TableWrapper>
<TableStyle ref={tableRef}>
<thead>
<tr>
{tableHeaders.map(header => {
return (
<th
key={header.id}
width={header.width}
colSpan={header.colSpan}
>
{header.label}
</th>
);
})}
</tr>
</thead>
<tbody>
{dataList?.currency_list?.map((item, index) => (
<Fragment key={index}>
<tr>
<td>{item.logDay}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.MailTaken)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ShopSell)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ShopPurchase)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.SeasonPassTakeReward)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ClaimReward)}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.QuestMainReward || 0) + (item.actionSummary.QuestTaskUpdate || 0))}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.UgqAbort)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.RewardProp)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ItemRandomBoxUse)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.GainLandProfit)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ConvertExchangeCalium)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ConvertCalium)}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.BeaconSell || 0) + (item.actionSummary.BeaconShopReceivePaymentForSales || 0))}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.MoneyChange)}</td>
<td>{numberFormatter.formatCurrency(item.totalDeltaAmount)}</td>
</tr>
</Fragment>
))}
</tbody>
</TableStyle>
</TableWrapper>
<TopButton />
</>
}
</AnimatedPageWrapper>
);
};
export default CurrencyAcquireContent;

View File

@@ -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 (
<AnimatedPageWrapper>
<DailyDashBoard />
<FormWrapper>
<AssetsIndexSearchBar
searchParams={searchParams}
onSearch={(newParams, executeSearch = true) => {
if (executeSearch) {
handleSearch(newParams);
} else {
updateSearchParams(newParams);
}
}}
onReset={handleReset}
/>
</FormWrapper>
<ViewTableInfo >
<ListOption>
<CSVDownloadButton tableRef={tableRef} fileName={t('FILE_INDEX_ASSETS_CURRENCY')} />
</ListOption>
</ViewTableInfo>
{dataLoading ? <TableSkeleton width='100%' count={15} /> :
<>
<TableWrapper>
<TableStyle ref={tableRef}>
<thead>
<tr>
{tableHeaders.map(header => {
return (
<th
key={header.id}
width={header.width}
colSpan={header.colSpan}
>
{header.label}
</th>
);
})}
</tr>
</thead>
<tbody>
{dataList?.assets_list?.map((data, index) => (
<Fragment key={index}>
<tr>
<td>{data.logDay}</td>
<td>{numberFormatter.formatCurrency(data.userCount)}</td>
<td>{numberFormatter.formatCurrency(data.gold)}</td>
<td>{numberFormatter.formatCurrency(data.sapphire)}</td>
<td>{numberFormatter.formatCurrency(data.calium)}</td>
<td>{numberFormatter.formatCurrency(data.ruby)}</td>
</tr>
</Fragment>
))}
</tbody>
</TableStyle>
</TableWrapper>
<TopButton />
</>
}
</AnimatedPageWrapper>
);
};
export default CurrencyAssetsContent;

View File

@@ -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 (
<AnimatedPageWrapper>
<FormWrapper>
<CurrencyConsumeIndexSearchBar
searchParams={searchParams}
onSearch={(newParams, executeSearch = true) => {
if (executeSearch) {
handleSearch(newParams);
} else {
updateSearchParams(newParams);
}
}}
onReset={handleReset}
/>
</FormWrapper>
<ViewTableInfo >
<ListOption>
<CSVDownloadButton tableRef={tableRef} fileName={t('FILE_INDEX_CURRENCY_CONSUME')} />
</ListOption>
</ViewTableInfo>
{dataLoading ? <TableSkeleton width='100%' count={15} /> :
<>
<TableWrapper>
<TableStyle ref={tableRef}>
<thead>
<tr>
{tableHeaders.map(header => {
return (
<th
key={header.id}
width={header.width}
colSpan={header.colSpan}
>
{header.label}
</th>
);
})}
</tr>
</thead>
<tbody>
{dataList?.currency_list?.map((item, index) => (
<Fragment key={index}>
<tr>
<td>{item.logDay}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ItemBuy)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ShopPurchase)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ShopRePurchase)}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.BeaconShopRegisterItem || 0) + (item.actionSummary.BeaconShopPurchaseItem || 0))}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.BeaconCreate || 0) + (item.actionSummary.BeaconEdit || 0) + (item.actionSummary.BeaconAppearanceCustomize || 0))}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.TaxiMove)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.FarmingStart)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.SeasonPassBuyCharged)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ConvertExchangeCalium)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ConvertCalium)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.RentFloor)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.LandAuctionBid)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.UgqAssign)}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.MoneyChange ||0) + (item.actionSummary.RenewalShopProducts ||0) + (item.actionSummary.CharacterAppearanceCustomize ||0))}</td>
<td>{numberFormatter.formatCurrency(item.totalDeltaAmount)}</td>
</tr>
</Fragment>
))}
</tbody>
</TableStyle>
</TableWrapper>
<TopButton />
</>
}
</AnimatedPageWrapper>
);
};
export default CurrencyConsumeContent;

View File

@@ -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 (
<>
<DailySearchBar setResultData={setResultData} resultData={resultData} handleSearch={handleSearch} fetchData={fetchData} />
<TableInfo>
<ListOption>
<Button theme="line" text="엑셀 다운로드" handleClick={handleXlsxExport} />
</ListOption>
</TableInfo>
<IndexTableWrap>
<TableStyle>
<caption></caption>
<thead>
<tr>
<th rowSpan="1" width="45">
일자
</th>
<th colSpan="1" width="30">
DAU
</th>
{/*<th colSpan="1" width="30">*/}
{/* DALC*/}
{/*</th>*/}
<th colSpan="1" width="30">
DGLC
</th>
{/*<th colSpan="1" width="30">*/}
{/* MaxAU*/}
{/*</th>*/}
</tr>
</thead>
<tbody>
{dataList && (dataList || []).map((data, index) => (
<tr key={index}>
<td>{data.date}</td>
<td>{data.dau}</td>
{/*<td>{data.dalc}</td>*/}
<td>{data.dglc}</td>
{/*<td>{data.maxAu}</td>*/}
</tr>
))}
</tbody>
</TableStyle>
</IndexTableWrap>
</>
);
};
export default PlayTimeContent;

View File

@@ -0,0 +1,141 @@
import { useEffect, useState } from 'react';
import { dashboardCaliumIndex } from '../../apis';
import { styled } from 'styled-components';
import TitleArrow from '../../assets/img/icon/icon-title.png';
const DailyDashBoard = () => {
const [boardState, setBoardState] = useState('active');
const [totalData, setTotalData] = useState([]);
const handleBoard = () => {
if (boardState === 'active') {
setBoardState('inactive');
} else {
setBoardState('active');
}
};
useEffect(() => {
fetchData();
}, []);
const fetchData = async () => {
const token = sessionStorage.getItem('token');
await dashboardCaliumIndex(token).then(data => {
setTotalData(data.dashboard_calium);
});
};
const dashboardItems = [
{
title: '컨버터 칼리움 보유량',
value: totalData.total_calium || 0
},
{
title: '컨버터 변환 효율',
value: `${totalData.converter_rate || 0}%`
},
{
title: '인플레이션 가중치',
value: `${totalData.inflation_rate || 0}%`
},
{
title: '칼리움 누적 총량',
value: totalData.cumulative_calium || 0
}
];
return (
<DailyBoardWrapper>
{totalData &&
<DailyBoard>
<BoardTitle onClick={handleBoard} $state={boardState}>
Daily Dashboard
</BoardTitle>
<BoardInfo $state={boardState}>
<BoxWrapper>
{dashboardItems?.map((item, index) => (
<InfoItem key={index}>
<InfoTitle>{item.title}</InfoTitle>
<InfoValue>
{item.value}
</InfoValue>
</InfoItem>
))}
</BoxWrapper>
</BoardInfo>
</DailyBoard>
}
</DailyBoardWrapper>
);
};
export default DailyDashBoard;
const DailyBoardWrapper = styled.div`
padding-top: 20px;
border-top: 1px solid #000;
`;
const DailyBoard = styled.div`
background: #f6f6f6;
border-radius: 10px;
margin-bottom: 20px;
`;
const BoardTitle = styled.div`
font-size: 24px;
font-weight: 600;
line-height: 52px;
padding: 0 10px;
cursor: pointer;
&:after {
content: '';
display: inline-block;
width: 11px;
height: 52px;
margin-left: 10px;
background: url(${TitleArrow}) 50% 50% no-repeat;
position: absolute;
transform: ${props => (props.$state === 'active' ? 'rotate(0)' : 'rotate(180deg)')};
}
`;
const BoardInfo = styled.div`
padding: 20px;
border-top: 1px solid #d9d9d9;
display: ${props => (props.$state === 'active' ? 'block' : 'none')};
`;
const BoxWrapper = styled.div`
display: flex;
flex-wrap: wrap;
gap: 20px;
`;
const InfoItem = styled.div`
width: 18%;
background: #fff;
padding: 15px 20px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
border-radius: 15px;
`;
const InfoTitle = styled.div`
font-size: 20px;
font-weight: 600;
`;
const InfoValue = styled.div`
display: inline-flex;
flex-wrap: wrap;
margin: 5px 0;
gap: 5px 0;
align-items: center;
font-size: 18px;
font-weight: 600;
`;

View File

@@ -26,7 +26,6 @@ const DailyDashBoard = ({ content }) => {
const fetchData = async () => {
const token = sessionStorage.getItem('token');
await userTotalIndex(token).then(data => {
console.log(data);
setTotalData(data.dashboard);
});
};

View File

@@ -1,111 +0,0 @@
import { Fragment, useEffect, useState } from 'react';
import Button from '../common/button/Button';
import { TableStyle, TableInfo, ListOption, IndexTableWrap } from '../../styles/Components';
import { DailySearchBar } from './index';
import { DailyMedalView } from '../../apis';
const DailyMedalContent = () => {
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);
}, []);
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());
setDataList(await DailyMedalView(token, startDateToLocal, endDateToLocal));
setSendDate(startDateToLocal);
setFinishDate(endDateToLocal);
};
// 검색 함수
const handleSearch = (send_dt, end_dt) => {
fetchData(send_dt, end_dt);
};
// 엑셀 다운로드
const handleXlsxExport = () => {
const fileName = 'Caliverse_Daily_Medal.xlsx';
//DailyActiveUserExport(token, fileName, sendDate, finishDate);
};
return (
<>
<DailySearchBar setResultData={setResultData} resultData={resultData} handleSearch={handleSearch} fetchData={fetchData} />
<TableInfo>
<ListOption>
<Button theme="line" text="엑셀 다운로드" handleClick={handleXlsxExport} />
</ListOption>
</TableInfo>
<IndexTableWrap>
<TableStyle>
<caption></caption>
<thead >
<tr>
<th rowSpan="1" width="20">
일자
</th>
<th colSpan="1" width="30">
UserID
</th>
<th colSpan="1" width="30">
닉네임
</th>
<th colSpan="1" width="30">
Item ID
</th>
<th colSpan="1" width="30">
획득량
</th>
</tr>
</thead>
<tbody>
{(dataList || []).map((data, index) => (
<tr key={index}>
<td>{data.date}</td>
<td>{data.dau}</td>
<td>{data.dalc}</td>
<td>{data.dglc}</td>
<td>{data.maxAu}</td>
{Array.from({ length: 24 }, (_, i) => (
<td key={i}>{data['h' + i]}</td>
))}
</tr>
))}
</tbody>
</TableStyle>
</IndexTableWrap>
</>
);
};
export default DailyMedalContent;

View File

@@ -0,0 +1,152 @@
import React, { Fragment, useMemo, useRef } from 'react';
import {
TableStyle,
FormWrapper,
TableWrapper, ListOption, TextInput, TableInfoContent, Notice,
} from '../../styles/Components';
import { ItemAcquireIndexSearchBar, useItemAcquireIndexSearch } 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 ItemAcquireContent = () => {
const { t } = useTranslation();
const token = sessionStorage.getItem('token');
const tableRef = useRef(null);
const {
searchParams,
loading: dataLoading,
data: dataList,
handleSearch,
handleReset,
updateSearchParams
} = useItemAcquireIndexSearch(token);
const tableHeaders = useMemo(() => {
return [
{ id: 'logDay', label: '일자', width: '100px' },
{ id: 'mail', label: '우편', width: '80px' },
{ id: 'shopPurchase', label: '상점 구매', width: '80px' },
{ id: 'shopRePurchase', label: '상점 재구매', width: '80px' },
{ id: 'itemBuy', label: '아이템 구매', width: '80px' },
{ id: 'itemUse', 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: 'runRace', label: '런레이스', width: '80px' },
{ id: 'prop', label: '보급품 상자', width: '80px' },
{ id: 'randomBox', label: '랜덤박스', width: '80px' },
{ id: 'beacon', label: '비컨', width: '80px' },
{ id: 'beaconShop', label: '비컨 상점', width: '80px' },
{ id: 'myHome', label: '마이홈', width: '80px' },
{ id: 'craft', label: '크래프트', width: '80px' },
{ id: 'etc', label: '기타', width: '80px' },
{ id: 'summary', label: '합계', width: '80px' },
];
}, []);
return (
<AnimatedPageWrapper>
<FormWrapper>
<ItemAcquireIndexSearchBar
searchParams={searchParams}
onSearch={(newParams, executeSearch = true) => {
if (executeSearch) {
handleSearch(newParams);
} else {
updateSearchParams(newParams);
}
}}
onReset={handleReset}
/>
</FormWrapper>
<ViewTableInfo >
{dataList?.item_list && dataList.item_list.length > 0 &&
<TableInfoContent>
<TextInput
type="text"
value={dataList.item_list[0].itemId}
width="100px"
readOnly
/>
<TextInput
type="text"
value={dataList.item_list[0].itemName}
width="150px"
readOnly
/>
<Notice $color='#F15F5F'>* 확인되지 않은 액션이 있을 있습니다</Notice>
</TableInfoContent>
}
<ListOption>
<CSVDownloadButton tableRef={tableRef} fileName={t('FILE_INDEX_ITEM_ACQUIRE')} />
</ListOption>
</ViewTableInfo>
{dataLoading ? <TableSkeleton width='100%' count={15} /> :
<>
<TableWrapper>
<TableStyle ref={tableRef}>
<thead>
<tr>
{tableHeaders.map(header => {
return (
<th
key={header.id}
width={header.width}
colSpan={header.colSpan}
>
{header.label}
</th>
);
})}
</tr>
</thead>
<tbody>
{dataList?.item_list?.map((item, index) => (
<Fragment key={index}>
<tr>
<td>{item.logDay}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.MailTaken)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ShopPurchase)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ShopRePurchase)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ItemBuy)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ItemUse)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.SeasonPassTakeReward)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ClaimReward)}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.QuestMainReward || 0) + (item.actionSummary.QuestTaskUpdate || 0) + (item.actionSummary.QuestMainTask || 0))}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.UgqAbort)}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.BattleRoundStateUpdate || 0) + (item.actionSummary.BattlePodCombatOccupyReward || 0) + (item.actionSummary.BattleObjectInteraction || 0))}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.RunRaceFinishReward || 0) + (item.actionSummary.RunRaceRespawnReward || 0))}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.RewardProp)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ItemRandomBoxUse)}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.BeaconCreate || 0) + (item.actionSummary.BeaconEdit || 0))}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.BeaconShopPurchaseItem || 0))}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.DeleteMyhome || 0) + (item.actionSummary.SaveMyhome || 0))}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.CraftFinish || 0) + (item.actionSummary.CraftStop || 0))}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.CheatCommandItem || 0) + (item.actionSummary.CharacterAppearanceUpdate || 0)
+ (item.actionSummary.ItemTattooLevelUp || 0) + (item.actionSummary.UserCreate || 0) + (item.actionSummary.JoinInstance || 0))}</td>
<td>{numberFormatter.formatCurrency(item.totalDeltaCount)}</td>
</tr>
</Fragment>
))}
</tbody>
</TableStyle>
</TableWrapper>
<TopButton />
</>
}
</AnimatedPageWrapper>
);
};
export default ItemAcquireContent;

View File

@@ -0,0 +1,119 @@
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 ItemAssetsContent = () => {
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: 'item_13080002', label: '퀘스트 메달', width: '100px' },
{ id: 'item_13080004', label: '보급품 메달', width: '100px' },
{ id: 'item_13080005', label: '제작 메달', width: '100px' },
{ id: 'item_13080006', label: '에테론 315 포드', width: '100px' },
{ id: 'item_13080007', label: '에테론 316 포드', width: '100px' },
{ id: 'item_13080008', label: '에테론 317 포드', width: '100px' },
{ id: 'item_13080009', label: '에테론 318 포드', width: '100px' },
{ id: 'item_11570001', label: '강화 잉크', width: '100px' },
{ id: 'item_11570002', label: '연성 잉크', width: '100px' }
];
}, []);
return (
<AnimatedPageWrapper>
<DailyDashBoard />
<FormWrapper>
<AssetsIndexSearchBar
searchParams={searchParams}
onSearch={(newParams, executeSearch = true) => {
if (executeSearch) {
handleSearch(newParams);
} else {
updateSearchParams(newParams);
}
}}
onReset={handleReset}
/>
</FormWrapper>
<ViewTableInfo >
<ListOption>
<CSVDownloadButton tableRef={tableRef} fileName={t('FILE_INDEX_ASSETS_ITEM')} />
</ListOption>
</ViewTableInfo>
{dataLoading ? <TableSkeleton width='100%' count={15} /> :
<>
<TableWrapper>
<TableStyle ref={tableRef}>
<thead>
<tr>
{tableHeaders.map(header => {
return (
<th
key={header.id}
width={header.width}
colSpan={header.colSpan}
>
{header.label}
</th>
);
})}
</tr>
</thead>
<tbody>
{dataList?.assets_list?.map((data, index) => (
<Fragment key={index}>
<tr>
<td>{data.logDay}</td>
<td>{numberFormatter.formatCurrency(data.userCount)}</td>
<td>{numberFormatter.formatCurrency(data.item_13080002)}</td>
<td>{numberFormatter.formatCurrency(data.item_13080004)}</td>
<td>{numberFormatter.formatCurrency(data.item_13080005)}</td>
<td>{numberFormatter.formatCurrency(data.item_13080006)}</td>
<td>{numberFormatter.formatCurrency(data.item_13080007)}</td>
<td>{numberFormatter.formatCurrency(data.item_13080008)}</td>
<td>{numberFormatter.formatCurrency(data.item_13080009)}</td>
<td>{numberFormatter.formatCurrency(data.item_11570001)}</td>
<td>{numberFormatter.formatCurrency(data.item_11570002)}</td>
</tr>
</Fragment>
))}
</tbody>
</TableStyle>
</TableWrapper>
<TopButton />
</>
}
</AnimatedPageWrapper>
);
};
export default ItemAssetsContent;

View File

@@ -0,0 +1,143 @@
import React, { Fragment, useMemo, useRef } from 'react';
import {
TableStyle,
FormWrapper,
TableWrapper, ListOption, TableInfoContent, TextInput, Label, Notice,
} from '../../styles/Components';
import {
ItemAcquireIndexSearchBar,
ItemConsumeIndexSearchBar,
useItemAcquireIndexSearch,
useItemConsumeIndexSearch,
} 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 styled from 'styled-components';
const ItemConsumeContent = () => {
const { t } = useTranslation();
const token = sessionStorage.getItem('token');
const tableRef = useRef(null);
const {
searchParams,
loading: dataLoading,
data: dataList,
handleSearch,
handleReset,
updateSearchParams
} = useItemConsumeIndexSearch(token);
const tableHeaders = useMemo(() => {
return [
{ id: 'logDay', label: '일자', width: '100px' },
{ id: 'shopSell', label: '상점 판매', width: '80px' },
{ id: 'itemUse', label: '아이템 사용', width: '80px' },
{ id: 'beaconShop', label: '비컨상점', width: '80px' },
{ id: 'beacon', label: '비컨', width: '80px' },
{ id: 'quest', label: '퀘스트', width: '80px' },
{ id: 'ugq', label: 'UGQ', width: '80px' },
{ id: 'randomBox', label: '랜덤박스', width: '80px' },
{ id: 'myHome', label: '마이홈', width: '80px' },
{ id: 'craft', label: '크래프트', width: '80px' },
{ id: 'etc', label: '기타', width: '80px' },
{ id: 'summary', label: '합계', width: '80px' },
];
}, []);
return (
<AnimatedPageWrapper>
<FormWrapper>
<ItemConsumeIndexSearchBar
searchParams={searchParams}
onSearch={(newParams, executeSearch = true) => {
if (executeSearch) {
handleSearch(newParams);
} else {
updateSearchParams(newParams);
}
}}
onReset={handleReset}
/>
</FormWrapper>
<ViewTableInfo >
{dataList?.item_list && dataList.item_list.length > 0 &&
<TableInfoContent>
<TextInput
type="text"
value={dataList.item_list[0].itemId}
width="100px"
readOnly
/>
<TextInput
type="text"
value={dataList.item_list[0].itemName}
width="300px"
readOnly
/>
<Notice $color='#F15F5F'>* 확인되지 않은 액션이 있을 있습니다</Notice>
</TableInfoContent>
}
<ListOption>
<CSVDownloadButton tableRef={tableRef} fileName={t('FILE_INDEX_ITEM_CONSUME')} />
</ListOption>
</ViewTableInfo>
{dataLoading ? <TableSkeleton width='100%' count={15} /> :
<>
<TableWrapper>
<TableStyle ref={tableRef}>
<thead>
<tr>
{tableHeaders.map(header => {
return (
<th
key={header.id}
width={header.width}
colSpan={header.colSpan}
>
{header.label}
</th>
);
})}
</tr>
</thead>
<tbody>
{dataList?.item_list?.map((item, index) => (
<Fragment key={index}>
<tr>
<td>{item.logDay}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ShopSell)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ItemUse)}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.BeaconShopRegisterItem || 0))}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.BeaconEdit || 0) + (item.actionSummary.BeaconCreate || 0))}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.QuestTaskUpdate || 0))}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.UgqAbort)}</td>
<td>{numberFormatter.formatCurrency(item.actionSummary.ItemRandomBoxUse)}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.SaveMyhome || 0))}</td>
<td>{numberFormatter.formatCurrency((item.actionSummary.CraftStart || 0))}</td>
<td>{numberFormatter.formatCurrency(
(item.actionSummary.SummonParty || 0) + (item.actionSummary.ItemDestroy || 0) + (item.actionSummary.CreatePartyInstance || 0) + (item.actionSummary.ItemTattooChangeAttribute || 0)
+ (item.actionSummary.CheatCommandItem || 0) + (item.actionSummary.ItemDestoryByExpiration || 0) + (item.actionSummary.ItemDestroyByUser || 0) + (item.actionSummary.ItemTattooLevelUp || 0)
)}</td>
<td>{numberFormatter.formatCurrency(item.totalDeltaCount)}</td>
</tr>
</Fragment>
))}
</tbody>
</TableStyle>
</TableWrapper>
<TopButton />
</>
}
</AnimatedPageWrapper>
);
};
export default ItemConsumeContent;

View File

@@ -1,112 +0,0 @@
import { Fragment, useEffect, useState } from 'react';
import Button from '../../components/common/button/Button';
import { TableStyle, TableInfo, ListOption, IndexTableWrap } from '../../styles/Components';
import { PlayTimeSearchBar } from '../../components/IndexManage/index';
import { PlaytimeIndexExport, PlaytimeIndexView } 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);
}, []);
// 이용자 지표 데이터
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());
setDataList(await PlaytimeIndexView(token, startDateToLocal, endDateToLocal));
setSendDate(startDateToLocal);
setFinishDate(endDateToLocal);
};
// 검색 함수
const handleSearch = (send_dt, end_dt) => {
fetchData(send_dt, end_dt);
};
// 엑셀 다운로드
const handleXlsxExport = () => {
const fileName = 'Caliverse_PlayTime_Index.xlsx';
PlaytimeIndexExport(token, fileName, sendDate, finishDate);
};
return (
<>
<PlayTimeSearchBar setResultData={setResultData} resultData={resultData} handleSearch={handleSearch} fetchData={fetchData} />
<TableInfo>
<ListOption>
<Button theme="line" text="엑셀 다운로드" handleClick={handleXlsxExport} />
</ListOption>
</TableInfo>
<IndexTableWrap>
<TableStyle>
<caption></caption>
<thead>
<tr>
<th rowSpan="2" width="140">
일자
</th>
<th colSpan="4" width="520">
유저수
</th>
<th rowSpan="2" width="160">
누적 플레이타임()
</th>
<th rowSpan="2" width="160">
1인당 평균 플레이타임()
</th>
</tr>
<tr>
<th>30 이내</th>
<th>30 ~ 1시간</th>
<th>1시간 ~ 3시간</th>
<th>3시간 이상</th>
</tr>
</thead>
<tbody>
{dataList.playtime &&
dataList.playtime.map(time => (
<tr key={time.date}>
<td>{time.date}</td>
{time.user_cnt.map((cnt, index) => (
<td className="text-left" key={index}>
{cnt}
</td>
))}
<td className="text-left">{time.total_time}</td>
<td className="text-left">{time.average_time}</td>
</tr>
))}
</tbody>
</TableStyle>
</IndexTableWrap>
</>
);
};
export default PlayTimeContent;

View File

@@ -5,8 +5,8 @@ import { AnimatedPageWrapper } from '../common/Layout';
import { useRetentionSearch, RetentionSearchBar } from '../searchBar';
import { TableSkeleton } from '../Skeleton/TableSkeleton';
import { numberFormatter } from '../../utils';
import { ExcelDownButton } from '../common';
import { useTranslation } from 'react-i18next';
import CSVDownloadButton from '../common/button/CsvDownButton';
const RetentionContent = () => {
const { t } = useTranslation();
@@ -38,7 +38,7 @@ const RetentionContent = () => {
/>
<TableInfo>
<ListOption>
<ExcelDownButton tableRef={tableRef} fileName={t('FILE_INDEX_USER_RETENTION')} />
<CSVDownloadButton tableRef={tableRef} fileName={t('FILE_INDEX_USER_RETENTION')} />
</ListOption>
</TableInfo>
{dataLoading ? <TableSkeleton width='100%' count={15} /> :

View File

@@ -1,90 +0,0 @@
import { Fragment, useEffect, useState } from 'react';
import Button from '../../components/common/button/Button';
import { TableStyle, TableInfo, ListOption, IndexTableWrap } from '../../styles/Components';
import { SegmentSearchBar } from '../../components/IndexManage/index';
import { SegmentIndexExport, SegmentIndexView } from '../../apis';
const SegmentContent = () => {
const token = sessionStorage.getItem('token');
const END_DATE = new Date();
const [dataList, setDataList] = useState([]);
const [resultData, setResultData] = useState([]);
const [finishDate, setFinishDate] = useState(END_DATE);
useEffect(() => {
fetchData(END_DATE);
}, []);
// Retention 지표 데이터
const fetchData = async endDate => {
const endDateToLocal =
endDate.getFullYear() +
'-' +
(endDate.getMonth() + 1 < 9 ? '0' + (endDate.getMonth() + 1) : endDate.getMonth() + 1) +
'-' +
(endDate.getDate() < 9 ? '0' + endDate.getDate() : endDate.getDate());
setDataList(await SegmentIndexView(token, endDateToLocal));
setFinishDate(endDateToLocal);
};
// 검색 함수
const handleSearch = end_dt => {
fetchData(end_dt);
};
// 엑셀 다운로드
const handleXlsxExport = () => {
const fileName = 'Caliverse_Segment_Index.xlsx';
SegmentIndexExport(token, fileName, finishDate);
};
return (
<>
<SegmentSearchBar setResultData={setResultData} resultData={resultData} handleSearch={handleSearch} fetchData={fetchData} />
<TableInfo>
<ListOption>
<Button theme="line" text="엑셀 다운로드" handleClick={handleXlsxExport} />
</ListOption>
</TableInfo>
<IndexTableWrap>
<TableStyle>
<caption></caption>
<thead>
<tr>
<th colSpan="1" width="200">
{dataList && dataList.start_dt} ~ {dataList && dataList.end_dt}
</th>
<th colSpan="2" width="400">
KIP
</th>
</tr>
<tr>
{/* <th>국가</th> */}
<th>세그먼트 분류</th>
<th>AU</th>
<th>AU Percentage by User Segment (%)</th>
</tr>
</thead>
<tbody>
{dataList && dataList.segment &&
dataList.segment.map((segment, index) => (
<tr key={index}>
{/* <td rowSpan="6">TH</td> */}
<td>{segment.type}</td>
<td>{segment.au}</td>
<td>{segment.dif}</td>
</tr>
))}
</tbody>
</TableStyle>
</IndexTableWrap>
</>
);
};
export default SegmentContent;

View File

@@ -1,16 +1,14 @@
import { Fragment, useEffect, useRef, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import Button from '../../components/common/button/Button';
import { TableStyle, TableInfo, ListOption, IndexTableWrap } from '../../styles/Components';
import { DailyDashBoard } from '../../components/IndexManage/index';
import { Title, TableStyle, TableInfo, ListOption, IndexTableWrap } from '../../styles/Components';
import { UserIndexSearchBar, DailyDashBoard } from '../../components/IndexManage/index';
import { userIndexView, userIndexExport } from '../../apis';
import Loading from '../common/Loading';
import { userIndexView } from '../../apis';
import { ExcelDownButton } from '../common';
import { useTranslation } from 'react-i18next';
import { formatStringDate } from '../../utils';
import { AnimatedPageWrapper } from '../common/Layout';
import { UserIndexSearchBar } from '../searchBar';
const UserContent = () => {
const token = sessionStorage.getItem('token');

View File

@@ -1,219 +0,0 @@
import { styled } from 'styled-components';
import { useState, useEffect } from 'react';
import { TableStyle, TableInfo, ListOption } from '../../styles/Components';
import Button from '../../components/common/button/Button';
import VBPSearchBar from '../searchBar/VBPSearchBar';
import { VBPIndexExport, VbpIndexView } from '../../apis';
const VBPContent = () => {
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 [sendDate, setSendDate] = useState(START_DATE);
const [finishDate, setFinishDate] = useState(END_DATE);
const [dataList, setDataList] = useState([]);
useEffect(() => {
fetchData(START_DATE, END_DATE);
}, []);
// console.log(dataList);
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());
setDataList(await VbpIndexView(token, startDateToLocal, endDateToLocal));
setSendDate(startDateToLocal);
setFinishDate(endDateToLocal);
};
// 엑셀 다운로드
const handleXlsxExport = () => {
const fileName = 'Caliverse_VBP_Index.xlsx';
VBPIndexExport(token, fileName, sendDate, finishDate);
};
return (
<>
<VBPSearchBar fetchData={fetchData} />
<TableInfo>
<ListOption>
<Button theme="line" text="엑셀 다운로드" handleClick={handleXlsxExport} />
</ListOption>
</TableInfo>
<TableWrapper>
<EconomicTable>
<thead>
<tr>
<th colSpan="2" className="text-center" width="300">
Product
</th>
<th width="160">2023-08-07</th>
<th width="160">2023-08-08</th>
<th width="160">2023-08-09</th>
<th width="160">2023-08-10</th>
<th width="160">2023-08-11</th>
<th width="160">2023-08-12</th>
</tr>
</thead>
<tbody>
<tr>
<TableTitle colSpan="2">(Total) VBP 생산량</TableTitle>
<TableData>500000</TableData>
<TableData>500000</TableData>
<TableData>500000</TableData>
<TableData>500000</TableData>
<TableData>500000</TableData>
<TableData>500000</TableData>
</tr>
<tr>
<TableTitle colSpan="2">(Total) VBP 소진량</TableTitle>
<TableData>490000</TableData>
<TableData>490000</TableData>
<TableData>490000</TableData>
<TableData>490000</TableData>
<TableData>490000</TableData>
<TableData>490000</TableData>
</tr>
<tr>
<TableTitle colSpan="2">(Total) VBP 보유량</TableTitle>
<TableData>3.2M</TableData>
<TableData>3.3M</TableData>
<TableData>3.3M</TableData>
<TableData>3.4M</TableData>
<TableData>3.5M</TableData>
<TableData>3.5M</TableData>
</tr>
<tr>
<TableTitle rowSpan="2">GET</TableTitle>
<TableTitle>퀘스트 보상</TableTitle>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
</tr>
<tr>
<TableTitle>시즌패스 보상</TableTitle>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
</tr>
<tr>
<TableTitle rowSpan="2">USE</TableTitle>
<TableTitle>퀘스트 보상</TableTitle>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
</tr>
<tr>
<TableTitle>시즌패스 보상</TableTitle>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
<TableData>150000</TableData>
</tr>
{/* {mokupData.map((data, index) => (
<Fragment key={index}>
<tr>
<td>{data.date}</td>
<td>{data.name}</td>
<td>{data.trader}</td>
<td>{data.id}</td>
<td>{data.key}</td>
</tr>
</Fragment>
))} */}
</tbody>
</EconomicTable>
</TableWrapper>
</>
);
};
export default VBPContent;
const TableWrapper = styled.div`
width: 100%;
min-width: 680px;
overflow: auto;
&::-webkit-scrollbar {
height: 4px;
}
&::-webkit-scrollbar-thumb {
background: #666666;
}
&::-webkit-scrollbar-track {
background: #d9d9d9;
}
${TableStyle} {
width: 100%;
min-width: 900px;
th {
&.cell-nru {
background: #f0f0f0;
border-left: 1px solid #aaa;
border-right: 1px solid #aaa;
}
}
td {
&.blank {
background: #f9f9f9;
}
&.cell-nru {
background: #fafafa;
border-left: 1px solid #aaa;
border-right: 1px solid #aaa;
}
}
}
`;
const TableData = styled.td`
background: ${props => (props.$state === 'danger' ? '#d60000' : props.$state === 'blank' ? '#F9F9F9' : 'transparent')};
color: ${props => (props.$state === 'danger' ? '#fff' : '#2c2c2c')};
`;
const TableTitle = styled.td`
text-align: center;
`;
const EconomicTable = styled(TableStyle)`
${TableData} {
text-align: left;
}
tbody {
tr:nth-child(1),
tr:nth-child(2),
tr:nth-child(3) {
background: #f5fcff;
}
}
`;

View File

@@ -1,27 +1,17 @@
import UserIndexSearchBar from "../searchBar/UserIndexSearchBar";
import RetentionSearchBar from "../searchBar/RetentionSearchBar";
import SegmentSearchBar from "../searchBar/SegmentSearchBar";
import DailyDashBoard from "./DailyDashBoard";
import PlayTimeSearchBar from "../searchBar/PlayTimeSearchBar";
import UserContent from "./UserContent";
import PlayTimeContent from "./PlayTimeContent";
import RetentionContent from "./RetentionContent";
import SegmentContent from "./SegmentContent";
import DailyActiveUserContent from "./DailyActiveUserContent";
import DailyMedalContent from "./DailyMedalContent";
import DailySearchBar from "../searchBar/DailySearchBar";
import CurrencyConsumeContent from "./CurrencyConsumeContent";
import CurrencyAcquireContent from "./CurrencyAcquireContent";
import ItemAcquireContent from "./ItemAcquireContent";
import ItemConsumeContent from "./ItemConsumeContent";
export {
UserIndexSearchBar,
RetentionSearchBar,
SegmentSearchBar,
DailyDashBoard,
PlayTimeSearchBar,
DailyDashBoard,
UserContent,
SegmentContent,
RetentionContent,
PlayTimeContent,
DailySearchBar,
DailyActiveUserContent,
DailyMedalContent,
CurrencyConsumeContent,
CurrencyAcquireContent,
ItemAcquireContent,
ItemConsumeContent
};