345 lines
12 KiB
JavaScript
345 lines
12 KiB
JavaScript
import { Fragment, useEffect, useState } from 'react';
|
|
|
|
import CheckBox from '../../components/common/input/CheckBox';
|
|
|
|
import styled from 'styled-components';
|
|
import { Title, FormWrapper, TableInfo, ListCount, ListOption, TableStyle, SelectInput, TableWrapper, ButtonClose, ModalText, BtnWrapper } from '../../styles/Components';
|
|
import Button from '../../components/common/button/Button';
|
|
|
|
import { ReportListDetailModal, ReportListAnswerModal, ReportListSearchBar, ReportListSummary } from '../../components/ServiceManage';
|
|
import Modal from '../../components/common/modal/Modal';
|
|
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { authList } from '../../store/authList';
|
|
import { useRecoilValue } from 'recoil';
|
|
import { ReportListView, ReportListDetailView, ReportReplyDetail } from '../../apis/Report';
|
|
import Pagination from '../../components/common/Pagination/Pagination';
|
|
import { convertKTC } from '../../utils';
|
|
import AuthModal from '../../components/common/modal/AuthModal';
|
|
import { authType } from '../../assets/data';
|
|
import ViewTableInfo from '../../components/common/Table/ViewTableInfo';
|
|
|
|
const reportType = [
|
|
{ value: 'ALL', name: '전체' },
|
|
{ value: 'UNMANNERED_ACT', name: '비매너 행위' },
|
|
{ value: 'USE_UNHEALTHY_NAMES', name: '불건전 이름 사용' },
|
|
{ value: 'CASH_TRADING', name: '현금거래 행위' },
|
|
{ value: 'INTERFERENCE_GAME', name: '게임 진행 방해' },
|
|
{ value: 'INTERFERENCE_SERVICE', name: '운영서비스 방해' },
|
|
{ value: 'ACCOUNT_EXPLOITATION', name: '계정도용' },
|
|
{ value: 'BUG_ABUSING', name: '버그/어뷰징' },
|
|
{ value: 'USE_HACK', name: '불법프로그램 사용' },
|
|
{ value: 'LEAK_PERSONAL_INFO', name: '개인정보 유출' },
|
|
{ value: 'PRETENDING_GM', name: '운영자 사칭' },
|
|
];
|
|
|
|
const ReportList = () => {
|
|
const navigate = useNavigate();
|
|
const token = sessionStorage.getItem('token');
|
|
const userInfo = useRecoilValue(authList);
|
|
|
|
// 권한 설정용
|
|
let deleteAuth = userInfo.auth_list && userInfo.auth_list.some(auth => auth.id === 31); // 삭제 권한
|
|
let replyAuth = userInfo.auth_list && userInfo.auth_list.some(auth => auth.id === 31); // 답변 권한
|
|
|
|
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 [currentPage, setCurrentPage] = useState(1);
|
|
const [pageSize, setPageSize] = useState(50);
|
|
const [selectedRow, setSelectedRow] = useState([]);
|
|
|
|
const [searchData, setSearchData] = useState({
|
|
startDate: START_DATE,
|
|
endDate: END_DATE,
|
|
reportType: 'ALL',
|
|
status: 'ALL',
|
|
searchType: 'ALL',
|
|
searchKey: '',
|
|
});
|
|
const [orderBy, setOrderBy] = useState('DESC');
|
|
const [detailView, setDetailView] = useState('hidden');
|
|
const [answerView, setAnswerView] = useState('hidden');
|
|
|
|
const [dataList, setDataList] = useState([]);
|
|
|
|
// 신고내역 상세 조회용
|
|
const [detailData, setDetailData] = useState([]);
|
|
|
|
// 신고답변 상세 조회용
|
|
const [replyData, setReplyData] = useState([]);
|
|
const [pkId, setPkId] = useState('');
|
|
const [skId, setSkId] = useState('');
|
|
|
|
const [deleteModalClose, setDeleteModalClose] = useState('hidden');
|
|
const [confirmModalClose, setConfirmModalClose] = useState('hidden');
|
|
|
|
useEffect(() => {
|
|
fetchData(START_DATE, END_DATE, 'ALL', 'ALL', 'ALL', '');
|
|
}, [currentPage]);
|
|
|
|
const fetchData = async (startDate, endDate, reportType, status, searchType, searchKey, order, size) => {
|
|
await ReportListView(
|
|
token,
|
|
startDate && new Date(startDate).toISOString().split('.')[0],
|
|
endDate && new Date(endDate).toISOString().split('.')[0],
|
|
reportType && reportType,
|
|
status && status,
|
|
searchType && searchType,
|
|
searchKey && searchKey,
|
|
order ? order : orderBy,
|
|
size ? size : pageSize,
|
|
currentPage,
|
|
).then(data => {
|
|
setDataList(data);
|
|
})
|
|
};
|
|
|
|
const handlePageSize = e => {
|
|
const size = e.target.value;
|
|
setPageSize(size);
|
|
setCurrentPage(1);
|
|
|
|
fetchData(searchData.startDate, searchData.endDate, searchData.reportType, searchData.status, searchData.searchType, searchData.searchKey, orderBy, size, 1);
|
|
};
|
|
|
|
const handleDetail = async (e, pk, sk) => {
|
|
const pkData = encodeURIComponent(pk);
|
|
const skData = encodeURIComponent(sk);
|
|
|
|
e.preventDefault();
|
|
setPkId(pk);
|
|
setSkId(sk);
|
|
|
|
setDetailData(await ReportListDetailView(token, pkData, skData));
|
|
|
|
handleDetailView();
|
|
};
|
|
|
|
// 상세 정보 모달 띄우기
|
|
const handleDetailView = () => {
|
|
if (detailView === 'hidden') {
|
|
setDetailView('block');
|
|
} else {
|
|
setDetailView('hidden');
|
|
}
|
|
};
|
|
|
|
// 신고 답변 불러오기
|
|
const handleReply = async e => {
|
|
const pk = encodeURIComponent(pkId);
|
|
const sk = encodeURIComponent(skId);
|
|
|
|
setReplyData(await ReportReplyDetail(token, pk, sk));
|
|
handleReplyView();
|
|
};
|
|
|
|
// 답변 모달 띄우기
|
|
const handleReplyView = () => {
|
|
if (answerView === 'hidden') {
|
|
setDetailView('hidden');
|
|
setAnswerView('block');
|
|
} else {
|
|
setAnswerView('hidden');
|
|
setDetailView('block');
|
|
}
|
|
};
|
|
|
|
// 검색 함수
|
|
const handleSearch = (startDate, endDate, reportType, status, searchType, searchKey) => {
|
|
fetchData(startDate && new Date(startDate).toISOString(), endDate && new Date(endDate).toISOString(), reportType, status, searchType, searchKey, orderBy, pageSize);
|
|
};
|
|
|
|
// 오름차순 내림차순
|
|
const handleOrderBy = e => {
|
|
const order = e.target.value;
|
|
|
|
setOrderBy(order);
|
|
fetchData(
|
|
searchData.startDate && new Date(searchData.startDate).toISOString().split('.')[0],
|
|
searchData.endDate && new Date(searchData.endDate).toISOString().split('.')[0],
|
|
searchData.reportType,
|
|
searchData.status,
|
|
searchData.searchKey,
|
|
order,
|
|
pageSize,
|
|
);
|
|
};
|
|
|
|
// 선택 삭제 함수
|
|
const handleSelectedDelete = () => {
|
|
let list = [];
|
|
|
|
selectedRow.map(data =>
|
|
list.push({
|
|
id: data,
|
|
}),
|
|
);
|
|
|
|
// ReportDelete(token, list);
|
|
|
|
handleDeleteModalClose();
|
|
handleConfirmeModalClose();
|
|
};
|
|
|
|
// 선택 삭제 모달
|
|
const handleDeleteModalClose = () => {
|
|
if (selectedRow.length !== 0 && deleteModalClose === 'hidden') {
|
|
setDeleteModalClose('view');
|
|
} else {
|
|
setDeleteModalClose('hidden');
|
|
}
|
|
};
|
|
|
|
// 삭제, 승인, 저장 확인 모달창
|
|
const handleConfirmeModalClose = () => {
|
|
if (confirmModalClose === 'hidden') {
|
|
setConfirmModalClose('view');
|
|
} else {
|
|
setConfirmModalClose('hidden');
|
|
window.location.reload();
|
|
}
|
|
};
|
|
|
|
// 체크박스 선택 리스트
|
|
const handleSelectCheckBox = e => {
|
|
let list = [...selectedRow];
|
|
if (e.target.checked) {
|
|
list.push(e.target.id);
|
|
setSelectedRow(list);
|
|
} else {
|
|
const filterList = list.filter(data => e.target.id !== data);
|
|
setSelectedRow(filterList);
|
|
}
|
|
};
|
|
|
|
// 전체 선택 구현
|
|
const handleAllSelect = () => {
|
|
let list = [];
|
|
if (document.getElementById('check-all').checked === true) {
|
|
dataList.list &&
|
|
dataList.list.map((data, index) => {
|
|
document.getElementsByName('select')[index].checked = true;
|
|
list.push(String(data.id));
|
|
});
|
|
} else if (document.getElementById('check-all').checked === false) {
|
|
for (let i = 0; i < dataList.list.length; i++) {
|
|
dataList.list && dataList.list.map((data, index) => (document.getElementsByName('select')[index].checked = false));
|
|
list = [];
|
|
}
|
|
}
|
|
setSelectedRow(list);
|
|
};
|
|
|
|
const handleCountSelectedRow = () => {
|
|
return currentPage > (dataList && dataList.total) / pageSize ? selectedRow.length === dataList.total % pageSize : selectedRow.length === Number(pageSize);
|
|
};
|
|
|
|
return (
|
|
<>
|
|
{userInfo.auth_list && !userInfo.auth_list.some(auth => auth.id === authType.reportRead) ? (
|
|
<AuthModal/>
|
|
) : (
|
|
<>
|
|
<Title>신고내역 조회 및 답변</Title>
|
|
<ReportListSummary />
|
|
<FormWrapper>
|
|
<ReportListSearchBar handleSearch={handleSearch} setResultData={setSearchData} />
|
|
</FormWrapper>
|
|
<ViewTableInfo handlePageSize={handlePageSize} handleOrderBy={handleOrderBy} total={dataList.total} total_all={dataList.total_all}>
|
|
{deleteAuth && <Button theme={'disable'} text="선택 삭제" />}
|
|
</ViewTableInfo>
|
|
<TableWrapper>
|
|
<TableStyle>
|
|
<caption></caption>
|
|
<thead>
|
|
<tr>
|
|
<th width="40">
|
|
<CheckBox id="check-all" handleCheck={handleAllSelect} checked={handleCountSelectedRow()} />
|
|
</th>
|
|
<th width="80">번호</th>
|
|
<th width="180">신고일자</th>
|
|
<th width="200">신고자</th>
|
|
<th width="15%">신고 유형</th>
|
|
<th width="110">확인 / 답변</th>
|
|
<th width="90">상태</th>
|
|
<th width="180">해결 일자</th>
|
|
<th width="15%">담당자(이메일주소)</th>
|
|
{deleteAuth && <th width="80">삭제</th>}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{dataList.list &&
|
|
dataList.list.map((report, index) => (
|
|
<Fragment key={index}>
|
|
<tr>
|
|
<td>
|
|
<CheckBox name={'select'} id={report.row_num} setData={e => handleSelectCheckBox(e)} />
|
|
</td>
|
|
<td>{report.row_num}</td>
|
|
<td>{convertKTC(report.create_time, false)}</td>
|
|
<td>{report.reporter_nickname}</td>
|
|
<td>{reportType.map(data => data.value === report.report_type && data.name)}</td>
|
|
<td>
|
|
<Button theme="line" text="상세보기" handleClick={e => handleDetail(e, report.pk, report.sk)} />
|
|
</td>
|
|
<td>{report.state === 'UNRESOLVED' ? <ListState>미해결</ListState> : '해결'}</td>
|
|
<td>
|
|
{report.resolution_time && convertKTC(report.resolution_time, false)}
|
|
</td>
|
|
<td>{report.manager_email}</td>
|
|
{deleteAuth && (
|
|
<td>
|
|
<Button theme="line" text="삭제" />
|
|
</td>
|
|
)}
|
|
</tr>
|
|
</Fragment>
|
|
))}
|
|
</tbody>
|
|
</TableStyle>
|
|
</TableWrapper>
|
|
|
|
<Pagination postsPerPage={pageSize} totalPosts={dataList && dataList.total_all} setCurrentPage={setCurrentPage} currentPage={currentPage} pageLimit={10} />
|
|
|
|
<ReportListDetailModal detailView={detailView} handleReply={handleReply} handleDetailView={handleDetailView} detailData={detailData} replyData={replyData} replyAuth={replyAuth} />
|
|
<ReportListAnswerModal answerView={answerView} setAnswerView={setAnswerView} detailData={detailData} replyData={replyData} pkId={pkId} skId={skId} />
|
|
{/* 선택 삭제 모달 */}
|
|
<Modal min="440px" $padding="40px" $bgcolor="transparent" $view={deleteModalClose}>
|
|
<BtnWrapper $justify="flex-end">
|
|
<ButtonClose onClick={handleDeleteModalClose} />
|
|
</BtnWrapper>
|
|
<ModalText $align="center">
|
|
선택된 우편을 삭제하시겠습니까?
|
|
<br />
|
|
삭제 시 설정 정보가 제거됩니다.
|
|
</ModalText>
|
|
<BtnWrapper $gap="10px">
|
|
<Button text="취소" theme="line" size="large" width="100%" handleClick={handleDeleteModalClose} />
|
|
<Button text="확인" theme="primary" type="submit" size="large" width="100%" handleClick={handleSelectedDelete} />
|
|
</BtnWrapper>
|
|
</Modal>
|
|
{/* 확인 모달 */}
|
|
<Modal min="440px" $padding="40px" $bgcolor="transparent" $view={confirmModalClose}>
|
|
<BtnWrapper $justify="flex-end">
|
|
<ButtonClose onClick={handleConfirmeModalClose} />
|
|
</BtnWrapper>
|
|
<ModalText $align="center">삭제가 완료되었습니다.</ModalText>
|
|
<BtnWrapper $gap="10px">
|
|
<Button text="확인" theme="primary" type="submit" size="large" width="100%" handleClick={handleConfirmeModalClose} />
|
|
</BtnWrapper>
|
|
</Modal>
|
|
</>
|
|
)}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default ReportList;
|
|
|
|
const ListState = styled.span`
|
|
color: #d60000;
|
|
`;
|