Yaltopia-Home-Email/src/email/templates.tsx
2026-03-12 00:42:12 +03:00

504 lines
15 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { BaseEmailShell } from './BaseEmailShell'
export interface CommonEmailProps {
recipientName: string
}
export interface InvitationEmailProps extends CommonEmailProps {
teamName: string
role: string
inviteUrl: string
}
export function InvitationTeamMemberEmail(props: InvitationEmailProps) {
const { recipientName, teamName, role, inviteUrl } = props
return (
<BaseEmailShell
category="invitation"
eyebrow="Team invitation"
title="Youve been invited to Yaltopia Home"
>
<p className="greeting">Hi {recipientName},</p>
<p className="body-text">
You have been invited to join the <strong>{teamName}</strong> workspace
on Yaltopia Home as <strong>{role}</strong>.
</p>
<div className="button-row">
<a href={inviteUrl} className="primary-button">
Accept invitation
</a>
</div>
<p className="body-text-muted">
If the button does not work, paste this link into your browser:{' '}
<span className="small-text">{inviteUrl}</span>
</p>
</BaseEmailShell>
)
}
export interface PropertyFoundEmailProps extends CommonEmailProps {
propertyTitle: string
address: string
price: string
link: string
}
export function PropertyFoundRequestEmail(props: PropertyFoundEmailProps) {
const { recipientName, propertyTitle, address, price, link } = props
return (
<BaseEmailShell
category="request"
eyebrow="Match found"
title="Weve found a property that fits your request"
>
<p className="greeting">Hi {recipientName},</p>
<p className="body-text">
Good news a new property matches your saved search on Yaltopia Home.
</p>
<div className="info-card">
<div className="info-title">Property match</div>
<div className="info-row">
<span className="info-label">Title</span>
<span className="info-value">{propertyTitle}</span>
</div>
<div className="info-row">
<span className="info-label">Address</span>
<span className="info-value">{address}</span>
</div>
<div className="info-row">
<span className="info-label">Guide price</span>
<span className="info-value">{price}</span>
</div>
</div>
<div className="button-row">
<a href={link} className="primary-button">
View property
</a>
</div>
</BaseEmailShell>
)
}
export interface PropertyRequestReceivedProps extends CommonEmailProps {
budget: string
locations: string
bedrooms: string
ref: string
}
export function PropertyRequestReceivedEmail(
props: PropertyRequestReceivedProps,
) {
const { recipientName, budget, locations, bedrooms, ref } = props
return (
<BaseEmailShell
category="request"
eyebrow="Request received"
title="Weve received your property request"
>
<p className="greeting">Hi {recipientName},</p>
<p className="body-text">
Thanks for sharing what you are looking for. Our team will start
searching and notify you as soon as we have a match.
</p>
<div className="info-card">
<div className="info-title">Request summary</div>
<div className="info-row">
<span className="info-label">Budget</span>
<span className="info-value">{budget}</span>
</div>
<div className="info-row">
<span className="info-label">Locations</span>
<span className="info-value">{locations}</span>
</div>
<div className="info-row">
<span className="info-label">Bedrooms</span>
<span className="info-value">{bedrooms}</span>
</div>
<div className="info-row">
<span className="info-label">Reference</span>
<span className="info-value">{ref}</span>
</div>
</div>
<p className="body-text-muted">
You can update your request at any time from your dashboard.
</p>
</BaseEmailShell>
)
}
export interface BankDetails {
bank: string
accountName: string
accountNumber: string
reference: string
}
export interface BillReminderEmailProps extends CommonEmailProps {
period: string
rent?: string
water?: string
security?: string
electric?: string
total: string
dueDate: string
paymentUrl?: string
bankDetails?: BankDetails[]
paymentOptionsUrl?: string
}
export function BillPaymentReminderEmail(props: BillReminderEmailProps) {
const {
recipientName,
period,
rent,
water,
security,
electric,
total,
dueDate,
paymentUrl,
bankDetails,
paymentOptionsUrl,
} = props
return (
<BaseEmailShell
category="billing"
eyebrow="Payment reminder"
title={`Upcoming bill for ${period}`}
>
<p className="greeting">Hi {recipientName},</p>
<p className="body-text">
This is a reminder that your housing charges for <strong>{period}</strong>{' '}
are due on <strong>{dueDate}</strong>.
</p>
<div className="info-card">
<div className="info-title">Charges</div>
{rent && (
<div className="info-row">
<span className="info-label">Rent</span>
<span className="info-value">{rent}</span>
</div>
)}
{water && (
<div className="info-row">
<span className="info-label">Water</span>
<span className="info-value">{water}</span>
</div>
)}
{security && (
<div className="info-row">
<span className="info-label">Security</span>
<span className="info-value">{security}</span>
</div>
)}
{electric && (
<div className="info-row">
<span className="info-label">Electric</span>
<span className="info-value">{electric}</span>
</div>
)}
<div className="info-row">
<span className="info-label">Total due</span>
<span className="info-value">{total}</span>
</div>
</div>
<div className="button-row">
{paymentUrl ? (
<a href={paymentUrl} className="primary-button">
Pay online
</a>
) : (
<span className="small-text">
Pay using the bank details below and include your reference.
</span>
)}
</div>
{bankDetails && bankDetails.length > 0 && (
<div className="bank-details">
{bankDetails.map((bank) => (
<div key={`${bank.bank}-${bank.accountNumber}`} className="bank-row">
<div>{bank.bank}</div>
<div>{bank.accountName}</div>
<div>Acct: {bank.accountNumber}</div>
<div>Ref: {bank.reference}</div>
</div>
))}
</div>
)}
{paymentOptionsUrl && (
<p className="body-text-muted">
View all approved payment options at{' '}
<a href={paymentOptionsUrl} className="secondary-link">
yaltopia.home/payments
</a>
.
</p>
)}
<p className="body-text-muted">
If you have already paid, you can ignore this reminder.
</p>
</BaseEmailShell>
)
}
export interface SingleChargeReminderProps extends CommonEmailProps {
period: string
amount: string
dueDate: string
paymentUrl?: string
bankDetails?: BankDetails[]
paymentOptionsUrl?: string
}
export function RentBillReminderEmail(props: SingleChargeReminderProps) {
const { amount, ...rest } = props
return (
<BillPaymentReminderEmail
{...rest}
rent={amount}
total={amount}
/>
)
}
export function WaterBillReminderEmail(props: SingleChargeReminderProps) {
const { amount, ...rest } = props
return (
<BillPaymentReminderEmail
{...rest}
water={amount}
total={amount}
/>
)
}
export function SecurityBillReminderEmail(props: SingleChargeReminderProps) {
const { amount, ...rest } = props
return (
<BillPaymentReminderEmail
{...rest}
security={amount}
total={amount}
/>
)
}
export function ElectricBillReminderEmail(props: SingleChargeReminderProps) {
const { amount, ...rest } = props
return (
<BillPaymentReminderEmail
{...rest}
electric={amount}
total={amount}
/>
)
}
export interface NewsletterEmailProps extends CommonEmailProps {
title: string
intro: string
articles: { title: string; description: string }[]
}
export function NewsletterEmail(props: NewsletterEmailProps) {
const { recipientName, title, intro, articles } = props
return (
<BaseEmailShell
category="newsletter"
eyebrow="Monthly digest"
title={title}
>
<p className="greeting">Hi {recipientName},</p>
<p className="body-text">{intro}</p>
{articles.map((article) => (
<div key={article.title} className="info-card">
<div className="info-title">{article.title}</div>
<p className="body-text">{article.description}</p>
</div>
))}
<p className="body-text-muted">
You are receiving this email because you are subscribed to the Yaltopia
Home newsletter. You can manage your email preferences from your
account.
</p>
</BaseEmailShell>
)
}
export interface OwnerSuccessEmailProps extends CommonEmailProps {
propertyTitle: string
address: string
outcome: 'sold' | 'rented'
price: string
}
export function OwnerSuccessEmail(props: OwnerSuccessEmailProps) {
const { recipientName, propertyTitle, address, outcome, price } = props
return (
<BaseEmailShell
category="success"
eyebrow="Congratulations"
title={
outcome === 'sold'
? 'Your property has been sold'
: 'Your property has been rented'
}
>
<p className="greeting">Dear {recipientName},</p>
<p className="body-text">
Were excited to share that your property on Yaltopia Home has{' '}
<strong>{outcome}</strong>.
</p>
<div className="info-card">
<div className="info-title">Property</div>
<div className="info-row">
<span className="info-label">Title</span>
<span className="info-value">{propertyTitle}</span>
</div>
<div className="info-row">
<span className="info-label">Address</span>
<span className="info-value">{address}</span>
</div>
<div className="info-row">
<span className="info-label">
{outcome === 'sold' ? 'Sale price' : 'Rental amount'}
</span>
<span className="info-value">{price}</span>
</div>
</div>
<p className="body-text-muted">
Our team will follow up shortly with settlement details and next
steps.
</p>
</BaseEmailShell>
)
}
export interface ListingApprovedEmailProps extends CommonEmailProps {
propertyTitle: string
address: string
publicUrl: string
}
export function ListingApprovedEmail(props: ListingApprovedEmailProps) {
const { recipientName, propertyTitle, address, publicUrl } = props
return (
<BaseEmailShell
category="listing"
eyebrow="Listing approved"
title="Your listing is now live"
>
<p className="greeting">Hi {recipientName},</p>
<p className="body-text">
Your property listing has been reviewed and approved. It is now visible
to the public on Yaltopia Home.
</p>
<div className="info-card">
<div className="info-title">Listing details</div>
<div className="info-row">
<span className="info-label">Title</span>
<span className="info-value">{propertyTitle}</span>
</div>
<div className="info-row">
<span className="info-label">Address</span>
<span className="info-value">{address}</span>
</div>
</div>
<div className="button-row">
<a href={publicUrl} className="primary-button">
View public listing
</a>
</div>
</BaseEmailShell>
)
}
export interface AppointmentBookedEmailProps extends CommonEmailProps {
date: string
time: string
timezone: string
location: string
agentName: string
calendarUrl: string
}
export function AppointmentBookedEmail(props: AppointmentBookedEmailProps) {
const { recipientName, date, time, timezone, location, agentName, calendarUrl } =
props
return (
<BaseEmailShell
category="appointment"
eyebrow="Appointment booked"
title="Your viewing appointment is confirmed"
>
<p className="greeting">Hi {recipientName},</p>
<p className="body-text">
Your appointment has been scheduled. Here are the details:
</p>
<div className="info-card">
<div className="info-title">Appointment</div>
<div className="info-row">
<span className="info-label">Date</span>
<span className="info-value">{date}</span>
</div>
<div className="info-row">
<span className="info-label">Time</span>
<span className="info-value">
{time} ({timezone})
</span>
</div>
<div className="info-row">
<span className="info-label">Location</span>
<span className="info-value">{location}</span>
</div>
<div className="info-row">
<span className="info-label">Agent</span>
<span className="info-value">{agentName}</span>
</div>
</div>
<div className="button-row">
<a href={calendarUrl} className="primary-button">
Add to calendar
</a>
</div>
<p className="body-text-muted">
Please arrive a few minutes early. You can reschedule or cancel from
your dashboard.
</p>
</BaseEmailShell>
)
}
export interface PasswordResetEmailProps extends CommonEmailProps {
resetUrl: string
expiresInMinutes: number
}
export function PasswordResetEmail(props: PasswordResetEmailProps) {
const { recipientName, resetUrl, expiresInMinutes } = props
return (
<BaseEmailShell
category="security"
eyebrow="Security"
title="Reset your Yaltopia Home password"
>
<p className="greeting">Hi {recipientName},</p>
<p className="body-text">
We received a request to reset the password for your Yaltopia Home
account. Click the button below to choose a new password.
</p>
<div className="button-row">
<a href={resetUrl} className="primary-button">
Reset password
</a>
</div>
<p className="body-text-muted">
This link will expire in {expiresInMinutes} minutes. If you did not
request a password reset, you can safely ignore this email.
</p>
</BaseEmailShell>
)
}