유저 조회 접속 상태 표시
유저 조회 kick 처리
This commit is contained in:
@@ -65,6 +65,20 @@ export const UserChangeAdminLevel = async (token, params) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const UserKick = async (token, params) => {
|
||||||
|
try {
|
||||||
|
const res = await Axios.put('/api/v1/users/user-kick', params, {
|
||||||
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.data;
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof Error) {
|
||||||
|
throw new Error('UserKick Error', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 아바타 조회
|
// 아바타 조회
|
||||||
export const UserAvatarView = async (token, guid) => {
|
export const UserAvatarView = async (token, guid) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -247,6 +247,26 @@ export const opSuccessType = [
|
|||||||
{ value: false, name: '실패' },
|
{ value: false, name: '실패' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const opUserSessionType = [
|
||||||
|
{ value: true, name: '접속중' },
|
||||||
|
{ value: false, name: '미접속' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const opYNType = [
|
||||||
|
{ value: true, name: 'Y' },
|
||||||
|
{ value: false, name: 'N' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const opReadType = [
|
||||||
|
{ value: true, name: '확인' },
|
||||||
|
{ value: false, name: '미확인' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const opPickupType = [
|
||||||
|
{ value: true, name: '수령' },
|
||||||
|
{ value: false, name: '미수령' },
|
||||||
|
];
|
||||||
|
|
||||||
// export const logAction = [
|
// export const logAction = [
|
||||||
// { value: "None", name: "ALL" },
|
// { value: "None", name: "ALL" },
|
||||||
// { value: "AIChatDeleteCharacter", name: "NPC 삭제" },
|
// { value: "AIChatDeleteCharacter", name: "NPC 삭제" },
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import Profile from '../../assets/img/datamanage/img-profile.png';
|
import Profile from '../../assets/img/datamanage/img-profile.png';
|
||||||
import NicknameChangeModal from '../../components/DataManage/NicknameChangeModal';
|
import NicknameChangeModal from '../../components/DataManage/NicknameChangeModal';
|
||||||
import EditIcon from '../../assets/img/icon/icon-edit.png';
|
import EditIcon from '../../assets/img/icon/icon-edit.png';
|
||||||
import { UserChangeAdminLevel, UserInfoView } from '../../apis/Users';
|
import { UserChangeAdminLevel, UserInfoView, UserKick } from '../../apis/Users';
|
||||||
import { SelectInput } from '../../styles/Components';
|
import { SelectInput } from '../../styles/Components';
|
||||||
import { adminLevelType, authType, modalTypes } from '../../assets/data';
|
import { adminLevelType, authType, modalTypes } from '../../assets/data';
|
||||||
import DynamicModal from '../common/modal/DynamicModal';
|
import DynamicModal from '../common/modal/DynamicModal';
|
||||||
@@ -16,53 +16,89 @@ import { convertKTC } from '../../utils';
|
|||||||
import { EditButton, ProfileWrapper, UserDefault, UserInfoTable } from '../../styles/ModuleComponents';
|
import { EditButton, ProfileWrapper, UserDefault, UserInfoTable } from '../../styles/ModuleComponents';
|
||||||
import { TableSkeleton } from '../Skeleton/TableSkeleton';
|
import { TableSkeleton } from '../Skeleton/TableSkeleton';
|
||||||
import { UserInfoSkeleton } from '../Skeleton/UserInfoSkeleton';
|
import { UserInfoSkeleton } from '../Skeleton/UserInfoSkeleton';
|
||||||
|
import { opUserSessionType } from '../../assets/data/options';
|
||||||
|
import Button from '../common/button/Button';
|
||||||
|
import { useModal } from '../../utils/hook';
|
||||||
|
import { InitData } from '../../apis/Data';
|
||||||
|
|
||||||
const UserDefaultInfo = ({ userInfo }) => {
|
const UserDefaultInfo = ({ userInfo }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const authInfo = useRecoilValue(authList);
|
const authInfo = useRecoilValue(authList);
|
||||||
|
const token = sessionStorage.getItem('token');
|
||||||
const [pwPop, setPwPop] = useState('hidden');
|
const {
|
||||||
const [gmModal, setGmModal] = useState('hidden');
|
modalState,
|
||||||
|
handleModalView,
|
||||||
|
handleModalClose
|
||||||
|
} = useModal({
|
||||||
|
userKick: 'hidden',
|
||||||
|
gmLevelChange: 'hidden',
|
||||||
|
pwChange: 'hidden'
|
||||||
|
});
|
||||||
|
const [alertMsg, setAlertMsg] = useState('');
|
||||||
const [dataList, setDataList] = useState({});
|
const [dataList, setDataList] = useState({});
|
||||||
const [adminLevel, setAdminLevel] = useState('0');
|
const [adminLevel, setAdminLevel] = useState('0');
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
const handleClick = () => {
|
|
||||||
if (pwPop === 'hidden') setPwPop('view');
|
|
||||||
else setPwPop('hidden');
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
}, [userInfo]);
|
}, [userInfo]);
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
const token = sessionStorage.getItem('token');
|
setLoading(true);
|
||||||
await UserInfoView(token, userInfo.guid).then(data => {
|
await UserInfoView(token, userInfo.guid).then(data => {
|
||||||
setDataList(data);
|
setDataList(data);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleGMChange = (e) =>{
|
const handleSubmit = async (type, param = null) => {
|
||||||
setAdminLevel(e.target.value);
|
|
||||||
setGmModal('view');
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
|
||||||
const token = sessionStorage.getItem('token');
|
|
||||||
let params = {};
|
let params = {};
|
||||||
params.guid = userInfo.guid;
|
|
||||||
params.admin_level = adminLevel;
|
|
||||||
|
|
||||||
await UserChangeAdminLevel(token, params);
|
switch (type) {
|
||||||
|
case "gmLevelChangeSubmit":
|
||||||
|
setAdminLevel(param);
|
||||||
|
|
||||||
handleCancel();
|
handleModalView('gmLevelChange');
|
||||||
await fetchData();
|
break;
|
||||||
}
|
case "userKickSubmit":
|
||||||
|
handleModalView('userKick');
|
||||||
|
break;
|
||||||
|
case "gmLevelChange":
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
const handleCancel = () => {
|
params.guid = userInfo.guid;
|
||||||
setGmModal('hidden');
|
params.admin_level = adminLevel;
|
||||||
|
|
||||||
|
await UserChangeAdminLevel(token, params).then(data =>{
|
||||||
|
setAlertMsg(t('USER_GM_CHANGE_COMPLETE'))
|
||||||
|
}).catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
}).finally(() => {
|
||||||
|
setLoading(false);
|
||||||
|
handleModalClose('gmLevelChange');
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "userKick":
|
||||||
|
params.guid = userInfo.guid;
|
||||||
|
await UserKick(token, params).then((data) =>{
|
||||||
|
setAlertMsg(t('USER_KICK_COMPLETE'))
|
||||||
|
}).catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
}).finally(() => {
|
||||||
|
setLoading(false);
|
||||||
|
handleModalClose('userKick');
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "registComplete":
|
||||||
|
handleModalClose('registComplete');
|
||||||
|
break;
|
||||||
|
case "warning":
|
||||||
|
setAlertMsg('');
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -76,11 +112,11 @@ const UserDefaultInfo = ({ userInfo }) => {
|
|||||||
<UserInfoTable $maxwidth="530px">
|
<UserInfoTable $maxwidth="530px">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th>AID(GUID)</th>
|
<th>GUID</th>
|
||||||
<td>{dataList.user_info && dataList.user_info.aid}</td>
|
<td>{dataList.user_info && dataList.user_info.aid}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>계정 ID</th>
|
<th>Account ID</th>
|
||||||
<td>{dataList.user_info && dataList.user_info.user_id}</td>
|
<td>{dataList.user_info && dataList.user_info.user_id}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -88,12 +124,11 @@ const UserDefaultInfo = ({ userInfo }) => {
|
|||||||
<td>{dataList.user_info && dataList.user_info.nation}</td>
|
<td>{dataList.user_info && dataList.user_info.nation}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>멤버십</th>
|
<th>접속상태</th>
|
||||||
<td>{dataList.user_info && dataList.user_info.membership}</td>
|
<StatusCell>{dataList.user_session !== undefined && opUserSessionType.find(session => session.value === dataList.user_session)?.name}
|
||||||
</tr>
|
{<Button theme={dataList.user_session ? "line" : "disable"} id={"user_session"} name="kick" text="KICK" handleClick={e => handleSubmit('userKickSubmit')} disabled={!dataList.user_session}/>}
|
||||||
<tr>
|
{/*{<Button theme={dataList.user_session ? "line" : "disable"} id={"user_session"} name="kick" text="KICK" handleClick={e => handleSubmit('userKickSubmit')} />}*/}
|
||||||
<th>친구 추천코드</th>
|
</StatusCell>
|
||||||
<td>{dataList.user_info && dataList.user_info.friend_code}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>계정 생성일</th>
|
<th>계정 생성일</th>
|
||||||
@@ -103,10 +138,7 @@ const UserDefaultInfo = ({ userInfo }) => {
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>최근 접속일자</th>
|
<th>최근 접속일자</th>
|
||||||
<td>
|
<td>{dataList.user_info && convertKTC(dataList.user_info.access_dt)}</td>
|
||||||
{/*{dataList.user_info && String(new Date(new Date(dataList.user_info.access_dt).setHours(new Date(dataList.user_info.access_dt).getHours() + 9)).toLocaleString())}*/}
|
|
||||||
{dataList.user_info && convertKTC(dataList.user_info.access_dt)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>최근 종료일자</th>
|
<th>최근 종료일자</th>
|
||||||
@@ -121,7 +153,9 @@ const UserDefaultInfo = ({ userInfo }) => {
|
|||||||
<tr>
|
<tr>
|
||||||
<th>GM권한</th>
|
<th>GM권한</th>
|
||||||
<td>
|
<td>
|
||||||
<SelectInput value={dataList.user_info && dataList.user_info.admin_level} onChange={(e) => handleGMChange(e)} disabled={authInfo.auth_list && !authInfo.auth_list.some(auth => auth.id === authType.userSearchUpdate)} >
|
<SelectInput value={dataList.user_info && dataList.user_info.admin_level}
|
||||||
|
onChange={e => handleSubmit('gmLevelChangeSubmit', e.target.value)}
|
||||||
|
disabled={authInfo.auth_list && !authInfo.auth_list.some(auth => auth.id === authType.userSearchUpdate)} >
|
||||||
{adminLevelType.map((data, index) => (
|
{adminLevelType.map((data, index) => (
|
||||||
<option key={index} value={data.value}>
|
<option key={index} value={data.value}>
|
||||||
{data.name}
|
{data.name}
|
||||||
@@ -149,7 +183,7 @@ const UserDefaultInfo = ({ userInfo }) => {
|
|||||||
hidden={true}
|
hidden={true}
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
handleClick();
|
handleModalClose('pwChange');
|
||||||
}}></EditButton>
|
}}></EditButton>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -172,15 +206,36 @@ const UserDefaultInfo = ({ userInfo }) => {
|
|||||||
</tbody>
|
</tbody>
|
||||||
</UserInfoTable>
|
</UserInfoTable>
|
||||||
</div>
|
</div>
|
||||||
<NicknameChangeModal pwPop={pwPop} handleClick={handleClick} dataList={dataList} />
|
<NicknameChangeModal pwPop={modalState.pwChangeModal} handleClick={() => handleModalClose('pwChange')} dataList={dataList} />
|
||||||
<DynamicModal
|
<DynamicModal
|
||||||
modalType={modalTypes.childOkCancel}
|
modalType={modalTypes.confirmOkCancel}
|
||||||
view={gmModal}
|
view={modalState.gmLevelChangeModal}
|
||||||
modalText={t('USER_GM_CHANGE')}
|
modalText={t('USER_GM_CHANGE')}
|
||||||
handleCancel={handleCancel}
|
handleSubmit={() => handleSubmit('gmLevelChange')}
|
||||||
handleSubmit={handleSubmit}
|
handleCancel={() => handleModalClose('gmLevelChange')}
|
||||||
|
/>
|
||||||
|
<DynamicModal
|
||||||
|
modalType={modalTypes.confirmOkCancel}
|
||||||
|
view={modalState.userKickModal}
|
||||||
|
modalText={t('USER_KICK_CONFIRM')}
|
||||||
|
handleSubmit={() => handleSubmit('userKick')}
|
||||||
|
handleCancel={() => handleModalClose('userKick')}
|
||||||
|
/>
|
||||||
|
{/* 경고 모달 */}
|
||||||
|
<DynamicModal
|
||||||
|
modalType={modalTypes.completed}
|
||||||
|
view={alertMsg ? 'view' : 'hidden'}
|
||||||
|
modalText={alertMsg}
|
||||||
|
handleSubmit={() => setAlertMsg('')}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default UserDefaultInfo;
|
export default UserDefaultInfo;
|
||||||
|
|
||||||
|
const StatusCell = styled.td`
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px;
|
||||||
|
`;
|
||||||
@@ -9,37 +9,41 @@ export const UserInfoSkeleton = () => {
|
|||||||
<SkeletonImg width="200px" height="150px" />
|
<SkeletonImg width="200px" height="150px" />
|
||||||
</ProfileWrapper>
|
</ProfileWrapper>
|
||||||
<UserInfoTable>
|
<UserInfoTable>
|
||||||
<Skeleton width="530px" height="30px" />
|
<tbody>
|
||||||
<Skeleton width="530px" height="30px" />
|
{Array.from({ length: 10 }).map((_, index) => (
|
||||||
<Skeleton width="530px" height="30px" />
|
<tr key={index}>
|
||||||
<Skeleton width="530px" height="30px" />
|
<td>
|
||||||
<Skeleton width="530px" height="30px" />
|
<Skeleton width="530px" height="30px" />
|
||||||
<Skeleton width="530px" height="30px" />
|
</td>
|
||||||
<Skeleton width="530px" height="30px" />
|
</tr>
|
||||||
<Skeleton width="530px" height="30px" />
|
))}
|
||||||
<Skeleton width="530px" height="30px" />
|
</tbody>
|
||||||
<Skeleton width="530px" height="30px" />
|
|
||||||
</UserInfoTable>
|
</UserInfoTable>
|
||||||
</UserDefault>
|
</UserDefault>
|
||||||
<UserInfoTable>
|
<UserInfoTable>
|
||||||
<Skeleton width="750px" height="30px" />
|
<tbody>
|
||||||
<Skeleton width="750px" height="30px" />
|
{Array.from({ length: 4 }).map((_, index) => (
|
||||||
<Skeleton width="750px" height="30px" />
|
<tr key={index}>
|
||||||
<Skeleton width="750px" height="30px" />
|
<td>
|
||||||
|
<Skeleton width="750px" height="30px" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
</UserInfoTable>
|
</UserInfoTable>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const UserDefault = styled.div`
|
const UserDefault = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 40px;
|
gap: 40px;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
`;
|
`;
|
||||||
const ProfileWrapper = styled.div`
|
const ProfileWrapper = styled.div`
|
||||||
width: 150px;
|
width: 150px;
|
||||||
height: 150px;
|
height: 150px;
|
||||||
border-radius: 75px;
|
border-radius: 75px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ const resources = {
|
|||||||
API_FAIL: '처리 중 오류가 발생하였습니다. 잠시 후 다시 한번 진행해 주세요. 오류가 지속될 경우, 담당자에게 문의해주세요.',
|
API_FAIL: '처리 중 오류가 발생하였습니다. 잠시 후 다시 한번 진행해 주세요. 오류가 지속될 경우, 담당자에게 문의해주세요.',
|
||||||
USER_MAIL_DEL_CONFIRM: '해당 우편을 삭제하시겠습니까?',
|
USER_MAIL_DEL_CONFIRM: '해당 우편을 삭제하시겠습니까?',
|
||||||
USER_GM_CHANGE: 'GM 권한을 변경하시겠습니까?',
|
USER_GM_CHANGE: 'GM 권한을 변경하시겠습니까?',
|
||||||
|
USER_GM_CHANGE_COMPLETE: '권한변경을 완료하였습니다.',
|
||||||
|
USER_KICK_CONFIRM: '해당 유저를 Kick 하시겠습니까?',
|
||||||
|
USER_KICK_COMPLETE: '서버에 정상적으로 Kick을 요청하였습니다.',
|
||||||
DEL_COUNT_CHECK: '보유 개수 이상 삭제할 수 없습니다.',
|
DEL_COUNT_CHECK: '보유 개수 이상 삭제할 수 없습니다.',
|
||||||
DEL_COUNT_CONFIRM: '삭제할 아이템 개수를 입력하세요.\n(보유 개수: {{count}})',
|
DEL_COUNT_CONFIRM: '삭제할 아이템 개수를 입력하세요.\n(보유 개수: {{count}})',
|
||||||
CANCEL_CONFIRM: '취소하시겠습니까?\n취소 시 변경된 값은 초기화됩니다.',
|
CANCEL_CONFIRM: '취소하시겠습니까?\n취소 시 변경된 값은 초기화됩니다.',
|
||||||
|
|||||||
Reference in New Issue
Block a user