import * as React from 'npm:react@18.3.1' import { Body, Button, Container, Head, Heading, Html, Preview, Section, Text } from 'npm:@react-email/components@0.0.22' import type { TemplateEntry } from './registry.ts' const SITE_NAME = 'Avria Community Management' interface Props { memberName?: string associationName?: string vendorName?: string invoiceNumber?: string amount?: string billDate?: string dueDate?: string description?: string approveLink?: string denyLink?: string reviewLink?: string } const BillApprovalVoteInviteEmail = ({ memberName, associationName, vendorName, invoiceNumber, amount, billDate, dueDate, description, approveLink, denyLink, reviewLink, }: Props) => ( Approve or deny: {vendorName || 'Bill'} {invoiceNumber || ''}
Bill approval requested Hello {memberName || 'Board Member'}, A bill{associationName ? ` for ${associationName}` : ''} requires your approval.
Vendor {vendorName || 'โ€”'} {invoiceNumber && ( <> Invoice # {invoiceNumber} )} Amount {amount || 'โ€”'} {(billDate || dueDate) && ( <> {billDate ? 'Bill date' : ''}{billDate && dueDate ? ' ยท Due date' : (dueDate ? 'Due date' : '')} {billDate || ''}{billDate && dueDate ? ' ยท ' : ''}{dueDate || ''} )} {description && ( <> Description {description} )}
{approveLink && } {denyLink && }
{reviewLink && ( Prefer to review the full bill first? Open it here. )} ๐Ÿ”’ These approve / deny links are tied uniquely to your board seat. Please do not share or forward them. If you weren't expecting this email, please contact your association manager. โ€” {SITE_NAME} ) export const template = { component: BillApprovalVoteInviteEmail, subject: (d: Record) => `Approve or deny: ${d.vendorName || 'Bill'}${d.invoiceNumber ? ` ${d.invoiceNumber}` : ''}`, displayName: 'Bill approval vote invite', previewData: { memberName: 'John Director', associationName: 'Sunset Hills HOA', vendorName: 'Acme Plumbing', invoiceNumber: 'INV-1042', amount: '$1,250.00', billDate: '2026-05-01', dueDate: '2026-05-31', description: 'Quarterly pump-station maintenance', approveLink: 'https://avria.cloud/bill-approve/xxx?token=yyy&action=approve', denyLink: 'https://avria.cloud/bill-approve/xxx?token=yyy&action=deny', reviewLink: 'https://avria.cloud/bill-approve/xxx?token=yyy', }, } satisfies TemplateEntry const main = { backgroundColor: '#ffffff', fontFamily: 'Inter, Arial, sans-serif' } const container = { maxWidth: '600px', margin: '0 auto', padding: '28px 24px' } const brandBar = { height: '5px', backgroundColor: '#2563eb', borderRadius: '6px', marginBottom: '24px' } const h1 = { color: '#111827', fontSize: '24px', lineHeight: '32px', margin: '0 0 14px', fontWeight: '700' } const text = { color: '#374151', fontSize: '15px', lineHeight: '24px', margin: '0 0 14px' } const panel = { backgroundColor: '#f8fafc', border: '1px solid #e5e7eb', borderRadius: '8px', padding: '16px', margin: '14px 0 22px' } const label = { color: '#6b7280', fontSize: '11px', textTransform: 'uppercase' as const, letterSpacing: '0.04em', margin: '8px 0 2px' } const value = { color: '#111827', fontSize: '15px', lineHeight: '22px', fontWeight: '600', margin: '0' } const meta = { color: '#374151', fontSize: '14px', lineHeight: '22px', margin: '0', whiteSpace: 'pre-wrap' as const } const buttonRow = { margin: '0 0 18px' } const approveButton = { backgroundColor: '#16a34a', color: '#ffffff', borderRadius: '6px', fontSize: '14px', fontWeight: '600', textDecoration: 'none', padding: '12px 18px', marginRight: '10px' } const denyButton = { backgroundColor: '#dc2626', color: '#ffffff', borderRadius: '6px', fontSize: '14px', fontWeight: '600', textDecoration: 'none', padding: '12px 18px' } const smallText = { color: '#6b7280', fontSize: '13px', lineHeight: '20px', margin: '0 0 10px' } const link = { color: '#2563eb', textDecoration: 'underline' } const footer = { color: '#6b7280', fontSize: '12px', lineHeight: '18px', margin: '28px 0 0' }