mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
195 lines
6.5 KiB
TypeScript
195 lines
6.5 KiB
TypeScript
import { DataTable } from '@/components/admin/DataTable.tsx';
|
|
import { Badge, Button } from '@/components/ui';
|
|
import { useAnnouncements, useDeleteAnnouncement } from '@/hooks/api/useAdminAPI.ts';
|
|
import { useTranslation } from '@/hooks/useI18n.tsx';
|
|
import type { Announcement } from '@/services/admin-api.ts';
|
|
import { Edit, Plus, Trash2 } from 'lucide-react';
|
|
import { useState } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
|
const AnnouncementsPage = () => {
|
|
const { t } = useTranslation();
|
|
const navigate = useNavigate();
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
const pageSize = 25;
|
|
const [isActiveFilter, setIsActiveFilter] = useState<boolean | undefined>();
|
|
|
|
const { data, isLoading } = useAnnouncements({ isActive: isActiveFilter });
|
|
const { mutate: deleteAnnouncement } = useDeleteAnnouncement();
|
|
|
|
const handleDelete = (announcement: Announcement) => {
|
|
if (
|
|
window.confirm(
|
|
t('adminPage.content.announcements.confirmDelete', { title: announcement.title }) ||
|
|
`Delete "${announcement.title}"?`
|
|
)
|
|
) {
|
|
deleteAnnouncement(announcement.id, {
|
|
onSuccess: () => {
|
|
// Query will refetch automatically
|
|
},
|
|
});
|
|
}
|
|
};
|
|
|
|
const getPriorityBadge = (priority: string) => {
|
|
switch (priority) {
|
|
case 'urgent':
|
|
return (
|
|
<Badge variant="destructive">
|
|
{t('adminPage.content.announcements.urgent') || 'Urgent'}
|
|
</Badge>
|
|
);
|
|
case 'high':
|
|
return (
|
|
<Badge variant="default">{t('adminPage.content.announcements.high') || 'High'}</Badge>
|
|
);
|
|
case 'normal':
|
|
return (
|
|
<Badge variant="secondary">
|
|
{t('adminPage.content.announcements.normal') || 'Normal'}
|
|
</Badge>
|
|
);
|
|
case 'low':
|
|
return <Badge variant="outline">{t('adminPage.content.announcements.low') || 'Low'}</Badge>;
|
|
default:
|
|
return <Badge variant="secondary">{priority}</Badge>;
|
|
}
|
|
};
|
|
|
|
const columns = [
|
|
{
|
|
key: 'title',
|
|
header: t('adminPage.content.announcements.table.title') || 'Title',
|
|
render: (announcement: Announcement) => (
|
|
<span className="font-medium">{announcement.title}</span>
|
|
),
|
|
},
|
|
{
|
|
key: 'priority',
|
|
header: t('adminPage.content.announcements.table.priority') || 'Priority',
|
|
render: (announcement: Announcement) => getPriorityBadge(announcement.priority),
|
|
},
|
|
{
|
|
key: 'displayType',
|
|
header: t('adminPage.content.announcements.table.displayType') || 'Display Type',
|
|
render: (announcement: Announcement) => (
|
|
<Badge variant="outline">{announcement.displayType}</Badge>
|
|
),
|
|
},
|
|
{
|
|
key: 'isActive',
|
|
header: t('adminPage.content.announcements.table.status') || 'Status',
|
|
render: (announcement: Announcement) => (
|
|
<Badge variant={announcement.isActive ? 'success' : 'secondary'}>
|
|
{announcement.isActive
|
|
? t('adminPage.content.announcements.active') || 'Active'
|
|
: t('adminPage.content.announcements.inactive') || 'Inactive'}
|
|
</Badge>
|
|
),
|
|
},
|
|
{
|
|
key: 'views',
|
|
header: t('adminPage.content.announcements.table.views') || 'Views',
|
|
render: (announcement: Announcement) => (
|
|
<span className="text-sm text-muted-foreground">{announcement.views || 0}</span>
|
|
),
|
|
},
|
|
];
|
|
|
|
const actions = [
|
|
{
|
|
label: t('adminPage.content.announcements.edit') || 'Edit',
|
|
icon: <Edit className="h-4 w-4" />,
|
|
onClick: (announcement: Announcement) =>
|
|
navigate(`/admin/content/announcements/${announcement.id}/edit`),
|
|
},
|
|
{
|
|
label: t('adminPage.content.announcements.delete') || 'Delete',
|
|
icon: <Trash2 className="h-4 w-4" />,
|
|
variant: 'destructive' as const,
|
|
onClick: (announcement: Announcement) => handleDelete(announcement),
|
|
},
|
|
];
|
|
|
|
const announcements = data?.announcements || [];
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h1 className="text-2xl font-bold">
|
|
{t('adminPage.content.announcements.title') || 'Announcements'}
|
|
</h1>
|
|
<p className="text-muted-foreground">
|
|
{t('adminPage.content.announcements.description') ||
|
|
'Manage system announcements and notifications'}
|
|
</p>
|
|
</div>
|
|
<Button onClick={() => navigate('/admin/content/announcements/new')}>
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
{t('adminPage.content.announcements.newAnnouncement') || 'New Announcement'}
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Filters */}
|
|
<div className="flex gap-2">
|
|
<Button
|
|
variant={isActiveFilter === undefined ? 'default' : 'outline'}
|
|
onClick={() => setIsActiveFilter(undefined)}
|
|
>
|
|
{t('adminPage.content.announcements.all') || 'All'}
|
|
</Button>
|
|
<Button
|
|
variant={isActiveFilter === true ? 'default' : 'outline'}
|
|
onClick={() => setIsActiveFilter(true)}
|
|
>
|
|
{t('adminPage.content.announcements.active') || 'Active'}
|
|
</Button>
|
|
<Button
|
|
variant={isActiveFilter === false ? 'default' : 'outline'}
|
|
onClick={() => setIsActiveFilter(false)}
|
|
>
|
|
{t('adminPage.content.announcements.inactive') || 'Inactive'}
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Table */}
|
|
<DataTable
|
|
columns={columns}
|
|
data={announcements}
|
|
getRowId={(announcement) => announcement.id}
|
|
isLoading={isLoading}
|
|
actions={actions}
|
|
pagination={
|
|
announcements.length > 0
|
|
? {
|
|
currentPage,
|
|
totalPages: Math.ceil(announcements.length / pageSize),
|
|
pageSize,
|
|
totalItems: announcements.length,
|
|
onPageChange: setCurrentPage,
|
|
}
|
|
: undefined
|
|
}
|
|
emptyMessage={
|
|
t('adminPage.content.announcements.noAnnouncements') || 'No announcements found'
|
|
}
|
|
emptyDescription={
|
|
t('adminPage.content.announcements.createFirst') ||
|
|
'Create your first announcement to get started'
|
|
}
|
|
emptyAction={
|
|
<Button onClick={() => navigate('/admin/content/announcements/new')}>
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
{t('adminPage.content.announcements.newAnnouncement') || 'New Announcement'}
|
|
</Button>
|
|
}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default AnnouncementsPage;
|