mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
149 lines
5.0 KiB
TypeScript
149 lines
5.0 KiB
TypeScript
import { DataTable } from '@/components/admin/DataTable.tsx';
|
|
import { Badge, Button } from '@/components/ui';
|
|
import { usePages, useDeletePage } from '@/hooks/api/useAdminAPI.ts';
|
|
import { useTranslation } from '@/hooks/useI18n.tsx';
|
|
import type { StaticPage } from '@/services/admin-api.ts';
|
|
import { Edit, Plus, Trash2, Eye } from 'lucide-react';
|
|
import { useState } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
|
const ContentPagesPage = () => {
|
|
const { t } = useTranslation();
|
|
const navigate = useNavigate();
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
const pageSize = 25;
|
|
|
|
const { data, isLoading } = usePages();
|
|
const { mutate: deletePage } = useDeletePage();
|
|
|
|
const handleDelete = (page: StaticPage) => {
|
|
if (window.confirm(t('adminPage.content.pages.confirmDelete', { title: page.title }) || `Delete "${page.title}"?`)) {
|
|
deletePage(page.id, {
|
|
onSuccess: () => {
|
|
// Query will refetch automatically
|
|
},
|
|
});
|
|
}
|
|
};
|
|
|
|
const getStatusBadge = (status: string) => {
|
|
switch (status) {
|
|
case 'published':
|
|
return <Badge variant="success">{t('adminPage.content.pages.published') || 'Published'}</Badge>;
|
|
case 'draft':
|
|
return <Badge variant="secondary">{t('adminPage.content.pages.draft') || 'Draft'}</Badge>;
|
|
case 'archived':
|
|
return <Badge variant="outline">{t('adminPage.content.pages.archived') || 'Archived'}</Badge>;
|
|
default:
|
|
return <Badge variant="secondary">{status}</Badge>;
|
|
}
|
|
};
|
|
|
|
const columns = [
|
|
{
|
|
key: 'slug',
|
|
header: t('adminPage.content.pages.table.slug') || 'Slug',
|
|
render: (page: StaticPage) => <span className="font-mono text-sm">{page.slug}</span>,
|
|
},
|
|
{
|
|
key: 'title',
|
|
header: t('adminPage.content.pages.table.title') || 'Title',
|
|
render: (page: StaticPage) => <span className="font-medium">{page.title}</span>,
|
|
},
|
|
{
|
|
key: 'status',
|
|
header: t('adminPage.content.pages.table.status') || 'Status',
|
|
render: (page: StaticPage) => getStatusBadge(page.status),
|
|
},
|
|
{
|
|
key: 'visibility',
|
|
header: t('adminPage.content.pages.table.visibility') || 'Visibility',
|
|
render: (page: StaticPage) => (
|
|
<Badge variant="outline">{page.visibility || 'public'}</Badge>
|
|
),
|
|
},
|
|
{
|
|
key: 'updatedAt',
|
|
header: t('adminPage.content.pages.table.updated') || 'Updated',
|
|
render: (page: StaticPage) => {
|
|
try {
|
|
const date = new Date(page.updatedAt);
|
|
return <span className="text-sm text-muted-foreground">{date.toLocaleDateString()}</span>;
|
|
} catch {
|
|
return <span className="text-sm text-muted-foreground">—</span>;
|
|
}
|
|
},
|
|
},
|
|
];
|
|
|
|
const actions = [
|
|
{
|
|
label: t('adminPage.content.pages.edit') || 'Edit',
|
|
icon: <Edit className="h-4 w-4" />,
|
|
onClick: (page: StaticPage) => navigate(`/admin/content/pages/${page.id}/edit`),
|
|
},
|
|
{
|
|
label: t('adminPage.content.pages.view') || 'View',
|
|
icon: <Eye className="h-4 w-4" />,
|
|
onClick: (page: StaticPage) => window.open(`/${page.slug}`, '_blank'),
|
|
},
|
|
{
|
|
label: t('adminPage.content.pages.delete') || 'Delete',
|
|
icon: <Trash2 className="h-4 w-4" />,
|
|
variant: 'destructive' as const,
|
|
onClick: (page: StaticPage) => handleDelete(page),
|
|
},
|
|
];
|
|
|
|
const pages = data?.pages || [];
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h1 className="text-2xl font-bold">{t('adminPage.content.pages.title') || 'Static Pages'}</h1>
|
|
<p className="text-muted-foreground">
|
|
{t('adminPage.content.pages.description') || 'Manage static content pages like About, Contact, Privacy Policy, etc.'}
|
|
</p>
|
|
</div>
|
|
<Button onClick={() => navigate('/admin/content/pages/new')}>
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
{t('adminPage.content.pages.newPage') || 'New Page'}
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Table */}
|
|
<DataTable
|
|
columns={columns}
|
|
data={pages}
|
|
getRowId={(page) => page.id}
|
|
isLoading={isLoading}
|
|
actions={actions}
|
|
pagination={
|
|
pages.length > 0
|
|
? {
|
|
currentPage,
|
|
totalPages: Math.ceil(pages.length / pageSize),
|
|
pageSize,
|
|
totalItems: pages.length,
|
|
onPageChange: setCurrentPage,
|
|
}
|
|
: undefined
|
|
}
|
|
emptyMessage={t('adminPage.content.pages.noPages') || 'No pages found'}
|
|
emptyDescription={t('adminPage.content.pages.createFirst') || 'Create your first static page to get started'}
|
|
emptyAction={
|
|
<Button onClick={() => navigate('/admin/content/pages/new')}>
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
{t('adminPage.content.pages.newPage') || 'New Page'}
|
|
</Button>
|
|
}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ContentPagesPage;
|
|
|