import { Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, ConfirmDialog, Input, } from '@plunk/ui'; import type {Template} from '@plunk/db'; import {DashboardLayout} from '../../components/DashboardLayout'; import {network} from '../../lib/network'; import {formatRelativeTime} from '../../lib/dateUtils'; import {Calendar, Copy, Edit, FileText, Plus, Search, Trash2} from 'lucide-react'; import {NextSeo} from 'next-seo'; import Link from 'next/link'; import {useState} from 'react'; import {toast} from 'sonner'; import useSWR from 'swr'; import dayjs from 'dayjs'; interface PaginatedTemplates { templates: Template[]; total: number; page: number; pageSize: number; totalPages: number; } export default function TemplatesPage() { const [page, setPage] = useState(1); const [search, setSearch] = useState(''); const [searchInput, setSearchInput] = useState(''); const [typeFilter, setTypeFilter] = useState<'ALL' | 'TRANSACTIONAL' | 'MARKETING'>('ALL'); const [showDeleteDialog, setShowDeleteDialog] = useState(false); const [templateToDelete, setTemplateToDelete] = useState(null); const {data, mutate, isLoading} = useSWR( `/templates?page=${page}&pageSize=20${search ? `&search=${search}` : ''}${typeFilter !== 'ALL' ? `&type=${typeFilter}` : ''}`, {revalidateOnFocus: false}, ); const handleSearch = (e: React.FormEvent) => { e.preventDefault(); setSearch(searchInput); setPage(1); }; const handleDelete = async () => { if (!templateToDelete) return; try { await network.fetch('DELETE', `/templates/${templateToDelete}`); toast.success('Template deleted successfully'); void mutate(); } catch (error) { toast.error(error instanceof Error ? error.message : 'Failed to delete template'); } finally { setTemplateToDelete(null); } }; const handleDuplicate = async (templateId: string) => { try { await network.fetch('POST', `/templates/${templateId}/duplicate`); toast.success('Template duplicated successfully'); void mutate(); } catch (error) { toast.error(error instanceof Error ? error.message : 'Failed to duplicate template'); } }; return ( <>
{/* Header */}

Email Templates

Create and manage reusable email templates for your campaigns and workflows.{' '} {data?.total ? `${data.total} total templates` : ''}

{/* Search & Filters */}
setSearchInput(e.target.value)} className="pl-10" />
{search && ( )}
{/* Type Filter */}
{/* Templates Grid */}
{isLoading ? (

Loading templates...

) : data?.templates.length === 0 ? (

No templates found

{search ? 'Try adjusting your search terms' : 'Get started by creating your first template'}

{!search && ( )}
) : ( <> {data?.templates.map(template => (
{template.name} {template.type.toLowerCase()}
{template.description && ( {template.description} )}

Subject

{template.subject}

From

{template.from}

Created {formatRelativeTime(template.createdAt)}
{dayjs(template.createdAt).format('DD MMMM YYYY, hh:mm')}
• Updated {formatRelativeTime(template.updatedAt)}
{dayjs(template.updatedAt).format('DD MMMM YYYY, hh:mm')}
{template.replyTo && (
Reply to: {template.replyTo}
)}
))} {/* Pagination */} {data && data.totalPages > 1 && (

Showing {(page - 1) * data.pageSize + 1} to {Math.min(page * data.pageSize, data.total)} of{' '} {data.total} templates

Page {page} of {data.totalPages}
)} )}
); }