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' && ( +
+ + setReportForm({ ...reportForm, sendDay: parseInt(v) })} + options={Array.from({ length: 28 }, (_, i) => { + const d = i + 1 + const suffix = d === 1 ? 'st' : d === 2 ? 'nd' : d === 3 ? 'rd' : 'th' + return { value: String(d), label: `${d}${suffix}` } + })} + variant="input" + fullWidth + align="left" + /> +
+ )} + +
+ + setReportForm({ ...reportForm, timezone: v })} + options={TIMEZONES.map((tz) => ({ value: tz, label: tz }))} + variant="input" + fullWidth + align="left" + /> +
+