160 lines
4.7 KiB
TypeScript
160 lines
4.7 KiB
TypeScript
import { App, Button, Table, Tag, Tooltip, Typography } from 'antd';
|
||
import type { TableColumnsType } from 'antd';
|
||
import { useEffect, useState } from 'react';
|
||
import { Link, useNavigate } from 'react-router-dom';
|
||
import { colors } from '@/design/tokens/colors';
|
||
import { formatDateTime } from '@/utils/formatDate';
|
||
import { adsApi } from '@/services/adsApi';
|
||
import EmptyValue from '@/components/ui/EmptyValue';
|
||
import { AD_STATE_LABELS, AD_TYPE_LABELS, truncateText, truncateUuid } from '@/pages/Billboards/adLabels';
|
||
import type { Ad } from '@/types/ad';
|
||
|
||
const { Text } = Typography;
|
||
|
||
const PAGE_SIZE = 10;
|
||
|
||
interface FetchResult {
|
||
page: number;
|
||
status: 'success' | 'error';
|
||
ads: Ad[];
|
||
total: number;
|
||
}
|
||
|
||
const Billboards = () => {
|
||
const { message } = App.useApp();
|
||
const navigate = useNavigate();
|
||
const [page, setPage] = useState(1);
|
||
const [result, setResult] = useState<FetchResult | null>(null);
|
||
|
||
useEffect(() => {
|
||
adsApi
|
||
.getAdminAds({ limit: PAGE_SIZE, offset: (page - 1) * PAGE_SIZE })
|
||
.then(({ results, count }) => {
|
||
setResult({ page, status: 'success', ads: results, total: count });
|
||
})
|
||
.catch(() => {
|
||
setResult({ page, status: 'error', ads: [], total: 0 });
|
||
message.error('دریافت اطلاعات بیلبوردها با خطا مواجه شد');
|
||
});
|
||
}, [page, message]);
|
||
|
||
const isCurrent = result?.page === page;
|
||
const isLoading = !isCurrent;
|
||
const ads = isCurrent ? result.ads : [];
|
||
const total = isCurrent ? result.total : 0;
|
||
|
||
const columns: TableColumnsType<Ad> = [
|
||
{
|
||
title: 'شناسه',
|
||
dataIndex: 'uuid',
|
||
key: 'uuid',
|
||
render: (value: string) => (
|
||
<Tooltip title={value}>
|
||
<Text copyable={{ text: value }} style={{ direction: 'ltr', fontSize: 12 }}>
|
||
{truncateUuid(value)}
|
||
</Text>
|
||
</Tooltip>
|
||
),
|
||
},
|
||
{
|
||
title: 'کاربر (ثبتکننده)',
|
||
dataIndex: 'user',
|
||
key: 'user',
|
||
render: (value: string) => (
|
||
<Tooltip title={value}>
|
||
<Link to={`/profile?uuid=${value}`} style={{ direction: 'ltr', fontSize: 12 }}>
|
||
{truncateUuid(value)}
|
||
</Link>
|
||
</Tooltip>
|
||
),
|
||
},
|
||
{
|
||
title: 'عنوان',
|
||
dataIndex: 'title',
|
||
key: 'title',
|
||
ellipsis: true,
|
||
render: (value: string | null) => value ?? <EmptyValue />,
|
||
},
|
||
{
|
||
title: 'نوع',
|
||
dataIndex: 'type',
|
||
key: 'type',
|
||
render: (value: number) => <Tag color={colors.primary}>{AD_TYPE_LABELS[value] ?? value}</Tag>,
|
||
},
|
||
{
|
||
title: 'توضیحات',
|
||
dataIndex: 'description',
|
||
key: 'description',
|
||
render: (value: string | null) =>
|
||
value ? (
|
||
<Tooltip title={value}>
|
||
<span>{truncateText(value)}</span>
|
||
</Tooltip>
|
||
) : (
|
||
<EmptyValue />
|
||
),
|
||
},
|
||
{
|
||
title: 'برچسبها',
|
||
dataIndex: 'tags',
|
||
key: 'tags',
|
||
render: (tags: string[]) =>
|
||
tags?.length ? (
|
||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
|
||
{tags.map((tag) => (
|
||
<Tag key={tag}>{tag}</Tag>
|
||
))}
|
||
</div>
|
||
) : (
|
||
<EmptyValue />
|
||
),
|
||
},
|
||
{ title: 'تاریخ ایجاد', dataIndex: 'created_at', key: 'created_at', render: formatDateTime },
|
||
{ title: 'تاریخ آخرین ویرایش', dataIndex: 'updated_at', key: 'updated_at', render: formatDateTime },
|
||
{
|
||
title: 'وضعیت',
|
||
dataIndex: 'state',
|
||
key: 'state',
|
||
render: (value: number) => {
|
||
const state = AD_STATE_LABELS[value];
|
||
return <Tag color={state?.color ?? 'default'}>{state?.label ?? value}</Tag>;
|
||
},
|
||
},
|
||
{ title: 'تعداد نظرات', dataIndex: 'comments_count', key: 'comments_count' },
|
||
{ title: 'تعداد لایکها', dataIndex: 'likes_count', key: 'likes_count' },
|
||
{
|
||
title: 'فعال/غیرفعال',
|
||
dataIndex: 'is_active',
|
||
key: 'is_active',
|
||
render: (value: boolean) => <Tag color={value ? 'success' : 'default'}>{value ? 'فعال' : 'غیرفعال'}</Tag>,
|
||
},
|
||
{
|
||
title: 'جزئیات',
|
||
key: 'details',
|
||
render: (_, record) => (
|
||
<Button size="small" onClick={() => navigate(`/billboards/${record.uuid}`)}>
|
||
مشاهده جزئیات
|
||
</Button>
|
||
),
|
||
},
|
||
];
|
||
|
||
return (
|
||
<Table
|
||
rowKey="uuid"
|
||
columns={columns}
|
||
dataSource={ads}
|
||
loading={isLoading}
|
||
scroll={{ x: 'max-content' }}
|
||
pagination={{
|
||
current: page,
|
||
pageSize: PAGE_SIZE,
|
||
total,
|
||
showSizeChanger: false,
|
||
onChange: setPage,
|
||
}}
|
||
/>
|
||
);
|
||
};
|
||
|
||
export default Billboards;
|