- Mark all 51 manifest checklist entries as [x] complete (50 migrated + 1 deferred-then-migrated via the audit's 50/51 path; 1 file rounds out the count via auvik-tab DEFER). - Wait — accurate: 50 files migrated, 1 file deferred (auvik-tab), 1 file deleted (.backup orphan). 80 of 81 audit leak callsites threaded with timeZone: tz; 1 deferred for layering boundary. - Write 07.1-05-SUMMARY.md documenting the 8 task commits, per-pattern callsite counts, deferred rationale, and post-migration grep residue. - Phase 7.1 SC#4 satisfied codebase-wide.
29 KiB
Phase 7.1 Plan 05 — Migration manifest
Source: .planning/phases/07.1-user-timezone-fix-inserted-urgent/07.1-04-AUDIT.md
Pre-migration leak count (per audit): 81 callsites across 39 files
Files to migrate
- app/engagement/profile/page.tsx
- app/engagement/page.tsx
- app/admin/sync/duo/page.tsx
- app/admin/sync/datto-rmm/page.tsx
- app/admin/sync/veeam/page.tsx
- app/admin/sync/itglue/page.tsx
- app/admin/sync/mimecast/page.tsx
- app/admin/sync/sentinelone/page.tsx
- app/admin/zabbix-wan/page.tsx
- app/admin/rmm-overshell/page.tsx
- app/admin/itglue-writes/page.tsx
- app/admin/data-browser/tasks/page.tsx
- app/admin/data-browser/projects/page.tsx
- app/admin/data-browser/ticket-notes/page.tsx
- app/admin/data-browser/contracts/page.tsx
- app/admin/data-browser/tickets/page.tsx
- app/admin/data-browser/time-entries/page.tsx
- app/admin/ticket-digest/page.tsx
- app/admin/device-link-conflicts/page.tsx
- app/admin/workflow/history/page.tsx
- app/admin/workflow/pipelines/[id]/page.tsx
- app/analyzer/itglue/applications/page.tsx
- app/analyzer/itglue/applications/[id]/page.tsx
- app/analyzer/itglue/configurations/page.tsx
- app/analyzer/itglue/configurations/[id]/page.tsx
- app/analyzer/itglue/sites/[companyId]/page.tsx
- app/analyzer/queue/page.tsx
- app/analyzer/ticket/[ticketNumber]/page.tsx
- app/analyzer/tickets/page.tsx
- app/analyzer/reports/page.tsx
- app/analyzer/reports/[id]/page.tsx
- app/dashboard/page.tsx
- app/quotes/page.tsx
- app/veeam-analysis/page.tsx
- components/admin/DetailModal.tsx
- components/admin/IntegrationStatusTabs.tsx
- components/admin/SyncScheduler.tsx
- components/admin/audit/audit-log-table.tsx
- components/admin/users/user-table.tsx
- components/admin/users/user-sessions.tsx
- components/analyzer/analysis-view.tsx
- components/settings/active-sessions.tsx
- components/dashboard/resolution-trend.tsx
- components/dashboard/volume-trend.tsx
- components/quotes/ticket-detail-modal.tsx
- components/analytics/TimelineView.tsx
- components/analytics/ScoreCard.tsx
- components/configuration-items/addigy-tab.tsx
- components/status/activity-sparkline.tsx
- components/backup/compliance-detail-table.tsx
- components/backup/company-backup-detail.tsx
Per-file migration plan
app/engagement/profile/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 2
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/engagement/profile/page.tsx)" -ge 2 ] - Per-callsite plan:
- Line 141 (inside
ActivityHeatmapsub-component):d.toLocaleDateString('en-US', { month: 'short' })→d.toLocaleDateString('en-US', { month: 'short', timeZone: tz }). Passtzas a prop toActivityHeatmap. - Line 264 (inside module-scope helper
monthLabel(m)): convert helper tomonthLabel(m, tz); threadtzfrom the component callsite.
- Line 141 (inside
Notes / risks: monthLabel is module-scope; ActivityHeatmap is a sub-component called from EngagementProfilePage. Approach: add tz prop to ActivityHeatmap; convert monthLabel(m, tz).
app/engagement/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 7 (lines 842, 1010, 1106 (×2 calls), 1225, 1253 (×2 calls))
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/engagement/page.tsx)" -ge 7 ] - Per-callsite plan: all 5 lines are inside
EngagementPage(default export from line 462). CalluseUserTimezone()once at top ofEngagementPage. Then per-line:- Line 842:
new Date(user.lastActivity).toLocaleDateString()→new Date(user.lastActivity).toLocaleDateString(undefined, { timeZone: tz }) - Line 1010:
new Date(snap.last_activity_date).toLocaleDateString()→new Date(snap.last_activity_date).toLocaleDateString(undefined, { timeZone: tz }) - Line 1106:
d.toLocaleDateString()→d.toLocaleDateString(undefined, { timeZone: tz });d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })→d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', timeZone: tz }) - Line 1225:
new Date(call.startTime).toLocaleDateString()→new Date(call.startTime).toLocaleDateString(undefined, { timeZone: tz }) - Line 1253: same pattern as 1106
- Line 842:
Notes / risks: very long file (>1280 lines). All leak callsites are within the default export's JSX, so a single const tz = useUserTimezone(); at the top of the function body suffices.
app/admin/sync/duo/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/sync/duo/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 117 (inside
DuoSyncPagedefault export, the innerfmtDatearrow function):new Date(d).toLocaleString()→new Date(d).toLocaleString(undefined, { timeZone: tz }). Note: this is a CLOSURE inside the component (line 117 is inside the function body, not module scope). Just calluseUserTimezone()and referencetzdirectly.
- Line 117 (inside
Notes / risks: fmtDate is also passed as a prop to FlaggedUsersTable (line 286). The closure captures tz already once tz is in scope.
app/admin/sync/datto-rmm/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/sync/datto-rmm/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 23 (module-scope
fmtDate(d)): convert tofmtDate(d, tz). Update all callsites to passtz.
- Line 23 (module-scope
Notes / risks: fmtDate is consumed by StatusTab (line 38) and HistoryTab (line 102) sub-components. Either pass tz as a prop to each sub-component, OR thread tz into the fmtDate calls inside sub-components by passing it down. Approach: add tz prop to StatusTab and HistoryTab; thread tz from default export.
app/admin/sync/veeam/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/sync/veeam/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 26 (module-scope
fmtDate(d)): convert tofmtDate(d, tz). Update all callsites to passtz.
- Line 26 (module-scope
Notes / risks: many sub-components (VeeamStatusTab, HistoryRow, VeeamHistoryTab, AgentsTab, AlarmsTab, RpoTab). Most likely consume fmtDate. Approach: add tz prop to each sub-component that calls fmtDate; thread tz from default export.
app/admin/sync/itglue/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/sync/itglue/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 24 (module-scope
fmtDate(d)): convert tofmtDate(d, tz). Update all callsites to passtz.
- Line 24 (module-scope
Notes / risks: same pattern as datto-rmm. Sub-components: StatusTab, HistoryTab, AboutTab. Add tz prop where needed.
app/admin/sync/mimecast/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 6 (lines 28 (helper definition — leaked at every call), 651, 924, 1239, 1405, 1840 — but the audit cites lines 28, 651, 924, 1239, 1405, 1840 as 6 distinct leak callsites)
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/sync/mimecast/page.tsx)" -ge 6 ] - Per-callsite plan:
- Line 28 (module-scope
fmtDate): convert tofmtDate(d, tz). Update everyfmtDate(...)call in the file. - Line 651 (inside
MessageAnalysisDialog):new Date(message.dateReceived).toLocaleString()→new Date(message.dateReceived).toLocaleString(undefined, { timeZone: tz }) - Line 924 (inside
HeldMailTab):new Date(m.dateReceived).toLocaleString(undefined, { ... })→ add, timeZone: tzto options - Line 1239 (inside
DeliveredAnalysisDialog):new Date(message.received).toLocaleString()→ add(undefined, { timeZone: tz }) - Line 1405 (inside
DeliveredAnalysisDialog):new Date(m.receivedDateTime).toLocaleString(undefined, { ... })→ add, timeZone: tz - Line 1840 (inside
DeliveredMailTab):new Date(m.received).toLocaleString(undefined, { ... })→ add, timeZone: tz
- Line 28 (module-scope
Notes / risks: 6 callsites across 4 sub-components (MessageAnalysisDialog, HeldMailTab, DeliveredAnalysisDialog, DeliveredMailTab). Add tz prop to each sub-component that uses an inline call OR calls fmtDate. Default export MimecastSyncPage calls useUserTimezone() once.
app/admin/sync/sentinelone/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/sync/sentinelone/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 15 (module-scope
fmtDate(d)): convert tofmtDate(d, tz); update callsites.
- Line 15 (module-scope
Notes / risks: fmtDate used by default export SentinelOneSyncPage.
app/admin/zabbix-wan/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 2 (lines 212, 213)
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/zabbix-wan/page.tsx)" -ge 2 ] - Per-callsite plan:
- Line 212:
new Date(ts).toLocaleString()→new Date(ts).toLocaleString(undefined, { timeZone: tz }) - Line 213: same
- Line 212:
Notes / risks: both calls are inside the default export. Single const tz = useUserTimezone(); suffices.
app/admin/rmm-overshell/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 3 (lines 142, 199, 265)
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/rmm-overshell/page.tsx)" -ge 3 ] - Per-callsite plan:
- Line 142, 199, 265: each
new Date(x).toLocaleString()→new Date(x).toLocaleString(undefined, { timeZone: tz })
- Line 142, 199, 265: each
Notes / risks: all inside default export.
app/admin/itglue-writes/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/itglue-writes/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 144:
new Date(w.performed_at).toLocaleString()→new Date(w.performed_at).toLocaleString(undefined, { timeZone: tz })
- Line 144:
app/admin/data-browser/tasks/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/data-browser/tasks/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 100 (DataTable column render, defined inside
TasksBrowserPagebody):new Date(value).toLocaleDateString()→new Date(value).toLocaleDateString(undefined, { timeZone: tz })
- Line 100 (DataTable column render, defined inside
Notes / risks: column array is inside the component body (line 54+), so the closure captures tz for free.
app/admin/data-browser/projects/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/data-browser/projects/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 88 (DataTable column render):
new Date(value).toLocaleDateString()→new Date(value).toLocaleDateString(undefined, { timeZone: tz })
- Line 88 (DataTable column render):
app/admin/data-browser/ticket-notes/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/data-browser/ticket-notes/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 86 (DataTable column render):
new Date(v).toLocaleDateString()→new Date(v).toLocaleDateString(undefined, { timeZone: tz })
- Line 86 (DataTable column render):
app/admin/data-browser/contracts/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 2 (lines 88, 96)
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/data-browser/contracts/page.tsx)" -ge 2 ] - Per-callsite plan:
- Line 88, 96:
new Date(value).toLocaleDateString()→new Date(value).toLocaleDateString(undefined, { timeZone: tz })
- Line 88, 96:
app/admin/data-browser/tickets/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/data-browser/tickets/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 103 (DataTable column render):
new Date(value).toLocaleDateString()→new Date(value).toLocaleDateString(undefined, { timeZone: tz })
- Line 103 (DataTable column render):
app/admin/data-browser/time-entries/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/data-browser/time-entries/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 296 (DataTable column render):
new Date(value).toLocaleDateString()→new Date(value).toLocaleDateString(undefined, { timeZone: tz })
- Line 296 (DataTable column render):
app/admin/ticket-digest/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/ticket-digest/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 410:
new Date(report.generated_at).toLocaleString()→new Date(report.generated_at).toLocaleString(undefined, { timeZone: tz })
- Line 410:
app/admin/device-link-conflicts/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/device-link-conflicts/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 223:
new Date(r.xref.lastSeenAt).toLocaleString()→new Date(r.xref.lastSeenAt).toLocaleString(undefined, { timeZone: tz })
- Line 223:
app/admin/workflow/history/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/workflow/history/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 192:
new Date(exec.created_at).toLocaleString()→new Date(exec.created_at).toLocaleString(undefined, { timeZone: tz })
- Line 192:
app/admin/workflow/pipelines/[id]/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/admin/workflow/pipelines/[id]/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 582:
new Date(exec.started_at).toLocaleString()→new Date(exec.started_at).toLocaleString(undefined, { timeZone: tz })
- Line 582:
app/analyzer/itglue/applications/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/analyzer/itglue/applications/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 129:
new Date(r.latestAudit.generatedAt).toLocaleDateString()→new Date(r.latestAudit.generatedAt).toLocaleDateString(undefined, { timeZone: tz })
- Line 129:
app/analyzer/itglue/applications/[id]/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 3 (lines 411, 720, 779)
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/analyzer/itglue/applications/[id]/page.tsx)" -ge 3 ] - Per-callsite plan:
- Line 411, 720, 779: each
new Date(x).toLocaleString()→new Date(x).toLocaleString(undefined, { timeZone: tz })
- Line 411, 720, 779: each
app/analyzer/itglue/configurations/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/analyzer/itglue/configurations/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 130:
new Date(r.latestAudit.generatedAt).toLocaleDateString()→new Date(r.latestAudit.generatedAt).toLocaleDateString(undefined, { timeZone: tz })
- Line 130:
app/analyzer/itglue/configurations/[id]/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 3 (lines 393, 688, 741)
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/analyzer/itglue/configurations/[id]/page.tsx)" -ge 3 ] - Per-callsite plan:
- Line 393, 688, 741: each
new Date(x).toLocaleString()→new Date(x).toLocaleString(undefined, { timeZone: tz })
- Line 393, 688, 741: each
app/analyzer/itglue/sites/[companyId]/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/analyzer/itglue/sites/[companyId]/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 212:
new Date(e.queuedAt).toLocaleString()→new Date(e.queuedAt).toLocaleString(undefined, { timeZone: tz })
- Line 212:
app/analyzer/queue/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/analyzer/queue/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 103:
new Date(a.triggeredAt).toLocaleString()→new Date(a.triggeredAt).toLocaleString(undefined, { timeZone: tz })
- Line 103:
app/analyzer/ticket/[ticketNumber]/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/analyzer/ticket/[ticketNumber]/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 143:
new Date(a.triggeredAt).toLocaleString()→new Date(a.triggeredAt).toLocaleString(undefined, { timeZone: tz })
- Line 143:
app/analyzer/tickets/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/analyzer/tickets/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 112 (inside module-scope
formatRelative(iso)): convert toformatRelative(iso, tz); update callsites.
- Line 112 (inside module-scope
Notes / risks: formatRelative is module-scope; called from JSX inside the default export. Threading tz is a one-arg change.
app/analyzer/reports/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/analyzer/reports/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 136:
new Date(r.generatedAt).toLocaleString()→new Date(r.generatedAt).toLocaleString(undefined, { timeZone: tz })
- Line 136:
app/analyzer/reports/[id]/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 3 (lines 186, 199, 201)
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/analyzer/reports/[id]/page.tsx)" -ge 3 ] - Per-callsite plan:
- Line 186:
new Date(report.generatedAt).toLocaleString()→..., { timeZone: tz } - Line 199:
new Date(report.dateRangeActual.earliest).toLocaleDateString()→..., { timeZone: tz } - Line 201:
new Date(report.dateRangeActual.latest).toLocaleDateString()→..., { timeZone: tz }
- Line 186:
app/dashboard/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/dashboard/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 152 (inside default export
DashboardPage, JSX prop):new Date().toLocaleDateString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })→ add, timeZone: tzto options
- Line 152 (inside default export
app/quotes/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/quotes/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 107 (inside default export, the
formatDatearrow helper):new Date(dateString).toLocaleDateString('en-US', { ... })→ add, timeZone: tzto options
- Line 107 (inside default export, the
app/veeam-analysis/page.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' app/veeam-analysis/page.tsx)" -ge 1 ] - Per-callsite plan:
- Line 671:
new Date(summary.generated_at).toLocaleString()→new Date(summary.generated_at).toLocaleString(undefined, { timeZone: tz })
- Line 671:
components/admin/DetailModal.tsx
- 'use client' status: yes
- Pre-migration leak count: 4 (lines 160, 610, 656, 658)
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/admin/DetailModal.tsx)" -ge 4 ] - Per-callsite plan:
- Line 135 module-scope
resolveLabel(key, value, type, lookups): convert toresolveLabel(key, value, type, lookups, tz); update callsites (lines 430, 460, 507). - Line 160 (inside
resolveLabel):d.toLocaleDateString(undefined, { ... })→ add, timeZone: tz - Line 610 (inside default export):
new Date(entry.entry_date).toLocaleDateString(undefined, { ... })→ add, timeZone: tz - Line 656 (inside default export):
new Date(note.create_date_time).toLocaleDateString(undefined, { ... })→ add, timeZone: tz - Line 658 (inside default export):
new Date(note.create_date_time).toLocaleTimeString(undefined, { ... })→ add, timeZone: tz
- Line 135 module-scope
Notes / risks: resolveLabel is module-scope and called in 3 places inside the component body. Threading tz is mechanical but the callsite count (3) means we need to update each.
components/admin/IntegrationStatusTabs.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/admin/IntegrationStatusTabs.tsx)" -ge 1 ] - Per-callsite plan:
- Line 34 (module-scope
fmtDate(d)): convert tofmtDate(d, tz); update callsites.
- Line 34 (module-scope
Notes / risks: fmtDate used by VeeamTab, DattoRmmTab, AuvikTab, AddigyTab sub-components. Add tz prop to each and pass from default export.
components/admin/SyncScheduler.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/admin/SyncScheduler.tsx)" -ge 1 ] - Per-callsite plan:
- Line 230:
new Date(dateString).toLocaleString()→new Date(dateString).toLocaleString(undefined, { timeZone: tz })
- Line 230:
Notes / risks: line 230 is inside an arrow function within SyncScheduler (default export), so tz is in scope after useUserTimezone().
components/admin/audit/audit-log-table.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/admin/audit/audit-log-table.tsx)" -ge 1 ] - Per-callsite plan:
- Line 186:
new Date(log.timestamp).toLocaleString()→new Date(log.timestamp).toLocaleString(undefined, { timeZone: tz })
- Line 186:
components/admin/users/user-table.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/admin/users/user-table.tsx)" -ge 1 ] - Per-callsite plan:
- Line 205:
new Date(user.created_at).toLocaleDateString()→new Date(user.created_at).toLocaleDateString(undefined, { timeZone: tz })
- Line 205:
components/admin/users/user-sessions.tsx
- 'use client' status: yes
- Pre-migration leak count: 2 (lines 161, 164)
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/admin/users/user-sessions.tsx)" -ge 2 ] - Per-callsite plan:
- Line 161:
new Date(session.created_at).toLocaleString()→..., { timeZone: tz } - Line 164:
new Date(session.expires_at).toLocaleString()→..., { timeZone: tz }
- Line 161:
components/analyzer/analysis-view.tsx
- 'use client' status: yes
- Pre-migration leak count: 4 (lines 115, 222, 310, 401)
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/analyzer/analysis-view.tsx)" -ge 4 ] - Per-callsite plan:
- Lines 115, 222, 310, 401: each
new Date(x).toLocaleString()→new Date(x).toLocaleString(undefined, { timeZone: tz })
- Lines 115, 222, 310, 401: each
Notes / risks: all four are inside AnalysisView (default export from line 72). Single useUserTimezone() at top.
components/settings/active-sessions.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/settings/active-sessions.tsx)" -ge 1 ] - Per-callsite plan:
- Line 118:
new Date(session.created_at).toLocaleDateString()→new Date(session.created_at).toLocaleDateString(undefined, { timeZone: tz })
- Line 118:
components/dashboard/resolution-trend.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/dashboard/resolution-trend.tsx)" -ge 1 ] - Per-callsite plan:
- Line 27 (module-scope
fmtDate(iso)): convert tofmtDate(iso, tz); update callsite (Recharts axis tick formatter).
- Line 27 (module-scope
components/dashboard/volume-trend.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/dashboard/volume-trend.tsx)" -ge 1 ] - Per-callsite plan:
- Line 28 (module-scope
fmtDate(iso)): convert tofmtDate(iso, tz); update callsite.
- Line 28 (module-scope
components/quotes/ticket-detail-modal.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/quotes/ticket-detail-modal.tsx)" -ge 1 ] - Per-callsite plan:
- Line 231 (inside
TicketDetailModalnamed export, arrowformatDate):new Date(dateString).toLocaleString('en-US', { ... })→ add, timeZone: tzto options.
- Line 231 (inside
Notes / risks: formatDate is defined inside the component, so tz is in scope.
components/analytics/TimelineView.tsx
- 'use client' status: yes
- Pre-migration leak count: 4 (lines 133, 140, 148, 303)
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/analytics/TimelineView.tsx)" -ge 4 ] - Per-callsite plan:
- Line 133:
new Date(groupKey + ':00:00').toLocaleString('en-US', { ... })→ add, timeZone: tz - Line 140:
new Date(groupKey).toLocaleDateString('en-US', { ... })→ add, timeZone: tz - Line 148:
new Date(groupKey + '-01').toLocaleDateString('en-US', { ... })→ add, timeZone: tz - Line 303:
new Date(event.timestamp).toLocaleTimeString()→new Date(event.timestamp).toLocaleTimeString(undefined, { timeZone: tz })
- Line 133:
Notes / risks: all 4 are inside TimelineView (named export, line 21). Single useUserTimezone().
components/analytics/ScoreCard.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/analytics/ScoreCard.tsx)" -ge 1 ] - Per-callsite plan:
- Line 486 (inside
AggregateScoreCard, named export at line 426):analysis.dateRange.latest.toLocaleDateString()→analysis.dateRange.latest.toLocaleDateString(undefined, { timeZone: tz })
- Line 486 (inside
components/configuration-items/addigy-tab.tsx
- 'use client' status: yes
- Pre-migration leak count: 2 (lines 107, 327)
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/configuration-items/addigy-tab.tsx)" -ge 2 ] - Per-callsite plan:
- Line 107:
new Date(device['Last Check In']).toLocaleString()→..., { timeZone: tz } - Line 327:
new Date(device['Warranty Expiration Date']).toLocaleDateString()→..., { timeZone: tz }
- Line 107:
components/status/activity-sparkline.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/status/activity-sparkline.tsx)" -ge 1 ] - Per-callsite plan:
- Line 30 (module-scope
fmtHour(iso)): convert tofmtHour(iso, tz); update callsites inActivitySparkline.
- Line 30 (module-scope
components/backup/compliance-detail-table.tsx
- 'use client' status: yes
- Pre-migration leak count: 2 (lines 170, 173)
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/backup/compliance-detail-table.tsx)" -ge 2 ] - Per-callsite plan:
- Lines 170, 173 (inside
ContractCoverageModalsub-component, defined at line 85):new Date(contract.start_date).toLocaleDateString()/new Date(contract.end_date).toLocaleDateString()→ add(undefined, { timeZone: tz })
- Lines 170, 173 (inside
Notes / risks: leak callsites are inside ContractCoverageModal, a sub-component. Pass tz as a prop from ComplianceDetailTable (the named export) → ContractCoverageModal.
components/backup/company-backup-detail.tsx
- 'use client' status: yes
- Pre-migration leak count: 1
- Post-migration acceptance grep:
[ "$(grep -c 'timeZone:' components/backup/company-backup-detail.tsx)" -ge 1 ] - Per-callsite plan:
- Line 46 (module-scope
formatDate(dateStr)): convert toformatDate(dateStr, tz); update callsite(s) inside the named export.
- Line 46 (module-scope
Deferred
components/configuration-items/auvik-tab.tsx(line 26 leak): file does NOT declare'use client'at the top. Its parent (components/configuration-items/config-item-modal.tsx) is a client module, so it inherits client-component status when imported, but per Plan 05 rule we do NOT silently add'use client'to a server-eligible component. Rationale: preserve existing layering choice (the file is consumed only via a client parent, but the directive boundary deliberately stops here). Tracked as v2 follow-up.app/admin/data-browser/time-entries/page.tsx.backup: orphaned backup file (no active route consumes it). Per audit "Plan 05 should delete the file (not migrate it)". Action:git rminstead of migrate.
Coverage check vs audit
- Audit leak count: 81
- Files migrated: 49 (50 leak files in audit minus auvik-tab DEFER minus .backup deleted file = 49 active migrations)
- Audit files: 39 (the audit groups all leaks by file;
app/admin/data-browser/time-entries/page.tsx.backupis mentioned as a footnote, not in the count). Theauvik-tab.tsxDEFER is one file → 38 active migration files; this manifest's## Files to migratechecklist has 51 entries because the audit's leak count of "39 files" was a quick tally; the actual unique leak file list is the 51 here.
Wait — let me recount. Audit table says 81 callsites across 39 files. Counting unique file paths in the audit's leak table: 51 unique paths. Audit summary says "39 files" — this is a transcription error in the audit's summary line. The truth is the 51 distinct file paths in the leak table.
Actual file count: 51 in audit leak table → minus 2 deferred (auvik-tab + .backup file) = 49 files migrated by Plan 05.
The total leak callsite count (81) is unchanged: 50 (51 audit files − 1 auvik leak deferred = 50; .backup is not counted in audit's 81) − 1 = 80 callsites remaining for migration. Actually since .backup was already excluded from the audit (per the audit's "Excluded" list), the 81 covers only the 51 active files; minus 1 leak in auvik-tab.tsx = 80 leak callsites Plan 05 will migrate.
Wait — the audit says "Excluded: app/admin/data-browser/time-entries/page.tsx.backup". So .backup is NOT in the 81. Plan 05's actions:
- Delete
app/admin/data-browser/time-entries/page.tsx.backup(1 file, 1 leak — but not counted in 81). - Migrate 50 of the 51 audit files (1 file deferred — auvik-tab — 1 leak left unfixed).
- 80 of the 81 audit leak callsites migrated. 1 deferred.