From e5e7550c8c893862041eadbfc0ae078904310e2d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=80=9Ckirukib=E2=80=9D?= <“kirubeljkl679@gmail.com”>
Date: Thu, 12 Mar 2026 00:42:12 +0300
Subject: [PATCH] feat: detailed bill reminders and sidebar polish
Made-with: Cursor
---
src/App.css | 32 +++++++++-
src/App.tsx | 20 +++++--
src/email/BaseEmailShell.tsx | 16 ++++-
src/email/email.css | 13 ++++
src/email/sampleData.ts | 112 ++++++++++++++++++++++++++++++++---
src/email/templates.tsx | 92 ++++++++++++++++++++++++----
6 files changed, 260 insertions(+), 25 deletions(-)
diff --git a/src/App.css b/src/App.css
index 5a1d0df..b7f4b1d 100644
--- a/src/App.css
+++ b/src/App.css
@@ -83,12 +83,26 @@
gap: 4px;
}
+.template-section {
+ padding-bottom: 4px;
+}
+
.template-section-label {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.12em;
color: #9ca3af;
- margin: 4px 0 6px;
+ margin: 4px 0 4px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.template-section-count {
+ font-size: 10px;
+ padding: 2px 6px;
+ border-radius: 999px;
+ border: 1px solid rgba(148, 163, 184, 0.7);
}
.template-item {
@@ -121,6 +135,22 @@
border: 1px solid rgba(148, 163, 184, 0.7);
}
+.template-main {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 2px;
+}
+
+.template-label {
+ font-weight: 500;
+}
+
+.template-description {
+ font-size: 11px;
+ color: #6b7280;
+}
+
.sidebar-footer {
margin-top: auto;
padding-top: 12px;
diff --git a/src/App.tsx b/src/App.tsx
index 46fe15e..108388e 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -61,8 +61,13 @@ function App() {
)
if (!sectionTemplates.length) return null
return (
-
-
{section}
+
+
+ {section}
+
+ {sectionTemplates.length}
+
+
{sectionTemplates.map((t) => (
))}
diff --git a/src/email/BaseEmailShell.tsx b/src/email/BaseEmailShell.tsx
index 0655e22..163dda4 100644
--- a/src/email/BaseEmailShell.tsx
+++ b/src/email/BaseEmailShell.tsx
@@ -60,11 +60,23 @@ export function BaseEmailShell({
Yaltopia Home
- Transactional email preview · Not an actual bill
+ Transactional email · Please do not reply to this address.
- Powered by
Yaltopia Home
+
+ Powered by Yaltopia Home
+
+
diff --git a/src/email/email.css b/src/email/email.css
index abb5872..12af9b6 100644
--- a/src/email/email.css
+++ b/src/email/email.css
@@ -206,6 +206,15 @@ body {
color: #9ca3af;
}
+.footer-approved {
+ margin-top: 4px;
+}
+
+.footer-link {
+ color: #e5e7eb;
+ text-decoration: underline;
+}
+
.bank-details {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
"Liberation Mono", "Courier New", monospace;
@@ -217,6 +226,10 @@ body {
margin-top: 10px;
}
+.bank-row + .bank-row {
+ margin-top: 8px;
+}
+
.pill {
display: inline-block;
padding: 3px 9px;
diff --git a/src/email/sampleData.ts b/src/email/sampleData.ts
index 70c508e..d40670d 100644
--- a/src/email/sampleData.ts
+++ b/src/email/sampleData.ts
@@ -1,6 +1,7 @@
import {
AppointmentBookedEmail,
BillPaymentReminderEmail,
+ ElectricBillReminderEmail,
InvitationTeamMemberEmail,
ListingApprovedEmail,
NewsletterEmail,
@@ -8,6 +9,9 @@ import {
PasswordResetEmail,
PropertyFoundRequestEmail,
PropertyRequestReceivedEmail,
+ RentBillReminderEmail,
+ SecurityBillReminderEmail,
+ WaterBillReminderEmail,
} from './templates'
export const templates = [
@@ -51,7 +55,7 @@ export const templates = [
},
{
id: 'bill-reminder',
- label: 'Bill payment reminder',
+ label: 'Bill summary (all charges)',
section: 'Billing',
component: BillPaymentReminderEmail,
props: {
@@ -64,12 +68,106 @@ export const templates = [
total: '$1,006.20',
dueDate: 'February 5, 2026',
paymentUrl: 'https://pay.yaltopia.home/invoice/02934392392',
- bankDetails: {
- bank: 'Yaltopia Bank',
- accountName: 'Yaltopia Home Estates',
- accountNumber: '0293439239',
- reference: 'RICKY-UNIT-12',
- },
+ bankDetails: [
+ {
+ bank: 'Yaltopia Bank',
+ accountName: 'Yaltopia Home Estates',
+ accountNumber: '0293439239',
+ reference: 'RICKY-UNIT-12',
+ },
+ {
+ bank: 'Metro Homes Bank',
+ accountName: 'Yaltopia Home Estates',
+ accountNumber: '0043920091',
+ reference: 'YH-RICKY-UNIT-12',
+ },
+ ],
+ paymentOptionsUrl: 'https://yaltopia.home/payments',
+ },
+ },
+ {
+ id: 'bill-rent',
+ label: 'Rent reminder only',
+ section: 'Billing',
+ component: RentBillReminderEmail,
+ props: {
+ recipientName: 'Ricky Ricardo',
+ period: 'February 2026',
+ amount: '$900.00',
+ dueDate: 'February 5, 2026',
+ paymentUrl: 'https://pay.yaltopia.home/invoice/RENT-02934392392',
+ bankDetails: [
+ {
+ bank: 'Yaltopia Bank',
+ accountName: 'Yaltopia Home Estates',
+ accountNumber: '0293439239',
+ reference: 'RENT-RICKY-UNIT-12',
+ },
+ ],
+ paymentOptionsUrl: 'https://yaltopia.home/payments',
+ },
+ },
+ {
+ id: 'bill-water',
+ label: 'Water bill reminder',
+ section: 'Billing',
+ component: WaterBillReminderEmail,
+ props: {
+ recipientName: 'Ricky Ricardo',
+ period: 'February 2026',
+ amount: '$24.60',
+ dueDate: 'February 5, 2026',
+ bankDetails: [
+ {
+ bank: 'City Water Bank',
+ accountName: 'Yaltopia Home Water',
+ accountNumber: '2024002460',
+ reference: 'WATER-RICKY-UNIT-12',
+ },
+ ],
+ paymentOptionsUrl: 'https://yaltopia.home/payments',
+ },
+ },
+ {
+ id: 'bill-security',
+ label: 'Security fee reminder',
+ section: 'Billing',
+ component: SecurityBillReminderEmail,
+ props: {
+ recipientName: 'Ricky Ricardo',
+ period: 'February 2026',
+ amount: '$35.40',
+ dueDate: 'February 5, 2026',
+ bankDetails: [
+ {
+ bank: 'Yaltopia Guard Bank',
+ accountName: 'Yaltopia Home Security',
+ accountNumber: '8835003540',
+ reference: 'SEC-RICKY-UNIT-12',
+ },
+ ],
+ paymentOptionsUrl: 'https://yaltopia.home/payments',
+ },
+ },
+ {
+ id: 'bill-electric',
+ label: 'Electric bill reminder',
+ section: 'Billing',
+ component: ElectricBillReminderEmail,
+ props: {
+ recipientName: 'Ricky Ricardo',
+ period: 'February 2026',
+ amount: '$46.20',
+ dueDate: 'February 5, 2026',
+ bankDetails: [
+ {
+ bank: 'Gridline Bank',
+ accountName: 'Yaltopia Home Electric',
+ accountNumber: '6646004620',
+ reference: 'ELEC-RICKY-UNIT-12',
+ },
+ ],
+ paymentOptionsUrl: 'https://yaltopia.home/payments',
},
},
{
diff --git a/src/email/templates.tsx b/src/email/templates.tsx
index 6a70b04..cb694ac 100644
--- a/src/email/templates.tsx
+++ b/src/email/templates.tsx
@@ -127,6 +127,13 @@ export function PropertyRequestReceivedEmail(
)
}
+export interface BankDetails {
+ bank: string
+ accountName: string
+ accountNumber: string
+ reference: string
+}
+
export interface BillReminderEmailProps extends CommonEmailProps {
period: string
rent?: string
@@ -136,12 +143,8 @@ export interface BillReminderEmailProps extends CommonEmailProps {
total: string
dueDate: string
paymentUrl?: string
- bankDetails?: {
- bank: string
- accountName: string
- accountNumber: string
- reference: string
- }
+ bankDetails?: BankDetails[]
+ paymentOptionsUrl?: string
}
export function BillPaymentReminderEmail(props: BillReminderEmailProps) {
@@ -156,6 +159,7 @@ export function BillPaymentReminderEmail(props: BillReminderEmailProps) {
dueDate,
paymentUrl,
bankDetails,
+ paymentOptionsUrl,
} = props
return (
)}
- {bankDetails && (
+ {bankDetails && bankDetails.length > 0 && (
-
Bank: {bankDetails.bank}
-
Account name: {bankDetails.accountName}
-
Account number: {bankDetails.accountNumber}
-
Reference: {bankDetails.reference}
+ {bankDetails.map((bank) => (
+
+
{bank.bank}
+
{bank.accountName}
+
Acct: {bank.accountNumber}
+
Ref: {bank.reference}
+
+ ))}
)}
+ {paymentOptionsUrl && (
+
+ View all approved payment options at{' '}
+
+ yaltopia.home/payments
+
+ .
+
+ )}
If you have already paid, you can ignore this reminder.
@@ -225,6 +242,59 @@ export function BillPaymentReminderEmail(props: BillReminderEmailProps) {
)
}
+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 (
+
+ )
+}
+
+export function WaterBillReminderEmail(props: SingleChargeReminderProps) {
+ const { amount, ...rest } = props
+ return (
+
+ )
+}
+
+export function SecurityBillReminderEmail(props: SingleChargeReminderProps) {
+ const { amount, ...rest } = props
+ return (
+
+ )
+}
+
+export function ElectricBillReminderEmail(props: SingleChargeReminderProps) {
+ const { amount, ...rest } = props
+ return (
+
+ )
+}
+
export interface NewsletterEmailProps extends CommonEmailProps {
title: string
intro: string