2022-09-27 17:59:05 +08:00
|
|
|
import React, { FC } from 'react';
|
2022-10-09 18:20:19 +08:00
|
|
|
import { Button, Form, Table, Stack } from 'react-bootstrap';
|
2022-09-27 17:59:05 +08:00
|
|
|
import { useSearchParams } from 'react-router-dom';
|
|
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
|
|
|
|
import {
|
|
|
|
FormatTime,
|
|
|
|
BaseUserCard,
|
|
|
|
Empty,
|
|
|
|
Pagination,
|
2022-10-09 18:20:19 +08:00
|
|
|
QueryGroup,
|
2022-09-27 17:59:05 +08:00
|
|
|
} from '@answer/components';
|
|
|
|
import { useReportModal } from '@answer/hooks';
|
2022-09-29 10:46:30 +08:00
|
|
|
import * as Type from '@answer/common/interface';
|
2022-09-28 18:25:10 +08:00
|
|
|
import { useFlagSearch } from '@answer/api';
|
2022-09-27 17:59:05 +08:00
|
|
|
|
|
|
|
import '../index.scss';
|
|
|
|
|
|
|
|
const flagFilterKeys: Type.FlagStatus[] = ['pending', 'completed'];
|
|
|
|
const flagTypeKeys: Type.FlagType[] = ['all', 'question', 'answer', 'comment'];
|
|
|
|
|
|
|
|
const Flags: FC = () => {
|
|
|
|
const { t } = useTranslation('translation', { keyPrefix: 'admin.flags' });
|
|
|
|
const [urlSearchParams, setUrlSearchParams] = useSearchParams();
|
|
|
|
const curFilter = urlSearchParams.get('status') || flagFilterKeys[0];
|
|
|
|
const curType = urlSearchParams.get('type') || flagTypeKeys[0];
|
2022-09-29 15:09:47 +08:00
|
|
|
const PAGE_SIZE = 20;
|
2022-09-27 17:59:05 +08:00
|
|
|
const curPage = Number(urlSearchParams.get('page')) || 1;
|
2022-09-28 10:06:18 +08:00
|
|
|
const {
|
|
|
|
data: listData,
|
|
|
|
isLoading,
|
|
|
|
mutate: refreshList,
|
|
|
|
} = useFlagSearch({
|
2022-09-29 15:09:47 +08:00
|
|
|
page_size: PAGE_SIZE,
|
2022-09-27 17:59:05 +08:00
|
|
|
page: curPage,
|
|
|
|
status: curFilter as Type.FlagStatus,
|
|
|
|
object_type: curType as Type.FlagType,
|
|
|
|
});
|
2022-09-28 10:06:18 +08:00
|
|
|
const reportModal = useReportModal(refreshList);
|
2022-09-27 17:59:05 +08:00
|
|
|
|
|
|
|
const count = listData?.count || 0;
|
2022-10-09 18:20:19 +08:00
|
|
|
|
2022-09-27 17:59:05 +08:00
|
|
|
const onTypeChange = (evt) => {
|
|
|
|
urlSearchParams.set('type', evt.target.value);
|
|
|
|
setUrlSearchParams(urlSearchParams);
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleReview = ({ id, object_type }) => {
|
|
|
|
reportModal.onShow({
|
|
|
|
id,
|
|
|
|
type: object_type,
|
|
|
|
isBackend: true,
|
|
|
|
action: 'review',
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<h3 className="mb-4">{t('title')}</h3>
|
|
|
|
<div className="d-flex justify-content-between align-items-center mb-3">
|
2022-10-09 18:20:19 +08:00
|
|
|
<QueryGroup
|
|
|
|
data={flagFilterKeys}
|
|
|
|
currentSort={curFilter}
|
|
|
|
sortKey="status"
|
|
|
|
i18nkeyPrefix="admin.flags"
|
|
|
|
/>
|
|
|
|
|
2022-09-27 17:59:05 +08:00
|
|
|
<Form.Select
|
|
|
|
value={curType}
|
|
|
|
onChange={onTypeChange}
|
|
|
|
size="sm"
|
|
|
|
style={{ width: '12.25rem' }}>
|
|
|
|
{flagTypeKeys.map((li) => {
|
|
|
|
return (
|
|
|
|
<option value={li} key={li}>
|
|
|
|
{li}
|
|
|
|
</option>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</Form.Select>
|
|
|
|
</div>
|
|
|
|
<Table>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>{t('flagged')}</th>
|
|
|
|
<th style={{ width: '20%' }}>{t('created')}</th>
|
2022-09-29 10:44:27 +08:00
|
|
|
{curFilter !== 'completed' ? (
|
|
|
|
<th style={{ width: '20%' }}>{t('action')}</th>
|
|
|
|
) : null}
|
2022-09-27 17:59:05 +08:00
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody className="align-middle">
|
|
|
|
{listData?.list?.map((li) => {
|
|
|
|
return (
|
|
|
|
<tr key={li.id}>
|
|
|
|
<td>
|
|
|
|
<Stack>
|
|
|
|
<small className="text-secondary">
|
|
|
|
Flagged {li.object_type}
|
|
|
|
</small>
|
|
|
|
<BaseUserCard data={li.reported_user} className="mt-2" />
|
|
|
|
<a
|
|
|
|
href={`/questions/${li.question_id}`}
|
|
|
|
target="_blank"
|
|
|
|
className="text-wrap text-break mt-2"
|
|
|
|
rel="noreferrer">
|
|
|
|
{li.title}
|
|
|
|
</a>
|
|
|
|
<small className="text-break text-wrap word">
|
|
|
|
{li.excerpt}
|
|
|
|
</small>
|
|
|
|
</Stack>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<Stack>
|
|
|
|
<FormatTime
|
|
|
|
time={li.created_at}
|
|
|
|
className="fs-14 text-secondary"
|
|
|
|
/>
|
|
|
|
<BaseUserCard data={li.report_user} className="mt-2 mb-2" />
|
2022-10-14 17:12:34 +08:00
|
|
|
{li.flagged_reason ? (
|
|
|
|
<small>{li.flagged_content}</small>
|
2022-09-27 17:59:05 +08:00
|
|
|
) : (
|
|
|
|
<small>
|
|
|
|
{li.reason?.name}
|
|
|
|
<br />
|
|
|
|
<span className="text-secondary">{li.content}</span>
|
|
|
|
</small>
|
|
|
|
)}
|
|
|
|
</Stack>
|
|
|
|
</td>
|
2022-09-29 10:44:27 +08:00
|
|
|
{curFilter !== 'completed' ? (
|
|
|
|
<td>
|
|
|
|
<Button variant="link" onClick={() => handleReview(li)}>
|
|
|
|
{t('review')}
|
|
|
|
</Button>
|
|
|
|
</td>
|
|
|
|
) : null}
|
2022-09-27 17:59:05 +08:00
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</tbody>
|
|
|
|
</Table>
|
|
|
|
{Number(count) <= 0 && !isLoading && <Empty />}
|
|
|
|
<div className="mt-4 mb-2 d-flex justify-content-center">
|
|
|
|
<Pagination
|
|
|
|
currentPage={curPage}
|
|
|
|
totalSize={count}
|
2022-09-29 15:09:47 +08:00
|
|
|
pageSize={PAGE_SIZE}
|
2022-09-27 17:59:05 +08:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default Flags;
|