diff --git a/synculous-client/src/app/dashboard/routines/page.tsx b/synculous-client/src/app/dashboard/routines/page.tsx index 568fcff..6d85c1a 100644 --- a/synculous-client/src/app/dashboard/routines/page.tsx +++ b/synculous-client/src/app/dashboard/routines/page.tsx @@ -112,6 +112,14 @@ function timeToMinutes(t: string): number { return h * 60 + m; } +function timeToMinutesLocal(t: string, offsetMinutes: number): number { + const mins = timeToMinutes(t); + const localMins = mins - offsetMinutes; + if (localMins < 0) return localMins + 24 * 60; + if (localMins >= 24 * 60) return localMins - 24 * 60; + return localMins; +} + function minutesToTop(minutes: number, startHour: number): number { return ((minutes - startHour * 60) / 60) * HOUR_HEIGHT; } @@ -127,6 +135,17 @@ function formatTime(t: string): string { return `${dh}:${String(m).padStart(2, '0')} ${period}`; } +function formatTimeLocal(t: string, offsetMinutes: number): string { + const mins = timeToMinutes(t) - offsetMinutes; + let h = Math.floor(mins / 60) % 24; + if (h < 0) h += 24; + const m = mins % 60; + if (m < 0) m += 60; + const period = h >= 12 ? 'PM' : 'AM'; + const dh = h > 12 ? h - 12 : h === 0 ? 12 : h; + return `${dh}:${String(m).padStart(2, '0')} ${period}`; +} + function addMinutesToTime(t: string, mins: number): string { const [h, m] = t.split(':').map(Number); const total = h * 60 + m + mins; @@ -210,6 +229,7 @@ export default function RoutinesPage() { const [todayMeds, setTodayMeds] = useState([]); const [isLoading, setIsLoading] = useState(true); const [selectedDate, setSelectedDate] = useState(() => new Date()); + const [timezoneOffset, setTimezoneOffset] = useState(0); const [nowMinutes, setNowMinutes] = useState(() => { const n = new Date(); return n.getHours() * 60 + n.getMinutes(); @@ -230,7 +250,7 @@ export default function RoutinesPage() { const scheduledForDay = allSchedules .filter((s) => s.days.includes(dayKey)) - .sort((a, b) => timeToMinutes(a.time) - timeToMinutes(b.time)); + .sort((a, b) => timeToMinutesLocal(a.time, timezoneOffset) - timeToMinutesLocal(b.time, timezoneOffset)); const scheduledRoutineIds = new Set(allSchedules.map((s) => s.routine_id)); const unscheduledRoutines = allRoutines.filter( @@ -298,8 +318,8 @@ export default function RoutinesPage() { // ── Dynamic time window ─────────────────────────────────────── const allEventMins = [ nowMinutes, - ...scheduledForDay.map((e) => timeToMinutes(e.time)), - ...groupedMedEntries.map((e) => timeToMinutes(e.time)), + ...scheduledForDay.map((e) => timeToMinutesLocal(e.time, timezoneOffset)), + ...groupedMedEntries.map((e) => timeToMinutesLocal(e.time, timezoneOffset)), ]; const displayStartHour = allEventMins.length > 0 @@ -420,11 +440,13 @@ export default function RoutinesPage() { api.routines.list(), api.routines.listAllSchedules(), api.medications.getToday().catch(() => []), + api.preferences.get().catch(() => ({ timezone_offset: 0 })), ]) - .then(([routines, schedules, meds]) => { + .then(([routines, schedules, meds, prefs]) => { setAllRoutines(routines); setAllSchedules(schedules); setTodayMeds(meds); + setTimezoneOffset((prefs as any).timezone_offset || 0); }) .catch(() => {}) .finally(() => setIsLoading(false)); @@ -618,7 +640,7 @@ export default function RoutinesPage() { {/* Routine cards */} {scheduledForDay.map((entry) => { - const startMin = timeToMinutes(entry.time); + const startMin = timeToMinutesLocal(entry.time, timezoneOffset); const topPx = minutesToTop(startMin, displayStartHour); const heightPx = durationToHeight(entry.total_duration_minutes); const endMin = startMin + entry.total_duration_minutes; @@ -656,16 +678,17 @@ export default function RoutinesPage() { {entry.routine_name}

- {formatTime(entry.time)} + {formatTimeLocal(entry.time, timezoneOffset)} {entry.total_duration_minutes > 0 && ( <> {' '} -{' '} - {formatTime( + {formatTimeLocal( addMinutesToTime( entry.time, entry.total_duration_minutes - ) + ), + timezoneOffset )} )} diff --git a/synculous-client/src/lib/api.ts b/synculous-client/src/lib/api.ts index a75cac3..6cfc496 100644 --- a/synculous-client/src/lib/api.ts +++ b/synculous-client/src/lib/api.ts @@ -627,6 +627,7 @@ export const api = { haptic_enabled: boolean; show_launch_screen: boolean; celebration_style: string; + timezone_offset: number; }>('/api/preferences', { method: 'GET' }); },