201 lines
5.6 KiB
JavaScript
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; |