Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
94 lines
3.1 KiB
TypeScript
94 lines
3.1 KiB
TypeScript
'use client'
|
||
|
||
import type { PaginationListColumnType } from '@/types'
|
||
import PaginatedList from '@/components/PaginatedList'
|
||
import PageNavbar from '@/components/layouts/PageNavbar'
|
||
import Button from '@/components/formElements/Button'
|
||
import { APP_ROUTES } from '@/constants/routes'
|
||
import { API_ROUTES } from '@/services/config'
|
||
import {
|
||
SUPPORT_ADMIN_STATUS_LABELS,
|
||
SUPPORT_CATEGORY_LABELS,
|
||
SUPPORT_PRIORITY_LABELS,
|
||
type SupportTicket,
|
||
} from '@/services/supportTickets'
|
||
import { formatIranianMobile, formatPersianDate } from '@/lib/formatters'
|
||
import { coerceToString } from '@/helpers'
|
||
|
||
const columns: PaginationListColumnType[] = [
|
||
{ field: 'subject', label: 'موضوع', filterable: false, sortable: false },
|
||
{ field: 'user', label: 'کاربر', filterable: false, sortable: false },
|
||
{
|
||
field: 'category',
|
||
label: 'دستهبندی',
|
||
filterable: true,
|
||
sortable: false,
|
||
type: 'select',
|
||
filterItems: Object.entries(SUPPORT_CATEGORY_LABELS).map(([code, name]) => ({ code, name })),
|
||
},
|
||
{
|
||
field: 'priority',
|
||
label: 'اولویت',
|
||
filterable: true,
|
||
sortable: false,
|
||
type: 'select',
|
||
filterItems: Object.entries(SUPPORT_PRIORITY_LABELS).map(([code, name]) => ({ code, name })),
|
||
},
|
||
{
|
||
field: 'status',
|
||
label: 'وضعیت',
|
||
filterable: true,
|
||
sortable: false,
|
||
type: 'select',
|
||
filterItems: Object.entries(SUPPORT_ADMIN_STATUS_LABELS).map(([code, name]) => ({ code, name })),
|
||
},
|
||
{ field: 'lastMessageAt', label: 'آخرین پیام', filterable: false, sortable: true },
|
||
{ field: 'actions', label: 'عملیات' },
|
||
]
|
||
|
||
const AdminSupportTicketsPage = () => (
|
||
<section className="h-full w-full text-right">
|
||
<PageNavbar pageTitle="تیکتهای پشتیبانی" />
|
||
<div className="admin-page-container">
|
||
<PaginatedList
|
||
columns={columns}
|
||
url={API_ROUTES.SUPPORT_TICKETS.ADMIN_LIST}
|
||
>
|
||
{{
|
||
subject: (_row, value) => coerceToString(value),
|
||
user: (row) => {
|
||
const ticket = row as unknown as SupportTicket
|
||
|
||
return (
|
||
<div>
|
||
<p>{ticket.user.displayName || 'کاربر'}</p>
|
||
<p
|
||
className="text-xs text-text-muted"
|
||
dir="ltr"
|
||
>
|
||
{formatIranianMobile(ticket.user.mobile)}
|
||
</p>
|
||
</div>
|
||
)
|
||
},
|
||
category: (_row, value) => SUPPORT_CATEGORY_LABELS[coerceToString(value)] ?? coerceToString(value),
|
||
priority: (_row, value) => SUPPORT_PRIORITY_LABELS[coerceToString(value)] ?? coerceToString(value),
|
||
status: (_row, value) => SUPPORT_ADMIN_STATUS_LABELS[coerceToString(value)] ?? coerceToString(value),
|
||
lastMessageAt: (_row, value) => formatPersianDate(value),
|
||
actions: (row) => (
|
||
<Button
|
||
size="sm"
|
||
to={APP_ROUTES.SUPPORT_TICKET_DETAIL((row as unknown as SupportTicket).id)}
|
||
variant="light"
|
||
>
|
||
مشاهده و پاسخ
|
||
</Button>
|
||
),
|
||
}}
|
||
</PaginatedList>
|
||
</div>
|
||
</section>
|
||
)
|
||
|
||
export default AdminSupportTicketsPage
|