'use client' import { useState } from 'react' import Link from 'next/link' import { trpc } from '@/lib/trpc/client' import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { Badge } from '@/components/ui/badge' import { Skeleton } from '@/components/ui/skeleton' import { Switch } from '@/components/ui/switch' import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from '@/components/ui/dialog' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog' import { ArrowLeft, Plus, Pencil, Trash2, Loader2, LayoutTemplate, Eye, Variable, } from 'lucide-react' import { toast } from 'sonner' const AVAILABLE_VARIABLES = [ { name: '{{projectName}}', desc: 'Project title' }, { name: '{{userName}}', desc: "Recipient's name" }, { name: '{{deadline}}', desc: 'Deadline date' }, { name: '{{roundName}}', desc: 'Round name' }, { name: '{{programName}}', desc: 'Program name' }, ] interface TemplateFormData { name: string category: string subject: string body: string variables: string[] isActive: boolean } const defaultForm: TemplateFormData = { name: '', category: '', subject: '', body: '', variables: [], isActive: true, } export default function MessageTemplatesPage() { const [dialogOpen, setDialogOpen] = useState(false) const [editingId, setEditingId] = useState(null) const [deleteId, setDeleteId] = useState(null) const [formData, setFormData] = useState(defaultForm) const [showPreview, setShowPreview] = useState(false) const utils = trpc.useUtils() const { data: templates, isLoading } = trpc.message.listTemplates.useQuery() const createMutation = trpc.message.createTemplate.useMutation({ onSuccess: () => { utils.message.listTemplates.invalidate() toast.success('Template created') closeDialog() }, onError: (e) => toast.error(e.message), }) const updateMutation = trpc.message.updateTemplate.useMutation({ onSuccess: () => { utils.message.listTemplates.invalidate() toast.success('Template updated') closeDialog() }, onError: (e) => toast.error(e.message), }) const deleteMutation = trpc.message.deleteTemplate.useMutation({ onSuccess: () => { utils.message.listTemplates.invalidate() toast.success('Template deleted') setDeleteId(null) }, onError: (e) => toast.error(e.message), }) const closeDialog = () => { setDialogOpen(false) setEditingId(null) setFormData(defaultForm) setShowPreview(false) } const openEdit = (template: Record) => { setEditingId(String(template.id)) setFormData({ name: String(template.name || ''), category: String(template.category || ''), subject: String(template.subject || ''), body: String(template.body || ''), variables: Array.isArray(template.variables) ? template.variables.map(String) : [], isActive: template.isActive !== false, }) setDialogOpen(true) } const insertVariable = (variable: string) => { setFormData((prev) => ({ ...prev, body: prev.body + variable, })) } const handleSubmit = () => { if (!formData.name.trim() || !formData.subject.trim()) { toast.error('Name and subject are required') return } const payload = { name: formData.name.trim(), category: formData.category.trim() || 'General', subject: formData.subject.trim(), body: formData.body.trim(), variables: formData.variables.length > 0 ? formData.variables : undefined, } if (editingId) { updateMutation.mutate({ id: editingId, ...payload, isActive: formData.isActive }) } else { createMutation.mutate(payload) } } const getPreviewText = (text: string): string => { return text .replace(/\{\{userName\}\}/g, 'John Doe') .replace(/\{\{projectName\}\}/g, 'Ocean Cleanup Initiative') .replace(/\{\{roundName\}\}/g, 'Round 1 - Semi-Finals') .replace(/\{\{programName\}\}/g, 'MOPC 2026') .replace(/\{\{deadline\}\}/g, 'March 15, 2026') } const isPending = createMutation.isPending || updateMutation.isPending return (
{/* Header */}

Message Templates

Create and manage reusable message templates

!open && closeDialog()}> {editingId ? 'Edit Template' : 'Create Template'} Define a reusable message template with variable placeholders.
setFormData({ ...formData, name: e.target.value })} />
setFormData({ ...formData, category: e.target.value })} />
setFormData({ ...formData, subject: e.target.value })} />
{showPreview ? (

Subject: {getPreviewText(formData.subject)}

{getPreviewText(formData.body) || 'No content yet'}
) : (