Files
operationSystem-front/src/components/DataManage/UserRankInfo.js
bcjang ac9bcdda8b 로그인정보 만료시 비밀번호 초기화 추가,
랭킹 강제 초기화 버튼 추가,
랭킹 시스템 조회 및 수정
2025-11-28 16:39:39 +09:00

201 lines
5.6 KiB
JavaScript

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 ? (
<Button
type="primary"
onClick={() => handleSubmit('valueChange', rankType.value)}
>
수정
</Button>
) : 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 ? <TableSkeleton width='30%' count={5} /> :
<>
<div>
<UserDefault>
<Table
columns={columns}
dataSource={data}
pagination={false}
showHeader={false}
bordered
/>
</UserDefault>
</div>
<InputConfirmModal
inputType='number'
view={modalState.valueChangeModal}
handleSubmit={() => handleSubmit('valueChangeConfirm')}
handleCancel={() => handleModalClose('valueChange')}
handleClose={() => handleModalClose('valueChange')}
value={updateValue}
setValue={setUpdateValue}
inputText={t('UPDATE_VALUE_COMMENT',{comment:comment})}
/>
</>
);
};
export default UserRankInfo;