226 lines
6.9 KiB
TypeScript

'use client';
import { ProTable, ProTableActions } from '@/components/pro-table';
import { Badge } from '@workspace/ui/components/badge';
import { Button } from '@workspace/ui/components/button';
import { ScrollArea } from '@workspace/ui/components/scroll-area';
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetTrigger,
} from '@workspace/ui/components/sheet';
import { Icon } from '@workspace/ui/custom-components/icon';
import { formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl';
import { useRef, useState } from 'react';
interface EmailLog extends Record<string, unknown> {
id: number;
subject: string;
recipient_email: string;
status: 'pending' | 'sent' | 'failed';
sent_at?: string;
error_message?: string;
broadcast_id: number;
}
interface GetEmailLogsParams extends Record<string, unknown> {
page: number;
size: number;
status?: string;
search?: string;
}
// Mock API function
const getEmailLogs = async (params: GetEmailLogsParams) => {
// Simulate API call
await new Promise((resolve) => setTimeout(resolve, 500));
// Mock data
const mockData: EmailLog[] = [
{
id: 1,
subject: 'New Feature Release Notification',
recipient_email: 'user1@example.com',
status: 'sent',
sent_at: '2024-01-15T10:05:00Z',
broadcast_id: 1,
},
{
id: 2,
subject: 'New Feature Release Notification',
recipient_email: 'user2@example.com',
status: 'sent',
sent_at: '2024-01-15T10:05:30Z',
broadcast_id: 1,
},
{
id: 3,
subject: 'New Feature Release Notification',
recipient_email: 'user3@example.com',
status: 'failed',
error_message: 'Invalid email address',
broadcast_id: 1,
},
{
id: 4,
subject: 'System Maintenance Notice',
recipient_email: 'user4@example.com',
status: 'sent',
sent_at: '2024-01-14T15:35:00Z',
broadcast_id: 2,
},
{
id: 5,
subject: 'System Maintenance Notice',
recipient_email: 'user5@example.com',
status: 'pending',
broadcast_id: 2,
},
];
return {
data: {
data: {
list: mockData,
total: mockData.length,
},
},
};
};
export default function BroadcastLogsTable() {
const t = useTranslations('marketing');
const [open, setOpen] = useState(false);
const ref = useRef<ProTableActions>(null);
const getStatusBadge = (status: string) => {
const statusMap = {
pending: { variant: 'secondary' as const, label: 'Pending' },
sent: { variant: 'default' as const, label: 'Sent' },
failed: { variant: 'destructive' as const, label: 'Failed' },
};
const statusInfo = statusMap[status as keyof typeof statusMap] || statusMap.pending;
return <Badge variant={statusInfo.variant}>{statusInfo.label}</Badge>;
};
return (
<Sheet open={open} onOpenChange={setOpen}>
<SheetTrigger asChild>
<div className='flex cursor-pointer items-center justify-between transition-colors'>
<div className='flex items-center gap-3'>
<div className='bg-primary/10 flex h-10 w-10 items-center justify-center rounded-lg'>
<Icon icon='mdi:email-newsletter' className='text-primary h-5 w-5' />
</div>
<div className='flex-1'>
<p className='font-medium'>Broadcast Logs</p>
<p className='text-muted-foreground text-sm'>
View email send records and detailed status
</p>
</div>
</div>
<Icon icon='mdi:chevron-right' className='size-6' />
</div>
</SheetTrigger>
<SheetContent className='w-[90vw] max-w-full md:max-w-screen-xl'>
<SheetHeader>
<SheetTitle>Broadcast Logs</SheetTitle>
</SheetHeader>
<ScrollArea className='-mx-6 h-[calc(100dvh-48px-36px-env(safe-area-inset-top))] px-6'>
<div className='pt-4'>
<ProTable<EmailLog, GetEmailLogsParams>
action={ref}
columns={[
{
accessorKey: 'id',
header: 'ID',
size: 80,
},
{
accessorKey: 'subject',
header: 'Subject',
size: 200,
cell: ({ row }) => (
<div
className='max-w-[200px] truncate'
title={row.getValue('subject') as string}
>
{row.getValue('subject') as string}
</div>
),
},
{
accessorKey: 'recipient_email',
header: 'Recipient Email',
size: 200,
},
{
accessorKey: 'status',
header: 'Status',
size: 100,
cell: ({ row }) => getStatusBadge(row.getValue('status') as string),
},
{
accessorKey: 'sent_at',
header: 'Sent At',
size: 150,
cell: ({ row }) => {
const sentAt = row.getValue('sent_at') as string;
return sentAt ? formatDate(new Date(sentAt)) : '--';
},
},
{
accessorKey: 'error_message',
header: 'Error Message',
size: 200,
cell: ({ row }) => {
const error = row.getValue('error_message') as string;
return error ? <span className='text-sm text-red-600'>{error}</span> : '--';
},
},
]}
request={async (pagination, filter) => {
const { data } = await getEmailLogs({
...pagination,
...filter,
});
return {
list: data.data?.list || [],
total: data.data?.total || 0,
};
}}
params={[
{
key: 'status',
placeholder: 'Status',
options: [
{ label: 'Pending', value: 'pending' },
{ label: 'Sent', value: 'sent' },
{ label: 'Failed', value: 'failed' },
],
},
{
key: 'search',
placeholder: 'Recipient Email',
},
]}
actions={{
render: (row) => {
return [
<Button key='view' variant='outline' size='sm'>
View
</Button>,
];
},
}}
/>
</div>
</ScrollArea>
</SheetContent>
</Sheet>
);
}