diff --git a/src/apis/Rank.js b/src/apis/Rank.js
index 22c9873..6c98148 100644
--- a/src/apis/Rank.js
+++ b/src/apis/Rank.js
@@ -21,6 +21,40 @@ export const RankingScheduleView = async (token, title, content, status, startDa
}
};
+export const RankingScheduleSimpleView = async (token) => {
+ try {
+ const res = await Axios.get(
+ `/api/v1/rank/schedule/simple-list`,
+ {
+ headers: { Authorization: `Bearer ${token}` },
+ },
+ );
+
+ return res.data.data.list;
+ } catch (e) {
+ if (e instanceof Error) {
+ throw new Error('RankingScheduleSimpleView Error', e);
+ }
+ }
+};
+
+export const RankingSnapshotView = async (token, guid) => {
+ try {
+ const res = await Axios.get(
+ `/api/v1/rank/snapshot/list?guid=${guid}`,
+ {
+ headers: { Authorization: `Bearer ${token}` },
+ },
+ );
+
+ return res.data.data.ranking_snapshot_list;
+ } catch (e) {
+ if (e instanceof Error) {
+ throw new Error('RankingSnapshotView Error', e);
+ }
+ }
+};
+
// 전투시스템 상세보기
export const RankingScheduleDetailView = async (token, id) => {
try {
@@ -36,6 +70,20 @@ export const RankingScheduleDetailView = async (token, id) => {
}
};
+export const RankerListView = async (token, guid, snapshot) => {
+ try {
+ const res = await Axios.get(`/api/v1/rank/ranker/list?guid=${guid}&snapshot=${snapshot}`, {
+ headers: { Authorization: `Bearer ${token}` },
+ });
+
+ return res.data.data;
+ } catch (e) {
+ if (e instanceof Error) {
+ throw new Error('RankerListView Error', e);
+ }
+ }
+};
+
// 랭킹스케줄 등록
export const RankingScheduleSingleRegist = async (token, params) => {
try {
@@ -96,4 +144,74 @@ export const RankingDataView = async (token) => {
throw new Error('RankingDataView Error', e);
}
}
+};
+
+export const RankingInfoView = async (token, guid) => {
+ try {
+ const res = await Axios.get(`/api/v1/rank/info?guid=${guid}`, {
+ headers: { Authorization: `Bearer ${token}` },
+ });
+
+ return res.data.data;
+ } catch (e) {
+ if (e instanceof Error) {
+ throw new Error('RankingInfoView Error', e);
+ }
+ }
+};
+
+export const RankerInfoModify = async (token, params) => {
+ try {
+ const res = await Axios.put(`/api/v1/rank/info`, params, {
+ headers: { Authorization: `Bearer ${token}` },
+ });
+
+ return res.data;
+ } catch (e) {
+ if (e instanceof Error) {
+ throw new Error('RankerInfoModify Error', e);
+ }
+ }
+};
+
+export const RankingUpdate = async (token, guid) => {
+ try {
+ const res = await Axios.put(`/api/v1/rank/ranking/${guid}`, {},{
+ headers: { Authorization: `Bearer ${token}` },
+ });
+
+ return res.data;
+ } catch (e) {
+ if (e instanceof Error) {
+ throw new Error('RankingUpdate Error', e);
+ }
+ }
+};
+
+export const RankingInit = async (token, guid) => {
+ try {
+ const res = await Axios.put(`/api/v1/rank/ranking/init/${guid}`, {},{
+ headers: { Authorization: `Bearer ${token}` },
+ });
+
+ return res.data;
+ } catch (e) {
+ if (e instanceof Error) {
+ throw new Error('RankingInit Error', e);
+ }
+ }
+};
+
+export const RankingSnapshot = async (token, guid) => {
+ try {
+ const res = await Axios.put(`/api/v1/rank/ranking/snapshot/${guid}`, {},{
+ headers: { Authorization: `Bearer ${token}` },
+ });
+
+ return res.data;
+ } catch (e) {
+ if (e instanceof Error) {
+ throw new Error('RankingSnapshot Error', e);
+ }
+ }
};
\ No newline at end of file
diff --git a/src/assets/data/data.js b/src/assets/data/data.js
index fe58ded..0e7c38e 100644
--- a/src/assets/data/data.js
+++ b/src/assets/data/data.js
@@ -153,15 +153,27 @@ export const FieldLabels = {
'create_by': '생성자',
'status': '상태',
'deleted': '삭제 여부',
+ 'guid': 'GUID',
+ 'meta_id': '메타 ID',
+ 'start_dt': '시작일',
+ 'end_dt': '종료일',
+ 'base_dt': '기준일',
+ 'title': '제목',
// 이벤트 필드 관련
'eventId': '이벤트 ID',
'eventName': '이벤트 명',
+ 'event_name': '이벤트 명',
'repeatType': '반복 타입',
- 'eventOperationTime': '운영 시간(초)',
- 'eventStartDt': '시작 시간',
- 'eventEndDt': '종료 시간',
+ 'repeat_type': '반복 타입',
+ 'eventOperationTime': '진행 시간(분)',
+ 'event_operation_time': '진행 시간(분)',
+ 'eventStartDt': '이벤트 시작일',
+ 'event_start_dt': '이벤트 시작일',
+ 'eventEndDt': '이벤트 종료일',
+ 'event_end_dt': '이벤트 종료일',
'roundTime': '라운드 시간(초)',
+ 'round_time': '라운드 시간(초)',
'roundCount': '라운드 수',
'hotTime': '핫타임',
'configId': '설정 ID',
@@ -203,6 +215,20 @@ export const FieldLabels = {
'gacha_group_id': '랜덤박스 그룹 ID',
'ugq_action': 'UGQ 사용 가능 여부',
'linked_land': '연결된 랜드 ID',
+
+ //스케줄
+ 'refresh_interval': '새로고침 주기',
+ 'initialization_interval': '초기화 주기',
+ 'snapshot_interval': '스냅샷 주기',
+ 'event_action_id': '이벤트 액션 그룹',
+ 'global_event_action_id': '이벤트 액션 그룹',
+ 'personal_event_action_id': '개인제작 액션 그룹',
+ 'max_point': '기여도 목표점수',
+
+ //메뉴
+ 'image_list': '이미지 목록',
+ 'is_link': '링크 여부',
+ 'order_id': '정렬'
};
export const historyTables = {
diff --git a/src/assets/data/menuConfig.js b/src/assets/data/menuConfig.js
index 9d8e3fa..8b03463 100644
--- a/src/assets/data/menuConfig.js
+++ b/src/assets/data/menuConfig.js
@@ -130,7 +130,16 @@ export const menuConfig = {
rankmanage: {
title: '랭킹 점수 관리',
permissions: {
- read: authType.rankManagerRead
+ read: authType.rankManagerRead,
+ update: authType.rankManagerUpdate,
+ },
+ view: true,
+ authLevel: adminAuthLevel.NONE
+ },
+ rankview: {
+ title: '랭킹 시스템 조회',
+ permissions: {
+ read: authType.rankInfoRead,
},
view: true,
authLevel: adminAuthLevel.NONE
diff --git a/src/assets/data/options.js b/src/assets/data/options.js
index f5dd37b..3775be5 100644
--- a/src/assets/data/options.js
+++ b/src/assets/data/options.js
@@ -45,9 +45,9 @@ export const TabUserIndexList = [
];
export const TabRankManageList = [
- { value: 'PIONEER', name: '개척자 랭킹 보드' },
- { value: 'RUN_RACE', name: '점프 러너 랭킹 보드' },
- { value: 'BATTLE_OBJECT', name: '컴뱃 존 랭킹 보드' }
+ { value: 'RANK', name: '랭킹 보드' },
+ // { value: 'RUN_RACE', name: '점프 러너 랭킹 보드' },
+ // { value: 'BATTLE_OBJECT', name: '컴뱃 존 랭킹 보드' }
];
export const mailSendType = [
@@ -245,6 +245,12 @@ export const itemSearchType = [
{ value: 'NAME', name: '아이템명' },
];
+export const instanceSearchType = [
+ { value: 'ID', name: '인스턴스 ID' },
+ { value: 'NAME', name: '인스턴스명' },
+ { value: 'BUILDING', name: '빌딩 ID' },
+];
+
export const blockType = [
{ value: '', name: '선택' },
{ value: 'Access_Restrictions', name: '접근 제한' },
@@ -419,6 +425,22 @@ export const opPropRecipeType = [
{ value: 'Add', name: '등록 필요' },
];
+export const opInstanceContentsType = [
+ { value: 'ALL', name: '전체' },
+ { value: 'Concert', name: 'Concert' },
+ { value: 'Movie', name: 'Movie' },
+ { value: 'Meeting', name: 'Meeting' },
+ { value: 'MyHome', name: 'MyHome' },
+ { value: 'Normal', name: 'Normal' },
+];
+
+export const opInstanceAccessType = [
+ { value: 'ALL', name: '전체' },
+ { value: 'Public', name: 'Public' },
+ { value: 'Item', name: 'Item' },
+ { value: 'Belong', name: 'Belong' },
+];
+
export const opEquipType = [
{ value: 0, name: '미장착' },
{ value: 1, name: '의상장착' },
@@ -654,6 +676,18 @@ export const opCommonStatus = [
{ value: 'RUNNING', name: '진행중' },
]
+export const opRankingType = [
+ { value: 'PIONEER', name: '개척자' },
+ { value: 'RUNNER1', name: '점프러너 - 맵1' },
+ { value: 'RUNNER2', name: '점프러너 - 맵2' },
+ { value: 'RUNNER3', name: '점프러너 - 맵3' },
+ { value: 'RUNNER4', name: '점프러너 - 맵4' },
+ { value: 'BATTLE_FFA', name: '컴뱃존 - FFA' },
+ { value: 'BATTLE_TEAM', name: '컴뱃존 - TEAM' },
+ { value: 'EVENT_CONTRIBUTION', name: '월드 이벤트 - 기여도' },
+ { value: 'EVENT_CRAFT', name: '월드 이벤트 - 개인 제작' },
+]
+
// export const logAction = [
// { value: "None", name: "ALL" },
// { value: "AIChatDeleteCharacter", name: "NPC 삭제" },
@@ -1128,6 +1162,10 @@ export const logAction = [
{ value: "QuestMailSend", name: "QuestMailSend" },
{ value: "QuestMainTask", name: "QuestMainTask" },
{ value: "QuestTaskUpdate", name: "QuestTaskUpdate" },
+ { value: "RankingStart", name: "RankingStart" },
+ { value: "RankingFinish", name: "RankingFinish" },
+ { value: "RankingScoreUpdate", name: "RankingScoreUpdate" },
+ { value: "RankingEventActionScore", name: "RankingEventActionScore" },
{ value: "RefuseFriendRequest", name: "RefuseFriendRequest" },
{ value: "RenameFriendFolder", name: "RenameFriendFolder" },
{ value: "RenameMyhome", name: "RenameMyhome" },
@@ -1199,6 +1237,7 @@ export const logAction = [
{ value: "UserLogout", name: "UserLogout" },
{ value: "UserLogoutSnapShot", name: "UserLogoutSnapShot" },
{ value: "UserReport", name: "UserReport" },
+ { value: "WorldEventActionScore", name: "WorldEventActionScore" },
{ value: "Warp", name: "Warp" },
{ value: "igmApiLogin", name: "igmApiLogin" }
];
@@ -1239,6 +1278,7 @@ export const logDomain = [
{ value: "Cart", name: "Cart" },
{ value: "Currency", name: "Currency" },
{ value: "CustomDefineUi", name: "CustomDefineUi" },
+ { value: "EventActionScore", name: "EventActionScore" },
{ value: "EscapePosition", name: "EscapePosition" },
{ value: "Friend", name: "Friend" },
{ value: "Farming", name: "Farming" },
@@ -1275,6 +1315,8 @@ export const logDomain = [
{ value: "QuestMain", name: "QuestMain" },
{ value: "QuestUgq", name: "QuestUgq" },
{ value: "QuestMail", name: "QuestMail" },
+ { value: "Ranking", name: "Ranking" },
+ { value: "Ranker", name: "Ranker" },
{ value: "RenewalShopProducts", name: "RenewalShopProducts" },
{ value: "Rental", name: "Rental" },
{ value: "RewardProp", name: "RewardProp" },
diff --git a/src/assets/data/pages/rankingTable.json b/src/assets/data/pages/rankingTable.json
index eb17f41..8c276fb 100644
--- a/src/assets/data/pages/rankingTable.json
+++ b/src/assets/data/pages/rankingTable.json
@@ -9,6 +9,30 @@
"orderType": "desc",
"pageType": "default",
"buttons": [
+ {
+ "id": "update",
+ "text": "강제 새로고침",
+ "theme": "line",
+ "disableWhen": "noSelection",
+ "requiredAuth": "rankingUpdate",
+ "action": "update"
+ },
+ {
+ "id": "init",
+ "text": "강제 초기화",
+ "theme": "line",
+ "disableWhen": "noSelection",
+ "requiredAuth": "rankingUpdate",
+ "action": "rankingInit"
+ },
+ {
+ "id": "snapshot",
+ "text": "강제 스냅샷",
+ "theme": "line",
+ "disableWhen": "noSelection",
+ "requiredAuth": "rankingUpdate",
+ "action": "rankingSnapshot"
+ },
{
"id": "delete",
"text": "선택 삭제",
diff --git a/src/assets/data/types.js b/src/assets/data/types.js
index e667e3b..9fd5452 100644
--- a/src/assets/data/types.js
+++ b/src/assets/data/types.js
@@ -62,6 +62,8 @@ export const authType = {
worldEventUpdate: 60,
worldEventDelete: 61,
craftingDictionaryRead: 62,
+ rankInfoRead: 63,
+ instanceDictionaryRead: 64,
levelReader: 999,
diff --git a/src/components/DataManage/RankPioneerInfo.js b/src/components/DataManage/RankPioneerInfo.js
new file mode 100644
index 0000000..2e2dfdd
--- /dev/null
+++ b/src/components/DataManage/RankPioneerInfo.js
@@ -0,0 +1,99 @@
+import styled from 'styled-components';
+import { useState, useEffect } from 'react';
+import { UserToolView } from '../../apis/Users';
+import { TableSkeleton } from '../Skeleton/TableSkeleton';
+
+const RankPioneerInfo = ({ userInfo }) => {
+ const [dataList, setDataList] = useState();
+ const [rowData, setRowData] = useState([]);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ if(userInfo && Object.keys(userInfo).length > 0) {
+ fetchData();
+ }
+ }, []);
+
+ useEffect(() => {
+ if(dataList && dataList.slot_list)
+ setRowData([
+ { title: 'GUID', itemNo: dataList.slot_list.slot1?.tool_id, itemName: dataList?.slot_list.slot1?.tool_name },
+ { title: '아바타명', itemNo: dataList.slot_list.slot2?.tool_id, itemName: dataList?.slot_list.slot2?.tool_name },
+ { title: '점수', itemNo: dataList.slot_list.slot3?.tool_id, itemName: dataList?.slot_list.slot3?.tool_name },
+ ])
+ }, [dataList])
+
+ const fetchData = async () => {
+ const token = sessionStorage.getItem('token');
+ await UserToolView(token, userInfo.guid).then(data => {
+ setDataList(data);
+ setLoading(false);
+ });
+ };
+
+ return (
+ loading ? :
+ <>
+
+
+
+
+
+
+
+
+ {rowData && rowData.map((el, idx) => {
+ return (
+
+ | {el.title} |
+ {el.itemNo} |
+ {el.itemName} |
+
+ );
+ })}
+
+
+
+ >
+ );
+};
+
+export default RankPioneerInfo;
+
+const UserInfoTable = styled.table`
+ width: 100%;
+ max-width: ${props => props.$maxwidth || 'auto'};
+ font-size: 13px;
+ border-radius: 15px;
+ overflow: hidden;
+ tr:first-child {
+ th,
+ td {
+ border-top: 0;
+ }
+ }
+ th,
+ td {
+ height: 36px;
+ vertical-align: middle;
+ border-top: 1px solid #d9d9d9;
+ }
+ th {
+ width: 120px;
+ background: #888;
+ color: #fff;
+ font-weight: 700;
+ }
+ td {
+ background: #fff;
+ padding: 0 20px;
+ }
+`;
+
+const ToolWrapper = styled.div`
+ ${UserInfoTable} {
+ td {
+ border-left: 1px solid #d9d9d9;
+ }
+ }
+`;
diff --git a/src/components/DataManage/RankingSnapshotInfo.js b/src/components/DataManage/RankingSnapshotInfo.js
new file mode 100644
index 0000000..371f7a2
--- /dev/null
+++ b/src/components/DataManage/RankingSnapshotInfo.js
@@ -0,0 +1,84 @@
+import React, { useRef } from 'react';
+import { TableSkeleton } from '../Skeleton/TableSkeleton';
+import { RankInfoSearchBar, useRankInfoSearch } from '../searchBar';
+import { useDataFetch } from '../../hooks/hook';
+import { RankingScheduleSimpleView } from '../../apis';
+import { FormWrapper, TableStyle, TableWrapper } from '../../styles/Components';
+import { ExcelDownButton, ViewTableInfo } from '../common';
+import { useTranslation } from 'react-i18next';
+import { formatTimeFromSeconds } from '../../utils';
+
+const RankingSnapshotInfo = () => {
+ const token = sessionStorage.getItem('token');
+ const tableRef = useRef(null);
+ const { t } = useTranslation();
+
+ const {
+ config,
+ loading: dataLoading,
+ searchParams,
+ data: dataList,
+ handleSearch,
+ handleReset,
+ updateSearchParams,
+ snapshotData
+ } = useRankInfoSearch(token);
+
+ const {
+ data: rankingScheduleData
+ } = useDataFetch(() => RankingScheduleSimpleView(token), [token]);
+
+ return (
+ <>
+
+ {
+ if (executeSearch) {
+ handleSearch(newParams);
+ } else {
+ updateSearchParams(newParams);
+ }
+ }}
+ onReset={handleReset}
+ scheduleData={rankingScheduleData}
+ snapshotData={snapshotData}
+ />
+
+
+
+
+ {dataLoading ? :
+
+
+
+
+
+ | 순위 |
+ account ID |
+ GUID |
+ 아바타명 |
+ 점수 |
+
+
+
+ {dataList?.ranker_List?.map((rank, index) => (
+
+ | {rank.rank} |
+ {rank.account_id} |
+ {rank.user_guid} |
+ {rank.nickname} |
+ {rank.score_type === "Time" ? formatTimeFromSeconds(rank.score) : rank.score} |
+
+ ))}
+
+
+
+ }
+ >
+ );
+};
+
+export default RankingSnapshotInfo;
+
diff --git a/src/components/DataManage/UserRankInfo.js b/src/components/DataManage/UserRankInfo.js
new file mode 100644
index 0000000..7cef225
--- /dev/null
+++ b/src/components/DataManage/UserRankInfo.js
@@ -0,0 +1,201 @@
+import React, { useCallback, useEffect, useState } from 'react';
+
+import NicknameChangeModal from '../../components/DataManage/NicknameChangeModal';
+import { UserInfoView } from '../../apis/Users';
+import { authType } from '../../assets/data';
+import { useTranslation } from 'react-i18next';
+import { useRecoilValue } from 'recoil';
+import { authList } from '../../store/authList';
+import { UserDefault } from '../../styles/ModuleComponents';
+import { TableSkeleton } from '../Skeleton/TableSkeleton';
+import { UserInfoSkeleton } from '../Skeleton/UserInfoSkeleton';
+import { useModal } from '../../hooks/hook';
+import { useAlert } from '../../context/AlertProvider';
+import { useLoading } from '../../context/LoadingProvider';
+import { alertTypes } from '../../assets/data/types';
+import { Button, Col, Descriptions, InputNumber, Row, Space, Table } from 'antd';
+import { RankerInfoModify, RankingInfoView } from '../../apis';
+import { InputItem, TextInput } from '../../styles/Components';
+import CustomConfirmModal from '../common/modal/CustomConfirmModal';
+import InputConfirmModal from '../common/modal/InputConfirmModal';
+import { opRankingType } from '../../assets/data/options';
+import { formatTimeFromSeconds } from '../../utils';
+
+const UserRankInfo = ({ userInfo }) => {
+ const { t } = useTranslation();
+ const authInfo = useRecoilValue(authList);
+ const token = sessionStorage.getItem('token');
+ const {showModal, showToast} = useAlert();
+ const {withLoading} = useLoading();
+
+ const {
+ modalState,
+ handleModalView,
+ handleModalClose
+ } = useModal({
+ valueChange: 'hidden'
+ });
+ const [dataList, setDataList] = useState({});
+ const [loading, setLoading] = useState(true);
+ const [authUpdate, setAuthUpdate] = useState(false);
+ const [selectRow, setSelectRow] = useState();
+ const [updateValue, setUpdateValue] = useState();
+ const [comment, setComment] = useState();
+
+ useEffect(() => {
+ setAuthUpdate(authInfo?.auth_list?.some(auth => auth.id === authType.rankManagerUpdate));
+ }, [authInfo]);
+
+ useEffect(() => {
+ if(userInfo && Object.keys(userInfo).length > 0) {
+ fetchData();
+ }
+ }, [userInfo]);
+
+ const fetchData = async () => {
+ setLoading(true);
+ await RankingInfoView(token, userInfo.guid).then(data => {
+ setDataList(data.user_ranking_info);
+ }).catch(error => {
+ showToast(error, {type: alertTypes.error});
+ }).finally(() => {
+ setLoading(false);
+ });
+ };
+
+ const findAndFormatScore = (rankingType) => {
+ if (!dataList?.rankingItems) return '';
+ const item = dataList.rankingItems.find(item => item.rankingType === rankingType);
+
+ if (!item || item.score === null || item.score === undefined) return '';
+
+ // scoreType이 "Time"이면 시:분:초 형식으로 변환 (초 단위로 가정)
+ if (item.scoreType === "Time") {
+ return formatTimeFromSeconds(item.score);
+ }
+
+ // 그 외의 경우는 숫자 그대로 반환
+ return item.score.toString();
+ };
+
+ const columns = [
+ {
+ dataIndex: 'label',
+ width: 200,
+ onCell: () => ({
+ style: {
+ backgroundColor: '#f0f0f0',
+ fontWeight: 'bold'
+ }
+ })
+ },
+ {
+ dataIndex: 'content',
+ width: 300,
+ },
+ {
+ dataIndex: 'action',
+ },
+ ];
+
+ const generateTableData = () => {
+ if (!dataList) return [];
+
+ const baseData = [
+ {
+ key: 'guid',
+ label: 'GUID',
+ content: userInfo?.guid || '',
+ action: null
+ },
+ {
+ key: 'nickname',
+ label: '아바타명',
+ content: dataList?.nickname || userInfo?.nickname || '',
+ action: null
+ }
+ ];
+
+ // opRankingType을 기반으로 동적 생성
+ const rankingData = opRankingType.map(rankType => {
+ const formattedScore = findAndFormatScore(rankType.value);
+ const hasScore = formattedScore !== '';
+
+ return {
+ key: rankType.value.toLowerCase(),
+ label: rankType.name,
+ content: formattedScore,
+ action: authUpdate && hasScore ? (
+
+ ) : null
+ };
+ });
+
+ return [...baseData, ...rankingData];
+ };
+
+ const data = generateTableData();
+
+ const handleSubmit = async (type, param = null) => {
+ let params = {};
+
+ switch (type) {
+ case "valueChange":
+ setSelectRow(param);
+ const comment = dataList.rankingItems.find(item => item.rankingType === param)?.scoreType === 'Time' ? '초단위로 입력해주세요.' : '점수';
+ setComment(comment);
+ handleModalView('valueChange');
+ break;
+ case "valueChangeConfirm":
+ const item = dataList.rankingItems.find(item => item.rankingType === selectRow);
+ params.guid = item.guid;
+ params.score = updateValue;
+ params.user_guid = userInfo.guid;
+
+ await withLoading(async () => {
+ return await RankerInfoModify(token, params);
+ }).then(data => {
+ showToast('UPDATE_COMPLETED', {type: alertTypes.success});
+ fetchData();
+ }).catch(error => {
+ showToast(error, {type: alertTypes.error});
+ }).finally(() => {
+ handleModalClose('valueChange');
+ });
+ break;
+ }
+ }
+
+ return (
+ loading ? :
+ <>
+
+ handleSubmit('valueChangeConfirm')}
+ handleCancel={() => handleModalClose('valueChange')}
+ handleClose={() => handleModalClose('valueChange')}
+ value={updateValue}
+ setValue={setUpdateValue}
+ inputText={t('UPDATE_VALUE_COMMENT',{comment:comment})}
+ />
+ >
+ );
+};
+export default UserRankInfo;
\ No newline at end of file
diff --git a/src/components/DataManage/index.js b/src/components/DataManage/index.js
new file mode 100644
index 0000000..c0fc13b
--- /dev/null
+++ b/src/components/DataManage/index.js
@@ -0,0 +1,24 @@
+export { default as UserDefaultInfo } from './UserDefaultInfo';
+export { default as UserAvatarInfo } from './UserAvatarInfo';
+export { default as UserDressInfo } from './UserDressInfo';
+export { default as UserToolInfo } from './UserToolInfo';
+export { default as UserInventoryInfo } from './UserInventoryInfo';
+export { default as UserMailInfo } from './UserMailInfo';
+export { default as UserMyHomeInfo } from './UserMyHomeInfo';
+export { default as UserFriendInfo } from './UserFriendInfo';
+export { default as UserTattooInfo } from './UserTattooInfo';
+export { default as UserQuestInfo } from './UserQuestInfo';
+export { default as UserClaimInfo } from './UserClaimInfo';
+export { default as CurrencyLogContent } from './CurrencyLogContent';
+export { default as ItemLogContent } from './ItemLogContent';
+export { default as CurrencyItemLogContent } from './CurrencyItemLogContent';
+export { default as UserLoginLogContent } from './UserLoginLogContent';
+export { default as UserCreateLogContent } from './UserCreateLogContent';
+export { default as UserSnapshotLogContent } from './UserSnapshotLogContent';
+export { default as RankPioneerInfo } from './RankPioneerInfo';
+export { default as LandDetailModal } from './LandDetailModal';
+export { default as MailDetailModal } from './MailDetailModal';
+export { default as QuestDetailModal } from './QuestDetailModal';
+export { default as NicknameChangeModal } from './NicknameChangeModal';
+export { default as UserRankInfo } from './UserRankInfo';
+export { default as RankingSnapshotInfo } from './RankingSnapshotInfo';
diff --git a/src/components/common/modal/InputConfirmModal.js b/src/components/common/modal/InputConfirmModal.js
new file mode 100644
index 0000000..102ced9
--- /dev/null
+++ b/src/components/common/modal/InputConfirmModal.js
@@ -0,0 +1,47 @@
+import { BtnWrapper, ButtonClose, InputItem, ModalText } from '../../../styles/Components';
+import Button from '../button/Button';
+import Modal from './Modal';
+import { Input, InputNumber } from 'antd';
+import React from 'react';
+
+const InputConfirmModal = ({view, handleClose, handleCancel, handleSubmit, inputText, inputType, value, setValue}) => {
+ return (
+
+
+
+
+
+
+ {inputText}
+ { inputType === 'number' &&
+ setValue(value)}
+ />}
+ { inputType === 'text' &&
+ setValue(value)}
+ />}
+
+
+
+
+
+
+
+
+ );
+}
+
+export default InputConfirmModal;
\ No newline at end of file
diff --git a/src/components/common/modal/LogDetailModal.js b/src/components/common/modal/LogDetailModal.js
index 5443bc3..e8a7dc7 100644
--- a/src/components/common/modal/LogDetailModal.js
+++ b/src/components/common/modal/LogDetailModal.js
@@ -161,7 +161,7 @@ const LogDetailModal = ({ detailView,
return (
| {getFieldLabel(item.sourceInfo.operationType)} |
- {item.fieldName} |
+ {getFieldLabel(item.fieldName)} |
{formatValue(item.newValue)} |
{formatValue(item.oldValue)} |
{item.sourceInfo.worker} |
diff --git a/src/components/modal/EventModal.js b/src/components/modal/EventModal.js
index cf77ca2..df70a5a 100644
--- a/src/components/modal/EventModal.js
+++ b/src/components/modal/EventModal.js
@@ -59,8 +59,8 @@ const EventModal = ({ modalType, detailView, handleDetailView, content, setDetai
const opEventActionMode = useMemo(() => {
return eventActionData?.map(item => ({
- value: item.id,
- name: `${item.description}(${item.id})`
+ value: item.groupId,
+ name: `${item.description}(${item.groupId})`
})) || [];
}, [eventActionData]);
diff --git a/src/components/modal/RankingModal.js b/src/components/modal/RankingModal.js
index 8a7293e..3bb6cba 100644
--- a/src/components/modal/RankingModal.js
+++ b/src/components/modal/RankingModal.js
@@ -79,8 +79,8 @@ const RankingModal = ({ modalType, detailView, handleDetailView, content, setDet
const opEventActionMode = useMemo(() => {
return eventActionData?.map(item => ({
- value: item.id,
- name: `${item.description}(${item.id})`
+ value: item.groupId,
+ name: `${item.description}(${item.groupId})`
})) || [];
}, [eventActionData]);
@@ -96,8 +96,9 @@ const RankingModal = ({ modalType, detailView, handleDetailView, content, setDet
if (!checkCondition()) return;
// const minAllowedTime = new Date(new Date().getTime() + 10 * 60000);
- // const startDt = resultData.event_start_dt;
- // const endDt = resultData.event_end_dt;
+ const startDt = resultData.start_dt;
+ const endDt = resultData.end_dt;
+ const baseDt = resultData.base_dt;
// if (modalType === TYPE_REGISTRY && startDt < minAllowedTime) {
// showToast('BATTLE_EVENT_MODAL_START_DT_WARNING', {type: alertTypes.warning});
// return;
@@ -106,12 +107,16 @@ const RankingModal = ({ modalType, detailView, handleDetailView, content, setDet
// showToast('BATTLE_EVENT_MODAL_START_DT_WARNING', {type: alertTypes.warning});
// return;
// }
- //
- // //화면에 머물면서 상태는 안바꼈을 경우가 있기에 시작시간 지났을경우 차단
- // if (modalType === TYPE_REGISTRY && startDt < new Date()) {
- // showToast('BATTLE_EVENT_MODAL_START_DT_WARNING', {type: alertTypes.warning});
- // return;
- // }
+
+ if(startDt > baseDt){
+ showToast('SCHEDULE_MODAL_START_DIFF_BASE_WARNING', {type: alertTypes.warning});
+ return;
+ }
+
+ if(startDt > endDt){
+ showToast('SCHEDULE_MODAL_START_DIFF_END_WARNING', {type: alertTypes.warning});
+ return;
+ }
showModal(isView('modify') ? 'SCHEDULE_UPDATE_CONFIRM' : 'SCHEDULE_REGIST_CONFIRM', {
type: alertTypes.confirm,
@@ -132,7 +137,11 @@ const RankingModal = ({ modalType, detailView, handleDetailView, content, setDet
if(data.result === "SUCCESS") {
showToast('UPDATE_COMPLETED', {type: alertTypes.success});
}else{
- showToast('UPDATE_FAIL', {type: alertTypes.error});
+ if(data.data.message){
+ showToast(data.data.message, {type: alertTypes.error});
+ }else{
+ showToast('UPDATE_FAIL', {type: alertTypes.error});
+ }
}
}).catch(reason => {
showToast('API_FAIL', {type: alertTypes.error});
@@ -147,7 +156,11 @@ const RankingModal = ({ modalType, detailView, handleDetailView, content, setDet
if(data.result === "SUCCESS") {
showToast('REGIST_COMPLTE', {type: alertTypes.success});
}else{
- showToast('REGIST_FAIL', {type: alertTypes.error});
+ if(data.data.message){
+ showToast(data.data.message, {type: alertTypes.error});
+ }else{
+ showToast('REGIST_FAIL', {type: alertTypes.error});
+ }
}
}).catch(reason => {
showToast('API_FAIL', {type: alertTypes.error});
@@ -168,7 +181,6 @@ const RankingModal = ({ modalType, detailView, handleDetailView, content, setDet
&& resultData.event_action_id > 0
&& resultData.title !== ''
&& resultData.refresh_interval > 0
- && resultData.initialization_interval > 0
&& resultData.snapshot_interval > 0
);
};
@@ -368,9 +380,9 @@ export const initData = {
start_dt: '',
end_dt: '',
base_dt: '',
- refresh_interval: 60,
- initialization_interval: 0,
- snapshot_interval: 1440,
+ refresh_interval: 5,
+ initialization_interval: 240,
+ snapshot_interval: 60,
meta_id: '',
event_action_id: '',
}
diff --git a/src/components/searchBar/RankInfoSearchBar.js b/src/components/searchBar/RankInfoSearchBar.js
new file mode 100644
index 0000000..57cc35e
--- /dev/null
+++ b/src/components/searchBar/RankInfoSearchBar.js
@@ -0,0 +1,162 @@
+import { InputLabel, SelectInput, InputGroup } from '../../styles/Components';
+import { SearchBarLayout } from '../common/SearchBar';
+import { useCallback, useEffect, useState } from 'react';
+import { RankingSnapshotView, RankerListView } from '../../apis';
+
+export const useRankInfoSearch = (token) => {
+ const [searchParams, setSearchParams] = useState({
+ guid: '',
+ snapshot: '',
+ orderBy: 'DESC',
+ currentPage: 1
+ });
+
+ const [loading, setLoading] = useState(false);
+ const [data, setData] = useState(null);
+ const [snapshotData, setSnapshotData] = useState([]);
+
+
+ useEffect(() => {
+ fetchData(searchParams); // 컴포넌트 마운트 시 초기 데이터 로드
+ }, [token]);
+
+ const fetchSnapshotData = useCallback(async (guid) => {
+ if (!guid) {
+ setSnapshotData([]);
+ return;
+ }
+
+ try {
+ const result = await RankingSnapshotView(
+ token,
+ guid
+ );
+ setSnapshotData(result || []);
+ } catch (error) {
+ console.error('Error fetching snapshot data:', error);
+ setSnapshotData([]);
+ }
+ }, [token]);
+
+ useEffect(() => {
+ if (searchParams.guid) {
+ fetchSnapshotData(searchParams.guid);
+ } else {
+ setSnapshotData([]);
+ }
+ }, [searchParams.guid, fetchSnapshotData]);
+
+ const fetchData = useCallback(async (params) => {
+ try {
+ if(params.snapshot === ''){
+ setData();
+ return;
+ }
+
+ setLoading(true);
+ const result = await RankerListView(
+ token,
+ params.guid,
+ params.snapshot,
+ );
+ setData(result);
+ return result;
+ } catch (error) {
+ console.error('Error fetching auction data:', error);
+ throw error;
+ } finally {
+ setLoading(false);
+ }
+ }, [token]);
+
+ const updateSearchParams = useCallback((newParams) => {
+ setSearchParams(prev => ({
+ ...prev,
+ ...newParams
+ }));
+ }, []);
+
+ const handleSearch = useCallback(async (newParams = {}) => {
+ const updatedParams = {
+ ...searchParams,
+ ...newParams,
+ currentPage: newParams.currentPage || 1 // Reset to first page on new search
+ };
+ updateSearchParams(updatedParams);
+ return await fetchData(updatedParams);
+ }, [searchParams, fetchData]);
+
+ const handleReset = useCallback(async () => {
+ const resetParams = {
+ guid: '',
+ snapshot: '',
+ orderBy: 'DESC',
+ currentPage: 1
+ };
+ setSearchParams(resetParams);
+ return await fetchData(resetParams);
+ }, [fetchData]);
+
+ const handlePageChange = useCallback(async (newPage) => {
+ return await handleSearch({ currentPage: newPage });
+ }, [handleSearch]);
+
+ const handleOrderByChange = useCallback(async (newOrder) => {
+ return await handleSearch({ orderBy: newOrder });
+ }, [handleSearch]);
+
+ return {
+ searchParams,
+ loading,
+ data,
+ snapshotData,
+ handleSearch,
+ handleReset,
+ handlePageChange,
+ handleOrderByChange,
+ updateSearchParams
+ };
+};
+
+const RankInfoSearchBar = ({ searchParams, onSearch, onReset, scheduleData, snapshotData }) => {
+ const handleSubmit = event => {
+ event.preventDefault();
+
+ onSearch(searchParams);
+ };
+
+ const searchList = [
+ <>
+ 랭킹스케줄
+
+ onSearch({ guid: e.target.value, snapshot: '' }, false)}>
+
+ {scheduleData?.map((data, index) => (
+
+ ))}
+
+
+ 스냅샷
+
+ onSearch({ snapshot: e.target.value }, false)}>
+
+
+ {snapshotData?.map((data, index) => (
+
+ ))}
+
+
+ >
+ ];
+ return ;
+};
+
+export default RankInfoSearchBar;
\ No newline at end of file
diff --git a/src/components/searchBar/index.js b/src/components/searchBar/index.js
index 80cf4f8..3579a84 100644
--- a/src/components/searchBar/index.js
+++ b/src/components/searchBar/index.js
@@ -40,6 +40,7 @@ import RankManageSearchBar, { useRankManageSearch } from './RankManageSearchBar'
import LandAuctionSearchBar from './LandAuctionSearchBar';
import CaliumRequestSearchBar from './CaliumRequestSearchBar';
import UserSearchBar, {useUserSearch} from './UserSearchBar';
+import RankInfoSearchBar, {useRankInfoSearch} from './RankInfoSearchBar';
// 모든 SearchBar 컴포넌트 export
export {
@@ -101,5 +102,7 @@ export {
useRankManageSearch,
UserSearchBar,
useUserSearch,
+ RankInfoSearchBar,
+ useRankInfoSearch,
};
diff --git a/src/hooks/useRDSPagination.js b/src/hooks/useRDSPagination.js
index 54c9209..a4892cd 100644
--- a/src/hooks/useRDSPagination.js
+++ b/src/hooks/useRDSPagination.js
@@ -1,4 +1,5 @@
import { useCallback, useState } from 'react';
+import { INITIAL_PAGE_SIZE } from '../assets/data/adminConstants';
/**
* RDS 스타일의 페이지네이션을 위한 훅
@@ -12,7 +13,7 @@ export const useRDSPagination = (fetchFunction, initialState = {}) => {
// 페이지네이션 상태
const [pagination, setPagination] = useState({
currentPage: initialState.currentPage || 1,
- pageSize: initialState.pageSize || 10,
+ pageSize: initialState.pageSize || INITIAL_PAGE_SIZE,
totalItems: initialState.totalItems || 0,
totalPages: initialState.totalPages || 0
});
diff --git a/src/pages/DataManage/RankInfoView.js b/src/pages/DataManage/RankInfoView.js
new file mode 100644
index 0000000..0944ef0
--- /dev/null
+++ b/src/pages/DataManage/RankInfoView.js
@@ -0,0 +1,52 @@
+import React, { useRef } from 'react';
+
+import { Title} from '../../styles/Components';
+
+import { authType } from '../../assets/data';
+import { withAuth } from '../../hooks/hook';
+import { AnimatedPageWrapper } from '../../components/common/Layout';
+import { TableSkeleton } from '../../components/Skeleton/TableSkeleton';
+import { Col, Divider, Row } from 'antd';
+import {RankingSnapshotInfo} from '../../components/DataManage';
+
+const RankInfoView = () => {
+
+
+ return (
+
+ 랭킹 시스템 조회
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default withAuth(authType.rankInfoRead)(RankInfoView);
diff --git a/src/pages/DataManage/RankManage.js b/src/pages/DataManage/RankManage.js
index 75a516f..aa40ec1 100644
--- a/src/pages/DataManage/RankManage.js
+++ b/src/pages/DataManage/RankManage.js
@@ -5,10 +5,6 @@ import { AnimatedPageWrapper } from '../../components/common/Layout'
import styled from 'styled-components';
-import UserDefaultInfo from '../../components/DataManage/UserDefaultInfo';
-import UserAvatarInfo from '../../components/DataManage/UserAvatarInfo';
-import UserDressInfo from '../../components/DataManage/UserDressInfo';
-
import { authType } from '../../assets/data';
import { withAuth } from '../../hooks/hook';
import { TabRankManageList } from '../../assets/data/options';
@@ -17,13 +13,13 @@ import {
useUserSearch,
} from '../../components/searchBar';
import { AnimatedTabs } from '../../components/common';
-import { UserRankPioneerInfo } from '../../components/DataManage';
+import { UserRankInfo } from '../../components/DataManage';
const RankManage = () => {
const token = sessionStorage.getItem('token');
const [infoView, setInfoView] = useState('none');
- const [activeTab, setActiveTab] = useState('PIONEER');
+ const [activeTab, setActiveTab] = useState('RANK');
const [resultData, setResultData] = useState();
const {
@@ -50,9 +46,7 @@ const RankManage = () => {
label: el.name,
children: (() => {
switch(el.value) {
- case 'PIONEER': return ;
- case 'RUN_RACE': return ;
- case 'BATTLE_OBJECT': return ;
+ case 'RANK': return ;
default: return null;
}
})()
diff --git a/src/pages/DataManage/index.js b/src/pages/DataManage/index.js
index 772ad81..0ecf36f 100644
--- a/src/pages/DataManage/index.js
+++ b/src/pages/DataManage/index.js
@@ -5,3 +5,4 @@ export { default as BusinessLogView} from './BusinessLogView';
export { default as MetaItemView} from './MetaItemView';
export { default as MetaCraftingView} from './MetaCraftingView';
export { default as RankManage} from './RankManage';
+export { default as RankInfoView} from './RankInfoView';
diff --git a/src/pages/ServiceManage/EventRegist.js b/src/pages/ServiceManage/EventRegist.js
deleted file mode 100644
index 3ea2d07..0000000
--- a/src/pages/ServiceManage/EventRegist.js
+++ /dev/null
@@ -1,467 +0,0 @@
-import React, { useState, Fragment, useEffect } from 'react';
-import Button from '../../components/common/button/Button';
-
-import {
- Title,
- BtnWrapper,
- TextInput,
- SelectInput,
- Label,
- InputLabel,
- Textarea,
- SearchBarAlert,
-} from '../../styles/Components';
-
-import { useNavigate } from 'react-router-dom';
-import { EventIsItem, EventSingleRegist } from '../../apis';
-
-import { authList } from '../../store/authList';
-import { useRecoilValue } from 'recoil';
-import { useTranslation } from 'react-i18next';
-import {
- AppendRegistBox, AppendRegistTable, AreaBtnClose,
- BtnDelete,
- Item,
- ItemList, LangArea, ModalItem, ModalItemList, RegistGroup,
- RegistInputItem,
- RegistInputRow, RegistNotice, RegistTable,
-} from '../../styles/ModuleComponents';
-import AuthModal from '../../components/common/modal/AuthModal';
-import { authType, benItems, currencyItemCode } from '../../assets/data';
-import DateTimeInput from '../../components/common/input/DateTimeInput';
-import { timeDiffMinute } from '../../utils';
-import { useAlert } from '../../context/AlertProvider';
-import { alertTypes, currencyCodeTypes } from '../../assets/data/types';
-import { useLoading } from '../../context/LoadingProvider';
-import { AnimatedPageWrapper } from '../../components/common/Layout';
-
-const EventRegist = () => {
- const navigate = useNavigate();
- const userInfo = useRecoilValue(authList);
- const { t } = useTranslation();
- const token = sessionStorage.getItem('token');
- const { showToast, showModal } = useAlert();
- const { withLoading} = useLoading();
-
- const [item, setItem] = useState(''); // 아이템 값
- const [itemCount, setItemCount] = useState(''); // 아이템 개수
- const [resource, setResource] = useState(currencyCodeTypes.gold); // 자원 값
- const [resourceCount, setResourceCount] = useState(''); // 자원 개수
-
- const [isNullValue, setIsNullValue] = useState(false);
- const [btnValidation, setBtnValidation] = useState(false);
- const [itemCheckMsg, setItemCheckMsg] = useState('');
-
- const [time, setTime] = useState({
- start_hour: '00',
- start_min: '00',
- end_hour: '00',
- end_min: '00',
- }); //시간 정보
-
- const [resultData, setResultData] = useState({
- is_reserve: false,
- start_dt: '',
- end_dt: '',
- event_type: 'ATTD',
- mail_list: [
- {
- title: '',
- content: '',
- language: 'KO',
- },
- {
- title: '',
- content: '',
- language: 'EN',
- },
- {
- title: '',
- content: '',
- language: 'JA',
- }
- ],
- item_list: [],
- guid: '',
- }); //데이터 정보
-
- useEffect(() => {
- if (checkCondition()) {
- setIsNullValue(false);
- } else {
- setIsNullValue(true);
- }
- }, [resultData]);
-
- useEffect(() => {
- setItemCheckMsg('');
- }, [item]);
-
- const combineDateTime = (date, hour, min) => {
- if (!date) return null;
- return new Date(date.getFullYear(), date.getMonth(), date.getDate(), hour, min);
- };
-
- // 날짜 처리
- const handleDateChange = (data, type) => {
- const date = new Date(data);
- setResultData({
- ...resultData,
- [`${type}_dt`]: combineDateTime(date, time[`${type}_hour`], time[`${type}_min`]),
- });
- };
-
- // 시간 처리
- const handleTimeChange = (e, type) => {
- const { id, value } = e.target;
- const newTime = { ...time, [`${type}_${id}`]: value };
- setTime(newTime);
-
- const date = resultData[`${type}_dt`] ? resultData[`${type}_dt`] : new Date();
-
- setResultData({
- ...resultData,
- [`${type}_dt`]: combineDateTime(date, newTime[`${type}_hour`], newTime[`${type}_min`]),
- });
- };
-
- // 아이템 수량 숫자 체크
- const handleItemCount = e => {
- if (e.target.value === '0' || e.target.value === '-0') {
- setItemCount('1');
- e.target.value = '1';
- } else if (e.target.value < 0) {
- let plusNum = Math.abs(e.target.value);
- setItemCount(plusNum);
- } else {
- setItemCount(e.target.value);
- }
- };
-
- // 아이템 추가
- const handleItemList = async () => {
- if(benItems.includes(item)){
- showToast('MAIL_ITEM_ADD_BEN', {type: alertTypes.warning});
- return;
- }
- if(item.length === 0 || itemCount.length === 0) return;
-
- const token = sessionStorage.getItem('token');
- const result = await EventIsItem(token, {item: item});
-
- if(result.data.result === "ERROR"){
- setItemCheckMsg(t('NOT_ITEM'));
- return;
- }
-
- const itemIndex = resultData.item_list.findIndex((data) => data.item === item);
- if (itemIndex !== -1) {
- showToast('MAIL_ITEM_ADD_DUPL', {type: alertTypes.warning});
- return;
- }
- const newItem = { item: item, item_cnt: itemCount, item_name: result.data.data.item_info.item_name };
-
- resultData.item_list.push(newItem);
- setItem('');
- setItemCount('');
- };
-
- // 추가된 아이템 삭제
- const onItemRemove = id => {
- let filterList = resultData.item_list && resultData.item_list.filter(item => item !== resultData.item_list[id]);
- setResultData({ ...resultData, item_list: filterList });
- };
-
- // 입력창 삭제
- const onLangDelete = language => {
- let filterList = resultData.mail_list && resultData.mail_list.filter(el => el.language !== language);
-
- if (filterList.length === 1) {
- setBtnValidation(true);
- } else {
- setBtnValidation(false);
- }
-
- setResultData({ ...resultData, mail_list: filterList });
- };
-
- // 자원 수량 숫자 체크
- const handleResourceCount = e => {
- if (e.target.value === '0' || e.target.value === '-0') {
- setResourceCount('1');
- e.target.value = '1';
- } else if (e.target.value < 0) {
- let plusNum = Math.abs(e.target.value);
- setResourceCount(plusNum);
- } else {
- setResourceCount(e.target.value);
- }
- };
-
- // 자원 추가
- const handleResourceList = (e) => {
- if(resource.length === 0 || resourceCount.length === 0) return;
-
- const itemIndex = resultData.item_list.findIndex(
- (item) => item.item === resource
- );
-
- if (itemIndex !== -1) {
- const item_cnt = resultData.item_list[itemIndex].item_cnt;
- resultData.item_list[itemIndex].item_cnt = Number(item_cnt) + Number(resourceCount);
- } else {
- const name = currencyItemCode.find(well => well.value === resource).name;
- const newItem = { item: resource, item_cnt: resourceCount, item_name: name };
- resultData.item_list.push(newItem);
- }
- setResourceCount('');
- };
-
- const handleSubmit = async (type, param = null) => {
- switch (type) {
- case "submit":
- if (!checkCondition()) return;
- const timeDiff = timeDiffMinute(resultData.start_dt, (new Date))
- if(timeDiff < 60) {
- showToast('EVENT_TIME_LIMIT_ADD', {type: alertTypes.warning});
- return;
- }
-
- showModal('', {
- type: alertTypes.confirmChildren,
- onConfirm: () => handleSubmit('registConfirm'),
- children:
- {t('EVENT_REGIST_CONFIRM')}
- {resultData.item_list && (
-
- {resultData.item_list.map((data, index) => {
- return (
- -
-
- {data.item_name} {data.item_cnt.toLocaleString()}
-
-
- );
- })}
-
- )}
-
- });
- break;
-
- case "registConfirm":
- await withLoading(async () => {
- return await EventSingleRegist(token, resultData);
- }).then((result) => {
- showToast('REGIST_COMPLTE', {type: alertTypes.success});
- }).catch(() => {
- showToast('API_FAIL', {type: alertTypes.error});
- }).finally(() => {
- callbackPage();
- });
- break;
- }
- }
-
- const callbackPage = () => {
- navigate('/servicemanage/event');
- }
-
- const checkCondition = () => {
- return (
- resultData.mail_list.every(data => data.content !== '' && data.title !== '') &&
- (resultData.start_dt.length !== 0) &&
- (resultData.end_dt.length !== 0)
- );
- };
-
- return (
-
- {userInfo.auth_list && !userInfo.auth_list.some(auth => auth.id === authType.eventUpdate) ? (
-
- ) : (
- <>
- 이벤트 등록
-
-
-
- 이벤트 타입
- setResultData({ ...resultData, event_type: e.target.value })} value={resultData.event_type}>
-
-
-
- handleDateChange(data, 'start')}
- onChange={e => handleTimeChange(e, 'start')}
- />
- handleDateChange(data, 'end')}
- onChange={e => handleTimeChange(e, 'end')}
- />
-
-
- {resultData.mail_list.map((data, idx) => {
- return (
-
-
-
- 언어 : {data.language}
- {btnValidation === false ? (
- {
- e.preventDefault();
- onLangDelete(data.language);
- }}
- />
- ) : (
-
- )}
-
-
-
-
- |
-
- |
-
-
- {
- if (e.target.value.length > 30) {
- return;
- }
- let list = [...resultData.mail_list];
- let findIndex = resultData.mail_list && resultData.mail_list.findIndex(item => item.language === e.target.id);
- list[findIndex].title = e.target.value.trimStart();
-
- setResultData({ ...resultData, mail_list: list });
- }}
- />
-
- 29 ? 'red' : '#666'}>* 최대 등록 가능 글자수 ({data.title.length}/30자)
- |
-
-
- |
-
- |
-
- |
-
-
-
-
-
- );
- })}
-
-
-
-
-
- |
-
- |
-
-
- setItem(e.target.value.trimStart())} />
- handleItemCount(e)} width="100px" />
-
- {itemCheckMsg && {itemCheckMsg}}
-
- |
-
-
- |
-
- |
-
-
- setResource(e.target.value)} value={resource}>
- {currencyItemCode.filter(data => data.value !== currencyCodeTypes.calium).map((data, index) => (
-
- ))}
-
- handleResourceCount(e)} width="200px" />
-
-
-
-
- {resultData.item_list && (
-
- {resultData.item_list.map((data, index) => {
- return (
- -
-
- {data.item_name}[{data.item}] ({data.item_cnt})
-
- onItemRemove(index)}>
-
- );
- })}
-
- )}
-
- |
-
-
-
-
- {isNullValue && (
-
- {t('NULL_MSG')}
-
- )}
-
-
-
- >
- )}
-
- );
-};
-
-export default EventRegist;
-
diff --git a/src/pages/ServiceManage/Ranking.js b/src/pages/ServiceManage/Ranking.js
index 602eb91..df38c97 100644
--- a/src/pages/ServiceManage/Ranking.js
+++ b/src/pages/ServiceManage/Ranking.js
@@ -15,8 +15,8 @@ import { useDataFetch, useModal, useTable, withAuth } from '../../hooks/hook';
import {
EventActionView,
LogHistory,
- RankingDataView, RankingScheduleDelete,
- RankingScheduleDetailView,
+ RankingDataView, RankingInit, RankingScheduleDelete,
+ RankingScheduleDetailView, RankingSnapshot, RankingUpdate,
} from '../../apis';
import { CommonSearchBar } from '../../components/ServiceManage';
import { useAlert } from '../../context/AlertProvider';
@@ -101,6 +101,102 @@ const Ranking = () => {
handleModalView('detail');
});
break;
+ case "update":
+ const sel = selectedRows[0];
+ const guid = sel.guid;
+ if(guid === null || guid === undefined || guid === "") {
+ showToast('SCHEDULE_REFRESH_GUID_NULL_WARNING', {type: alertTypes.warning});
+ return;
+ }
+
+ if(sel.status !== CommonStatus.running) {
+ showToast('UPDATE_STATUS_ONLY_RUNNING', {type: alertTypes.warning});
+ return;
+ }
+
+ showModal('SCHEDULE_SELECT_UPDATE', {
+ type: alertTypes.confirm,
+ onConfirm: () => handleAction('updateConfirm', guid)
+ });
+ break;
+ case "updateConfirm":
+
+ await withLoading(async () => {
+ return await RankingUpdate(token, item);
+ }).then(data => {
+ if(data.result === "SUCCESS") {
+ showToast('SCHEDULE_REFRESH_COMPLETE', {type: alertTypes.success});
+ }else{
+ showToast(data.data.message, {type: alertTypes.error});
+ }
+ }).catch(reason => {
+ showToast('API_FAIL', {type: alertTypes.error});
+ });
+ break;
+ case "rankingInit":
+ const initSel = selectedRows[0];
+ const initGuid = initSel.guid;
+ if(initGuid === null || initGuid === undefined || initGuid === "") {
+ showToast('SCHEDULE_REFRESH_GUID_NULL_WARNING', {type: alertTypes.warning});
+ return;
+ }
+
+ if(initSel.status !== CommonStatus.running) {
+ showToast('UPDATE_STATUS_ONLY_RUNNING', {type: alertTypes.warning});
+ return;
+ }
+
+ showModal('SCHEDULE_SELECT_INIT', {
+ type: alertTypes.confirm,
+ onConfirm: () => handleAction('rankingInitConfirm', initGuid)
+ });
+ break;
+ case "rankingInitConfirm":
+
+ await withLoading(async () => {
+ return await RankingInit(token, item);
+ }).then(data => {
+ if(data.result === "SUCCESS") {
+ showToast('SCHEDULE_INIT_COMPLETE', {type: alertTypes.success});
+ }else{
+ showToast(data.data.message, {type: alertTypes.error});
+ }
+ }).catch(reason => {
+ showToast('API_FAIL', {type: alertTypes.error});
+ });
+ break;
+ case "rankingSnapshot":
+ const snapshotSel = selectedRows[0];
+ const snapshotSGuid = snapshotSel.guid;
+ if(snapshotSGuid === null || snapshotSGuid === undefined || snapshotSGuid === "") {
+ showToast('SCHEDULE_REFRESH_GUID_NULL_WARNING', {type: alertTypes.warning});
+ return;
+ }
+
+ if(snapshotSel.status !== CommonStatus.running) {
+ showToast('UPDATE_STATUS_ONLY_RUNNING', {type: alertTypes.warning});
+ return;
+ }
+
+ showModal('SCHEDULE_SELECT_SNAPSHOT', {
+ type: alertTypes.confirm,
+ onConfirm: () => handleAction('rankingSnapshotConfirm', snapshotSGuid)
+ });
+ break;
+ case "rankingSnapshotConfirm":
+
+ await withLoading(async () => {
+ return await RankingSnapshot(token, item);
+ }).then(data => {
+ if(data.result === "SUCCESS") {
+ showToast('SCHEDULE_SNAPSHOT_COMPLETE', {type: alertTypes.success});
+ }else{
+ showToast(data.data.message, {type: alertTypes.error});
+ }
+ }).catch(reason => {
+ showToast('API_FAIL', {type: alertTypes.error});
+ });
+ break;
case "delete":
showModal('SCHEDULE_SELECT_DELETE', {
diff --git a/src/pages/UserManage/AdminView.js b/src/pages/UserManage/AdminView.js
index 116fa67..348f662 100644
--- a/src/pages/UserManage/AdminView.js
+++ b/src/pages/UserManage/AdminView.js
@@ -14,11 +14,15 @@ import { useNavigate } from 'react-router-dom';
import { authList } from '../../store/authList';
import { useRecoilValue } from 'recoil';
import AuthModal from '../../components/common/modal/AuthModal';
+import { alertTypes } from '../../assets/data/types';
+import { useLoading } from '../../context/LoadingProvider';
function AdminView() {
const token = sessionStorage.getItem('token');
const userInfo = useRecoilValue(authList);
const navigate = useNavigate();
+ const {withLoading} = useLoading();
+ const {showToast} = useLoading();
const [currentPage, setCurrentPage] = useState(1);
@@ -258,14 +262,24 @@ function AdminView() {
handleInitialModalClose();
};
- const handlePasswordInitialize = () => {
- AdminChangePw(token, { email: selectedEmail });
+ const handlePasswordInitialize = async () => {
+ await withLoading(async () => {
+ return await AdminChangePw({ email: selectedEmail });
+ }).then(res => {
+ if (res.status === 200) {
+ showToast('PASSWORD_INIT_COMPLETE', { type: alertTypes.success });
+ } else {
+ showToast('PASSWORD_INIT_ERROR', { type: alertTypes.error });
+ }
+ }).error(err => {
+ showToast('API_FAIL', { type: alertTypes.error });
+ }).finally(() => {
+ handleInitialModalClose();
+ handleConfirmeModalClose();
+ });
// console.log(selectedEmail);
- setConfirmText('비밀번호 초기화가');
- handleInitialModalClose();
- handleConfirmeModalClose();
};
// 전체 선택 구현
const handleAllSelect = () => {