From 27a9836d5adcd2e309d2fb312b6c89e6f84e011a Mon Sep 17 00:00:00 2001
From: Usman Baig
Date: Thu, 12 Mar 2026 15:17:46 +0100
Subject: [PATCH] feat: add time-of-day controls to scheduled reports UI
Add send hour, day of week/month selectors to report schedule modal.
Schedule cards now show descriptive delivery times like
"Every Monday at 9:00 AM (UTC)". Timezone picker moved into modal.
---
app/sites/[id]/settings/page.tsx | 100 ++++++++++++++++++++++++++++++-
lib/api/report-schedules.ts | 7 +++
2 files changed, 106 insertions(+), 1 deletion(-)
diff --git a/app/sites/[id]/settings/page.tsx b/app/sites/[id]/settings/page.tsx
index e21ca00..0a32b42 100644
--- a/app/sites/[id]/settings/page.tsx
+++ b/app/sites/[id]/settings/page.tsx
@@ -107,6 +107,8 @@ export default function SiteSettingsPage() {
frequency: 'weekly' as string,
reportType: 'summary' as string,
timezone: '',
+ sendHour: 9,
+ sendDay: 1,
})
useEffect(() => {
@@ -235,6 +237,8 @@ export default function SiteSettingsPage() {
frequency: 'weekly',
reportType: 'summary',
timezone: site?.timezone || '',
+ sendHour: 9,
+ sendDay: 1,
})
}
@@ -248,6 +252,8 @@ export default function SiteSettingsPage() {
frequency: schedule.frequency,
reportType: schedule.report_type,
timezone: schedule.timezone || site?.timezone || '',
+ sendHour: schedule.send_hour ?? 9,
+ sendDay: schedule.send_day ?? (schedule.frequency === 'monthly' ? 1 : 0),
})
setReportModalOpen(true)
}
@@ -277,6 +283,8 @@ export default function SiteSettingsPage() {
frequency: reportForm.frequency,
timezone: reportForm.timezone || undefined,
report_type: reportForm.reportType,
+ send_hour: reportForm.sendHour,
+ ...(reportForm.frequency !== 'daily' ? { send_day: reportForm.sendDay } : {}),
}
setReportSaving(true)
@@ -349,6 +357,34 @@ export default function SiteSettingsPage() {
}
}
+ const WEEKDAY_NAMES = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
+
+ const formatHour = (hour: number) => {
+ if (hour === 0) return '12:00 AM'
+ if (hour === 12) return '12:00 PM'
+ return hour < 12 ? `${hour}:00 AM` : `${hour - 12}:00 PM`
+ }
+
+ const getScheduleDescription = (schedule: ReportSchedule) => {
+ const hour = formatHour(schedule.send_hour ?? 9)
+ const tz = schedule.timezone || 'UTC'
+ switch (schedule.frequency) {
+ case 'daily':
+ return `Every day at ${hour} (${tz})`
+ case 'weekly': {
+ const day = WEEKDAY_NAMES[schedule.send_day ?? 0] || 'Monday'
+ return `Every ${day} at ${hour} (${tz})`
+ }
+ case 'monthly': {
+ const d = schedule.send_day ?? 1
+ const suffix = d === 1 ? 'st' : d === 2 ? 'nd' : d === 3 ? 'rd' : 'th'
+ return `${d}${suffix} of each month at ${hour} (${tz})`
+ }
+ default:
+ return schedule.frequency
+ }
+ }
+
const getReportTypeLabel = (type: string) => {
switch (type) {
case 'summary': return 'Summary'
@@ -1367,7 +1403,10 @@ export default function SiteSettingsPage() {
? (schedule.channel_config as EmailConfig).recipients.join(', ')
: (schedule.channel_config as WebhookConfig).url}
-
+
+ {getScheduleDescription(schedule)}
+
+
Last sent: {schedule.last_sent_at
? new Date(schedule.last_sent_at).toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric', hour: '2-digit', minute: '2-digit' })
@@ -1556,6 +1595,65 @@ export default function SiteSettingsPage() {
/>
+ {reportForm.frequency === 'weekly' && (
+
+
+
+ )}
+
+ {reportForm.frequency === 'monthly' && (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+