admin-panel-front/src/pages/Billboards/Billboards.tsx
2026-08-09 09:33:04 +03:30

160 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;