504 lines
15 KiB
TypeScript
504 lines
15 KiB
TypeScript
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="You’ve 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="We’ve 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="We’ve 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">
|
||
We’re 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>
|
||
)
|
||
}
|
||
|