From a709144685f37a81d6ef3d1bd2b557e610ce76e4 Mon Sep 17 00:00:00 2001 From: lorentz Date: Thu, 7 May 2026 08:23:24 -0400 Subject: [PATCH] feat(07.1-05): user-tz on engagement overview + profile pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - app/engagement/page.tsx: useUserTimezone in EngagementPage; thread tz into 7 toLocale* callsites (lines 844, 1012, 1108, 1227, 1255 — last two have 2 calls per line for date+time). - app/engagement/profile/page.tsx: useUserTimezone in EngagementProfilePage; add tz prop to ActivityHeatmap; convert module-scope monthLabel(m) to monthLabel(m, tz); update 2 callsites of monthLabel. Migrates 9 of 81 audit leak callsites. --- app/engagement/page.tsx | 12 +++++++----- app/engagement/profile/page.tsx | 16 +++++++++------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/app/engagement/page.tsx b/app/engagement/page.tsx index b91469c..86af00a 100644 --- a/app/engagement/page.tsx +++ b/app/engagement/page.tsx @@ -44,6 +44,7 @@ import { Legend, CartesianGrid, } from 'recharts'; +import { useUserTimezone } from '@/lib/hooks/use-user-timezone'; interface SummaryData { totalStaff: number; @@ -460,6 +461,7 @@ function SummaryCard({ } export default function EngagementPage() { + const tz = useUserTimezone(); const [period, setPeriod] = useState<'D7' | 'D30' | 'D90'>('D7'); const [activeTab, setActiveTab] = useState<'overview' | 'by-employee'>('by-employee'); const [summary, setSummary] = useState(null); @@ -839,7 +841,7 @@ export default function EngagementPage() { {user.lastActivity - ? new Date(user.lastActivity).toLocaleDateString() + ? new Date(user.lastActivity).toLocaleDateString(undefined, { timeZone: tz }) : '—'} @@ -1007,7 +1009,7 @@ export default function EngagementPage() { }] : []), ]} /> {snap?.last_activity_date && ( -

Last activity: {new Date(snap.last_activity_date).toLocaleDateString()}

+

Last activity: {new Date(snap.last_activity_date).toLocaleDateString(undefined, { timeZone: tz })}

)} @@ -1103,7 +1105,7 @@ export default function EngagementPage() { )} - {d.toLocaleDateString()} {d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} + {d.toLocaleDateString(undefined, { timeZone: tz })} {d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', timeZone: tz })} {mtg.durationMinutes != null && ` · ${mtg.durationMinutes}m`} @@ -1222,7 +1224,7 @@ export default function EngagementPage() {
{formatDuration(call.durationSeconds)} - {new Date(call.startTime).toLocaleDateString()} + {new Date(call.startTime).toLocaleDateString(undefined, { timeZone: tz })}
))} @@ -1250,7 +1252,7 @@ export default function EngagementPage() { )} - {d.toLocaleDateString()} {d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} + {d.toLocaleDateString(undefined, { timeZone: tz })} {d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', timeZone: tz })} {mtg.durationMinutes != null && ` · ${mtg.durationMinutes}m`} diff --git a/app/engagement/profile/page.tsx b/app/engagement/profile/page.tsx index e45925a..de86376 100644 --- a/app/engagement/profile/page.tsx +++ b/app/engagement/profile/page.tsx @@ -25,6 +25,7 @@ import { PolarRadiusAxis, Radar, } from 'recharts'; +import { useUserTimezone } from '@/lib/hooks/use-user-timezone'; import { Users, RefreshCw } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { @@ -100,7 +101,7 @@ function hoursLevel(h: number): number { return 4; } -function ActivityHeatmap({ daily }: { daily: DayData[] }) { +function ActivityHeatmap({ daily, tz }: { daily: DayData[]; tz: string }) { const dailyMap: Record = {}; for (const d of daily) dailyMap[d.date] = d; @@ -138,7 +139,7 @@ function ActivityHeatmap({ daily }: { daily: DayData[] }) { if (m !== lastMonth) { monthLabels.push({ weekIndex: wi, - label: d.toLocaleDateString('en-US', { month: 'short' }), + label: d.toLocaleDateString('en-US', { month: 'short', timeZone: tz }), }); lastMonth = m; } @@ -260,8 +261,8 @@ function buildRadarData(monthly: MonthData[]) { ]; } -function monthLabel(m: string) { - return new Date(m + '-02').toLocaleDateString('en-US', { month: 'short', year: 'numeric' }); +function monthLabel(m: string, tz: string) { + return new Date(m + '-02').toLocaleDateString('en-US', { month: 'short', year: 'numeric', timeZone: tz }); } interface BackfillStatus { @@ -276,6 +277,7 @@ interface BackfillStatus { } export default function EngagementProfilePage() { + const tz = useUserTimezone(); const [users, setUsers] = useState([]); const [usersLoading, setUsersLoading] = useState(true); const [selectedUserId, setSelectedUserId] = useState(''); @@ -496,7 +498,7 @@ export default function EngagementProfilePage() { {peakMonth ? peakMonth.hoursWorked.toFixed(0) + 'h' : '—'}

- {peakMonth ? monthLabel(peakMonth.month) : ''} + {peakMonth ? monthLabel(peakMonth.month, tz) : ''}

@@ -510,7 +512,7 @@ export default function EngagementProfilePage() { {history.daily.length > 0 ? ( - + ) : (

No time entry data available @@ -612,7 +614,7 @@ export default function EngagementProfilePage() { key={m.month} className={cn(isEmpty && 'opacity-40')} > - {monthLabel(m.month)} + {monthLabel(m.month, tz)} {m.hoursWorked > 0 ? m.hoursWorked.toFixed(1) : '—'}