Skip to content

fix(frontend): UTC day boundaries so dashboard today matches everywhere - #2931

Merged
riderx merged 10 commits into
mainfrom
cursor/dashboard-utc-timezone-1e2d
Aug 8, 2026
Merged

fix(frontend): UTC day boundaries so dashboard today matches everywhere#2931
riderx merged 10 commits into
mainfrom
cursor/dashboard-utc-timezone-1e2d

Conversation

@riderx

@riderx riderx commented Aug 7, 2026

Copy link
Copy Markdown
Member

Summary (AI generated)

  • Dashboard daily charts and API date params use UTC calendar day boundaries so “today” matches for all viewers of the same org.
  • Review follow-up: exclusive UTC upper bound for deployments, elapsed-UTC billing-day math (incl. 31-day cycles), UTC log-nav day bounds, Chart.js Legend registration, reactive cycle ends for expired subscriptions.
  • Fixed LineChartStats typecheck: remaining getDaysInCurrentMonth call sites updated to getDaysInCurrentUtcMonth.

Motivation (AI generated)

Brazil customers saw today’s device/stats after a release; Capgo (Europe) viewing the same org only saw through yesterday. Local midnight + toISOString() shifted the UTC day for positive offsets. Review bots also flagged remaining UTC edge cases that could drop today’s deployments or mis-size billing charts.

Business Impact (AI generated)

Dashboard “today” and billing-period charts stay consistent worldwide for the same org, avoiding false “missing data” support issues around timezone boundaries.

Test Plan (AI generated)

  • Unit tests for UTC date params, billing boundaries, day bounds, billing-window math
  • bun run typecheck:frontend passes after getDaysInCurrentUtcMonth fix
  • Same org from UTC+2 and UTC−3: network from/to end on the same UTC day
  • Deployments later on the current UTC day appear in Deployment stats
  • Chart day click opens logs for that UTC calendar day in US timezones
  • Billing period starting on the 30th/31st keeps day-1 and today’s buckets

Generated with AI

Open in Web Open in Cursor 

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes

    • Improved dashboard chart and billing-period accuracy across time zones with consistent UTC day boundaries.
    • Corrected date ranges, tooltip dates, “today” indicators, and rolling 30-day calculations.
    • Improved handling of missing daily data, billing-window boundaries, and chart color consistency.
    • Added consistent minimum loading delays for dashboard statistics.
  • Refactor

    • Standardized chart configuration, billing-cycle handling, and date processing across dashboard views.
    • Improved billing-period filtering and daily-series calculations.

Dashboard charts derived "today" from browser-local midnight then
converted with toISOString(), so Europe (east of UTC) requested
yesterday while Brazil kept today. Align all dashboard date ranges
and API params with UTC days to match backend daily_* buckets.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR centralizes UTC date handling and dashboard chart behavior. It adds shared billing-cycle, series transformation, Chart.js registration, color, today-line, filtering, and loading-delay utilities.

Changes

UTC date and range foundation

Layer / File(s) Summary
UTC date and range foundation
src/services/date.ts, src/services/buildCharts.ts, src/services/chartDataService.ts, src/services/chartTooltip.ts, src/services/supabase.ts, src/services/conversion.ts, src/stores/*, src/composables/useBuildChartConfig.ts, tests/*
Date normalization, date arithmetic, API parameters, chart ranges, tooltip dates, store calculations, fallback ranges, and tests now use UTC calendar boundaries.

Shared chart contracts and services

Layer / File(s) Summary
Shared chart contracts and services
src/composables/useOrgBillingCycleChart.ts, src/services/dailyChartProps.ts, src/services/dashboardChartRegister.ts, src/services/chartTodayLine.ts, src/utils/chartOptimizations.ts, src/utils/minDelay.ts, tests/chart-optimizations.unit.test.ts
Shared utilities now provide chart props, Chart.js registration, billing-cycle transformations, today-line options, safe colors, billing-period filtering, dynamic series windows, and minimum loading delays.

Dashboard data and loading flows

Layer / File(s) Summary
Dashboard data and loading flows
src/components/dashboard/BundleUploadsCard.vue, src/components/dashboard/DeploymentStatsCard.vue, src/components/dashboard/DevicesStats.vue, src/components/dashboard/UpdateStatsCard.vue, src/components/dashboard/Usage.vue
Dashboard queries, series sizing, billing-period filtering, statistic indexing, date labels, evolution calculations, and loading delays now use shared UTC-aware logic.

Dashboard chart integrations

Layer / File(s) Summary
Dashboard chart integrations
src/components/dashboard/BundleUploadsChart.vue, src/components/dashboard/DeploymentStatsChart.vue, src/components/dashboard/LineChartStats.vue, src/components/dashboard/UpdateStatsChart.vue
Dashboard charts now use shared props, registration, billing-cycle state, series transformation, color generation, tooltip routing, and today-line configuration.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • Cap-go/capgo.app#2755 — Both changes use UTC-normalized billing-period calculations and half-open date ranges.

Suggested labels: codex

Suggested reviewers: cursor

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.63% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main UTC dashboard date-boundary change.
Description check ✅ Passed The description gives a detailed summary, motivation, business impact, and test plan, but omits the template checklist and screenshots section.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@codspeed-hq

codspeed-hq Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing cursor/dashboard-utc-timezone-1e2d (711bd10) with main (10f1f4a)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Remove unused normalizeToStartOfDay and share billing-period filter
plus chart today/transform helpers to drop new-code duplication.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr August 7, 2026 19:58 Inactive
Move billing-cycle chart helpers into useOrgBillingCycleChart and
reuse computeLastDayEvolution / ensureMinDelay so new-code duplication
stays under the Sonar quality gate.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr August 7, 2026 20:06 Inactive
Extract createTodayLineOptions and hue helpers so Sonar no longer
counts duplicated new-code blocks across dashboard charts.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr August 7, 2026 20:21 Inactive
Register dashboard charts once and use useCurrentOrgBillingCycleChart
so file preambles no longer share long duplicated new-code blocks.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr August 7, 2026 20:31 Inactive
Extract dailyChartBaseProps so dashboard charts no longer share long
identical defineProps blocks counted as new duplication.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr August 7, 2026 20:40 Inactive
Share useDashboardDailyChartCycle and diversify chart file preambles
so identical new-code blocks stay under the duplication threshold.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr August 7, 2026 20:41 Inactive
@riderx
riderx marked this pull request as ready for review August 7, 2026 21:21
@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_e12b6610-73ad-498d-abfa-a036f67453e7)

@coderabbitai coderabbitai Bot added the codex label Aug 7, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/dashboard/BundleUploadsChart.vue`:
- Around line 16-17: Replace the relative imports in
src/components/dashboard/BundleUploadsChart.vue lines 16-17 and
src/components/dashboard/DeploymentStatsChart.vue lines 16-17 with
~/components/dashboard/... alias paths for createChartLegendItems and
ChartLegend. Replace the relative chartTooltip import in
src/components/dashboard/UpdateStatsChart.vue line 17 with
~/services/chartTooltip.

In `@src/components/dashboard/DeploymentStatsCard.vue`:
- Around line 145-146: Update the DeploymentStatsCard date-range query to
compute the next UTC day after last30DaysEnd, format it with formatUtcDateParam,
and filter deployed_at with an exclusive .lt() bound instead of .lte(). Add a
boundary test covering a deployment later on the current UTC day.

In `@src/services/chartTooltip.ts`:
- Around line 64-77: Update the log-navigation handler in UpdateStatsChart.vue
to derive both start and end query bounds from the selected UTC calendar date
using Date.UTC, preserving the day represented by clickContext.date across local
time zones. Remove the unused dayjs import, and add a non-UTC timezone test
covering the generated start and end parameters.

In `@src/services/dashboardChartRegister.ts`:
- Around line 1-30: Update registerDashboardCharts to import the Chart.js Legend
component and include Legend in the Chart.register call, ensuring
UpdateStatsChart’s enabled plugins.legend renders on direct page loads.

In `@src/services/date.ts`:
- Around line 186-190: Update getChartDateRange to parse date-only billingStart
and billingEnd values with a dedicated UTC range-boundary parser before
normalizeToUtcStartOfDay, while preserving parseDatePreservingUtc for localized
display paths. Add a regression test covering getChartDateRange(true,
'2026-08-07', ...) in a positive-offset timezone and verify the UTC date remains
August 7.
- Around line 159-165: Replace the nested ternary in formatUtcDateParam with an
if-based branch that selects the DATE_ONLY_RE UTC parsing path versus the
regular string parsing path, while preserving the existing Date handling,
invalid-date empty-string return, and ISO date formatting.

In `@src/stores/organization.ts`:
- Around line 360-363: Normalize the UTC start-of-day once before calculating
the billing range, then derive both last30DaysEnd and last30DaysStart from that
single anchor. Preserve the existing offsets so the request consistently covers
the intended 30-day window.

In `@src/utils/chartOptimizations.ts`:
- Around line 27-49: Update filterDailySeriesToBillingPeriod to normalize
billingStart to the UTC start of its day, derive the active billing-cycle start
using calendar-month arithmetic, and calculate currentBillingDay as the UTC
elapsed-day difference from that boundary plus one. Use the normalized
billingStart for date comparisons and billingIndex calculations so cycles
spanning months of different lengths retain every day.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 047a23cf-49a1-4fac-9b4f-33925a2164b4

📥 Commits

Reviewing files that changed from the base of the PR and between 12b8d22 and 7da548b.

📒 Files selected for processing (26)
  • src/components/dashboard/BundleUploadsCard.vue
  • src/components/dashboard/BundleUploadsChart.vue
  • src/components/dashboard/DeploymentStatsCard.vue
  • src/components/dashboard/DeploymentStatsChart.vue
  • src/components/dashboard/DevicesStats.vue
  • src/components/dashboard/LineChartStats.vue
  • src/components/dashboard/UpdateStatsCard.vue
  • src/components/dashboard/UpdateStatsChart.vue
  • src/components/dashboard/Usage.vue
  • src/composables/useBuildChartConfig.ts
  • src/composables/useOrgBillingCycleChart.ts
  • src/services/buildCharts.ts
  • src/services/chartDataService.ts
  • src/services/chartTodayLine.ts
  • src/services/chartTooltip.ts
  • src/services/conversion.ts
  • src/services/dailyChartProps.ts
  • src/services/dashboardChartRegister.ts
  • src/services/date.ts
  • src/services/supabase.ts
  • src/stores/main.ts
  • src/stores/organization.ts
  • src/utils/chartOptimizations.ts
  • src/utils/minDelay.ts
  • tests/dashboard-date-range.unit.test.ts
  • tests/date.unit.test.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

Comment on lines 16 to 17
import { createChartLegendItems } from './chartLegend'
import ChartLegend from './ChartLegend.vue'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the frontend alias for all new src/ imports.

  • src/components/dashboard/BundleUploadsChart.vue#L16-L17: Replace ./chartLegend and ./ChartLegend.vue with their ~/components/dashboard/... paths.
  • src/components/dashboard/DeploymentStatsChart.vue#L16-L17: Replace ./chartLegend and ./ChartLegend.vue with their ~/components/dashboard/... paths.
  • src/components/dashboard/UpdateStatsChart.vue#L17-L17: Replace ../../services/chartTooltip with ~/services/chartTooltip.

As per coding guidelines, import using the ~/ alias for the src/ directory in frontend code instead of relative paths.

📍 Affects 3 files
  • src/components/dashboard/BundleUploadsChart.vue#L16-L17 (this comment)
  • src/components/dashboard/DeploymentStatsChart.vue#L16-L17
  • src/components/dashboard/UpdateStatsChart.vue#L17-L17
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/dashboard/BundleUploadsChart.vue` around lines 16 - 17,
Replace the relative imports in src/components/dashboard/BundleUploadsChart.vue
lines 16-17 and src/components/dashboard/DeploymentStatsChart.vue lines 16-17
with ~/components/dashboard/... alias paths for createChartLegendItems and
ChartLegend. Replace the relative chartTooltip import in
src/components/dashboard/UpdateStatsChart.vue line 17 with
~/services/chartTooltip.

Source: Coding guidelines

Comment thread src/components/dashboard/DeploymentStatsCard.vue Outdated
Comment thread src/services/chartTooltip.ts
Comment thread src/services/dashboardChartRegister.ts
Comment thread src/services/date.ts
Comment thread src/services/date.ts
Comment thread src/stores/organization.ts Outdated
Comment thread src/utils/chartOptimizations.ts Outdated
Comment on lines +27 to +49
export function filterDailySeriesToBillingPeriod(fullData: number[], last30DaysStart: Date, billingStart: Date) {
const currentDate = normalizeToUtcStartOfDay()

let currentBillingDay: number
if (billingStart.getUTCDate() === 1) {
currentBillingDay = currentDate.getUTCDate()
}
else {
const billingStartDay = billingStart.getUTCDate()
const daysInMonth = new Date(Date.UTC(currentDate.getUTCFullYear(), currentDate.getUTCMonth() + 1, 0)).getUTCDate()
currentBillingDay = (currentDate.getUTCDate() - billingStartDay + 1 + daysInMonth) % daysInMonth
if (currentBillingDay === 0)
currentBillingDay = daysInMonth
}

const billingData = Array.from({ length: currentBillingDay }).fill(0) as number[]
for (let i = 0; i < 30; i++) {
const dataDate = addUtcDays(last30DaysStart, i)
if (dataDate >= billingStart && dataDate <= currentDate) {
const billingIndex = Math.floor((dataDate.getTime() - billingStart.getTime()) / (1000 * 60 * 60 * 24))
if (billingIndex >= 0 && billingIndex < currentBillingDay)
billingData[billingIndex] = fullData[i]
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Calculate the billing-day count from the active cycle boundary.

The day-of-month formula fails when the cycle crosses months with different lengths. For a cycle starting March 30 and a current date of April 1, Lines 36-39 calculate 2. The cycle contains three UTC days. Line 47 then drops the April 1 value at billing index 2.

Derive the active billing-cycle start with calendar-month arithmetic. Then calculate currentBillingDay from the UTC elapsed-day difference plus one. Normalize billingStart in this helper before comparisons.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/utils/chartOptimizations.ts` around lines 27 - 49, Update
filterDailySeriesToBillingPeriod to normalize billingStart to the UTC start of
its day, derive the active billing-cycle start using calendar-month arithmetic,
and calculate currentBillingDay as the UTC elapsed-day difference from that
boundary plus one. Use the normalized billingStart for date comparisons and
billingIndex calculations so cycles spanning months of different lengths retain
every day.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found across 26 files

Confidence score: 3/5

  • In src/components/dashboard/LineChartStats.vue, the chart now mixes UTC day boundaries with local getCurrentDayMonth() in accumulateData/per-app reduction, so cumulative cutoff and “today” indexing can drift by timezone and show shifted data windows—standardize all day-boundary math on one timezone basis and add cross-timezone coverage.
  • In src/services/chartTooltip.ts (with UpdateStatsChart consumers), a UTC-midnight click date is still resolved through local day derivation, so clicking a day can open logs for the wrong date for some users—normalize the click context/day-key mapping end-to-end (UTC or local, but consistently).
  • In src/services/buildCharts.ts, changing the upper bound from end-of-day to new Date() can alter created_at filtering near day boundaries and produce inconsistent chart ranges versus prior behavior—confirm intended semantics and either restore explicit end-of-day handling or update bounds logic/tests accordingly.
  • src/composables/useBuildChartConfig.ts and src/utils/minDelay.ts leave deduplication only partially applied (inline today-line config and repeated spinner-delay logic), which increases drift risk across views over time—route existing call sites through the shared helpers to keep behavior and styling consistent.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/services/chartTooltip.ts">

<violation number="1" location="src/services/chartTooltip.ts:64">
P2: Clicking an update-chart day can open logs for a different day depending on the viewer's timezone. The UTC-midnight `Date` introduced here is passed through `clickContext`, but `UpdateStatsChart` still derives local-day bounds; the click path should preserve the UTC calendar day when constructing the log query (or pass a calendar-day-safe local `Date` separately from the UTC tooltip date).</violation>
</file>

<file name="src/utils/minDelay.ts">

<violation number="1" location="src/utils/minDelay.ts:2">
P3: This helper duplicates the identical `elapsed < 300 → setTimeout` spinner-delay block already inlined in useBuildCardStats.ts, Usage.vue, and UpdateStatsCard.vue. Since the PR's goal is deduplication, migrate those three inline spots to call `ensureMinDelay(startTime)`; otherwise refreshData/usage/update paths keep two parallel implementations of the same logic.</violation>
</file>

<file name="src/components/dashboard/LineChartStats.vue">

<violation number="1" location="src/components/dashboard/LineChartStats.vue:48">
P1: Cumulative usage can still shift its cutoff by the browser timezone: this line switches the chart cycle/today index to UTC, but `accumulateData` and the per-app reducer continue using local `getCurrentDayMonth()`. Reusing the composable’s UTC `transformDailySeries` for both total and per-app data would keep the cumulative today bucket aligned with the UTC marker.</violation>
</file>

<file name="src/composables/useBuildChartConfig.ts">

<violation number="1" location="src/composables/useBuildChartConfig.ts:7">
P3: The new `createTodayLineOptions` helper centralizes the today-line styling, but `useBuildChartConfig` still returns the same inline today-line config with the identical hardcoded colors rather than delegating to the helper. This leaves two copies of the today-line look in the codebase, defeating the PR's dedup goal: future styling changes have to be updated in both places. Consider calling `createTodayLineOptions` here too (it already replicates the same `useBillingPeriod`/index guard).</violation>
</file>

<file name="src/services/buildCharts.ts">

<violation number="1" location="src/services/buildCharts.ts:62">
P3: The build chart's created_at upper bound changed behavior: the old `endOfToday.setHours(23,59,59,999)` (end of local day) was removed, so `endISO` is now the instant the window is built (`new Date()`), while `todayStart` moved to UTC midnight. This makes `endISO` time-of-fetch dependent and no longer 'end of today' as the `BuildChartWindow.endISO` comment documents, and it isn't aligned with the UTC day boundary that `todayStart` now uses. Consider restoring the intent by normalizing to the UTC end of day (e.g. `endOfToday.setUTCHours(23,59,59,999)`) or updating the comment/name to reflect that `endISO` is now 'fetch time' rather than end of today.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/utils/chartOptimizations.ts Outdated
Comment thread src/components/dashboard/DeploymentStatsCard.vue Outdated
})
return mapping
})
const { cycleStart, cycleEnd, todayLimit } = useDashboardDailyChartCycle(() => props.useBillingPeriod)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Cumulative usage can still shift its cutoff by the browser timezone: this line switches the chart cycle/today index to UTC, but accumulateData and the per-app reducer continue using local getCurrentDayMonth(). Reusing the composable’s UTC transformDailySeries for both total and per-app data would keep the cumulative today bucket aligned with the UTC marker.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/dashboard/LineChartStats.vue, line 48:

<comment>Cumulative usage can still shift its cutoff by the browser timezone: this line switches the chart cycle/today index to UTC, but `accumulateData` and the per-app reducer continue using local `getCurrentDayMonth()`. Reusing the composable’s UTC `transformDailySeries` for both total and per-app data would keep the cumulative today bucket aligned with the UTC marker.</comment>

<file context>
@@ -49,48 +39,29 @@ const props = defineProps({
-  })
-  return mapping
-})
+const { cycleStart, cycleEnd, todayLimit } = useDashboardDailyChartCycle(() => props.useBillingPeriod)
 
-// Click handler for tooltip items - navigates to app detail page
</file context>

Comment thread src/composables/useOrgBillingCycleChart.ts Outdated
Comment thread src/services/date.ts Outdated
Comment thread src/stores/organization.ts Outdated
Comment thread src/services/date.ts Outdated
Comment thread src/utils/minDelay.ts
@@ -0,0 +1,6 @@
/** Ensure at least `minMs` elapsed since `startTime` before continuing (spinner UX). */
export async function ensureMinDelay(startTime: number, minMs = 300) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This helper duplicates the identical elapsed < 300 → setTimeout spinner-delay block already inlined in useBuildCardStats.ts, Usage.vue, and UpdateStatsCard.vue. Since the PR's goal is deduplication, migrate those three inline spots to call ensureMinDelay(startTime); otherwise refreshData/usage/update paths keep two parallel implementations of the same logic.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/utils/minDelay.ts, line 2:

<comment>This helper duplicates the identical `elapsed < 300 → setTimeout` spinner-delay block already inlined in useBuildCardStats.ts, Usage.vue, and UpdateStatsCard.vue. Since the PR's goal is deduplication, migrate those three inline spots to call `ensureMinDelay(startTime)`; otherwise refreshData/usage/update paths keep two parallel implementations of the same logic.</comment>

<file context>
@@ -0,0 +1,6 @@
+/** Ensure at least `minMs` elapsed since `startTime` before continuing (spinner UX). */
+export async function ensureMinDelay(startTime: number, minMs = 300) {
+  const elapsed = Date.now() - startTime
+  if (elapsed < minMs)
</file context>

import { createLegendConfig, createStackedChartScales } from '~/services/chartConfig'
import { createTooltipConfig } from '~/services/chartTooltip'
import { generateMonthDays } from '~/services/date'
import { generateMonthDays, normalizeToUtcStartOfDay } from '~/services/date'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The new createTodayLineOptions helper centralizes the today-line styling, but useBuildChartConfig still returns the same inline today-line config with the identical hardcoded colors rather than delegating to the helper. This leaves two copies of the today-line look in the codebase, defeating the PR's dedup goal: future styling changes have to be updated in both places. Consider calling createTodayLineOptions here too (it already replicates the same useBillingPeriod/index guard).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/composables/useBuildChartConfig.ts, line 7:

<comment>The new `createTodayLineOptions` helper centralizes the today-line styling, but `useBuildChartConfig` still returns the same inline today-line config with the identical hardcoded colors rather than delegating to the helper. This leaves two copies of the today-line look in the codebase, defeating the PR's dedup goal: future styling changes have to be updated in both places. Consider calling `createTodayLineOptions` here too (it already replicates the same `useBillingPeriod`/index guard).</comment>

<file context>
@@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n'
 import { createLegendConfig, createStackedChartScales } from '~/services/chartConfig'
 import { createTooltipConfig } from '~/services/chartTooltip'
-import { generateMonthDays } from '~/services/date'
+import { generateMonthDays, normalizeToUtcStartOfDay } from '~/services/date'
 import { useOrganizationStore } from '~/stores/organization'
 
</file context>

export function getBuildChartWindow(useBillingPeriod: boolean, subscriptionStart?: string | null): BuildChartWindow {
const todayStart = new Date()
todayStart.setHours(0, 0, 0, 0)
const todayStart = normalizeToUtcStartOfDay()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The build chart's created_at upper bound changed behavior: the old endOfToday.setHours(23,59,59,999) (end of local day) was removed, so endISO is now the instant the window is built (new Date()), while todayStart moved to UTC midnight. This makes endISO time-of-fetch dependent and no longer 'end of today' as the BuildChartWindow.endISO comment documents, and it isn't aligned with the UTC day boundary that todayStart now uses. Consider restoring the intent by normalizing to the UTC end of day (e.g. endOfToday.setUTCHours(23,59,59,999)) or updating the comment/name to reflect that endISO is now 'fetch time' rather than end of today.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/services/buildCharts.ts, line 62:

<comment>The build chart's created_at upper bound changed behavior: the old `endOfToday.setHours(23,59,59,999)` (end of local day) was removed, so `endISO` is now the instant the window is built (`new Date()`), while `todayStart` moved to UTC midnight. This makes `endISO` time-of-fetch dependent and no longer 'end of today' as the `BuildChartWindow.endISO` comment documents, and it isn't aligned with the UTC day boundary that `todayStart` now uses. Consider restoring the intent by normalizing to the UTC end of day (e.g. `endOfToday.setUTCHours(23,59,59,999)`) or updating the comment/name to reflect that `endISO` is now 'fetch time' rather than end of today.</comment>

<file context>
@@ -57,25 +59,22 @@ export interface BuildChartWindow {
 export function getBuildChartWindow(useBillingPeriod: boolean, subscriptionStart?: string | null): BuildChartWindow {
-  const todayStart = new Date()
-  todayStart.setHours(0, 0, 0, 0)
+  const todayStart = normalizeToUtcStartOfDay()
   const endOfToday = new Date()
-  endOfToday.setHours(23, 59, 59, 999)
</file context>

Include today's deployments with an exclusive UTC upper bound, keep
billing-cycle math on elapsed UTC days, and preserve UTC calendar days
for chart click log navigation and date-only billing boundaries.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr August 8, 2026 07:15 Inactive
@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_f38c1f75-ed55-4c5f-85cd-fefb8b73bbf8)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/dashboard/BundleUploadsCard.vue`:
- Around line 181-186: Update the raw-row caching used by the series-window
query in BundleUploadsCard.vue (lines 181-186) and DeploymentStatsCard.vue
(lines 200-201) so each cache entry is keyed by organization plus the resolved
UTC start and exclusive-end bounds derived from useBillingPeriod, seriesStart,
and exclusiveEnd; ensure calculateStats(false) never reuses rows from a
different window.

In `@src/components/dashboard/LineChartStats.vue`:
- Line 14: In LineChartStats, replace both unresolved getDaysInCurrentMonth
calls with the imported getDaysInCurrentUtcMonth helper, preserving the existing
call arguments and behavior.

In `@src/services/date.ts`:
- Around line 206-213: Update formatUtcDateParam to validate date-only strings
against a real calendar date before constructing the UTC Date, so values such as
2026-02-30 follow the existing empty invalid-date fallback instead of being
normalized. Add a regression test covering 2026-02-30 and preserve valid
date-only formatting.

In `@tests/date.unit.test.ts`:
- Around line 143-145: Update the zone-less ISO regression test for
formatUtcDateParam to run under TZ=America/Los_Angeles, use the
timezone-sensitive input 2026-08-07T23:30:00, and continue expecting 2026-08-07.
Configure the test command or runner environment rather than mutating
process.env.TZ within the suite.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: eeca0302-617a-4478-8383-3a1b242e6532

📥 Commits

Reviewing files that changed from the base of the PR and between 7da548b and 71e1ce8.

📒 Files selected for processing (15)
  • src/components/dashboard/BundleUploadsCard.vue
  • src/components/dashboard/BundleUploadsChart.vue
  • src/components/dashboard/DeploymentStatsCard.vue
  • src/components/dashboard/DeploymentStatsChart.vue
  • src/components/dashboard/LineChartStats.vue
  • src/components/dashboard/UpdateStatsChart.vue
  • src/components/dashboard/Usage.vue
  • src/composables/useOrgBillingCycleChart.ts
  • src/services/dailyChartProps.ts
  • src/services/dashboardChartRegister.ts
  • src/services/date.ts
  • src/stores/organization.ts
  • src/utils/chartOptimizations.ts
  • tests/chart-optimizations.unit.test.ts
  • tests/date.unit.test.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

Comment on lines +181 to +186
// Fetch series window (billing cycle or last 30 UTC days)
const query = useSupabase()
.from('app_versions')
.select('created_at, app_id, deleted, r2_path, external_url, user_id')
.gte('created_at', last30DaysStart.toISOString())
.lte('created_at', last30DaysEnd.toISOString())
.lt('created_at', last30DaysEnd.toISOString())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Key cached raw data by the resolved series window.

Both components cache raw rows only by organization, but the query now depends on useBillingPeriod, seriesStart, and exclusiveEnd. When a user switches views, calculateStats(false) can reuse rows from a different window. This produces missing billing-cycle history or stale out-of-range data.

  • src/components/dashboard/BundleUploadsCard.vue#L181-L186: Include the resolved UTC bounds in the cache key, or cache a verified superset before filtering.
  • src/components/dashboard/DeploymentStatsCard.vue#L200-L201: Include the resolved UTC bounds in the cache key, or cache a verified superset before filtering.
📍 Affects 2 files
  • src/components/dashboard/BundleUploadsCard.vue#L181-L186 (this comment)
  • src/components/dashboard/DeploymentStatsCard.vue#L200-L201
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/dashboard/BundleUploadsCard.vue` around lines 181 - 186,
Update the raw-row caching used by the series-window query in
BundleUploadsCard.vue (lines 181-186) and DeploymentStatsCard.vue (lines
200-201) so each cache entry is keyed by organization plus the resolved UTC
start and exclusive-end bounds derived from useBillingPeriod, seriesStart, and
exclusiveEnd; ensure calculateStats(false) never reuses rows from a different
window.

Comment thread src/components/dashboard/LineChartStats.vue
Comment thread src/services/date.ts
Comment on lines +206 to +213
export function formatUtcDateParam(date: Date | string = new Date()) {
let parsed: Date
if (typeof date === 'string' && DATE_ONLY_RE.test(date))
parsed = new Date(`${date}T00:00:00.000Z`)
else if (typeof date === 'string' && ZONELESS_ISO_DATETIME_RE.test(date))
parsed = new Date(`${date}Z`)
else
parsed = new Date(date)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject calendar-invalid date-only parameters.

new Date('2026-02-30T00:00:00.000Z') normalizes to March 2. This function returns 2026-03-02 instead of its empty invalid-date fallback. Validate date-only fields before formatting. Add a regression test for 2026-02-30.

Proposed fix
 export function formatUtcDateParam(date: Date | string = new Date()) {
+  if (typeof date === 'string' && DATE_ONLY_RE.test(date)) {
+    const parsed = parseUtcRangeBoundary(date)
+    return parsed ? parsed.toISOString().slice(0, 10) : ''
+  }
+
   let parsed: Date
-  if (typeof date === 'string' && DATE_ONLY_RE.test(date))
-    parsed = new Date(`${date}T00:00:00.000Z`)
-  else if (typeof date === 'string' && ZONELESS_ISO_DATETIME_RE.test(date))
+  if (typeof date === 'string' && ZONELESS_ISO_DATETIME_RE.test(date))
     parsed = new Date(`${date}Z`)
   else
     parsed = new Date(date)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function formatUtcDateParam(date: Date | string = new Date()) {
let parsed: Date
if (typeof date === 'string' && DATE_ONLY_RE.test(date))
parsed = new Date(`${date}T00:00:00.000Z`)
else if (typeof date === 'string' && ZONELESS_ISO_DATETIME_RE.test(date))
parsed = new Date(`${date}Z`)
else
parsed = new Date(date)
export function formatUtcDateParam(date: Date | string = new Date()) {
if (typeof date === 'string' && DATE_ONLY_RE.test(date)) {
const parsed = parseUtcRangeBoundary(date)
return parsed ? parsed.toISOString().slice(0, 10) : ''
}
let parsed: Date
if (typeof date === 'string' && ZONELESS_ISO_DATETIME_RE.test(date))
parsed = new Date(`${date}Z`)
else
parsed = new Date(date)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/date.ts` around lines 206 - 213, Update formatUtcDateParam to
validate date-only strings against a real calendar date before constructing the
UTC Date, so values such as 2026-02-30 follow the existing empty invalid-date
fallback instead of being normalized. Add a regression test covering 2026-02-30
and preserve valid date-only formatting.

Comment thread tests/date.unit.test.ts
Comment on lines +143 to +145
it('treats zone-less ISO datetimes as UTC in formatUtcDateParam', () => {
expect(formatUtcDateParam('2026-08-07T15:30:00')).toBe('2026-08-07')
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -HI -t f '^(package\.json|vitest\.config\..*|vite\.config\..*)$' . \
  -x sh -c 'printf "\n### %s\n" "$1"; rg -n -C 3 "vitest|test|TZ" "$1" || true' sh {}

Repository: Cap-go/capgo.app

Length of output: 28473


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '### tests/date.unit.test.ts'
sed -n '1,190p' tests/date.unit.test.ts

printf '%s\n' '### date helpers and usages'
rg -n -C 5 "formatUtcDateParam|formatUtc|DateParam" src tests --glob '*.{ts,tsx,vue}' || true

printf '%s\n' '### timezone-sensitive runtime probe'
TZ=America/Los_Angeles node - <<'JS'
const input = '2026-08-07T23:30:00'
const local = new Date(input)
const utc = new Date(`${input}Z`)
const day = date => date.toISOString().slice(0, 10)
console.log(JSON.stringify({
  timezone: process.env.TZ,
  localISO: local.toISOString(),
  utcISO: utc.toISOString(),
  localDay: day(local),
  utcDay: day(utc),
}))
JS

Repository: Cap-go/capgo.app

Length of output: 24651


Make the zone-less ISO regression test timezone-sensitive.

The current 15:30:00 input does not distinguish UTC parsing from local parsing. Run an equivalent assertion with TZ=America/Los_Angeles and 2026-08-07T23:30:00, expecting 2026-08-07. Do not mutate process.env.TZ inside this suite.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/date.unit.test.ts` around lines 143 - 145, Update the zone-less ISO
regression test for formatUtcDateParam to run under TZ=America/Los_Angeles, use
the timezone-sensitive input 2026-08-07T23:30:00, and continue expecting
2026-08-07. Configure the test command or runner environment rather than
mutating process.env.TZ within the suite.

Source: Coding guidelines

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 15 files (changes from recent commits).

Confidence score: 3/5

  • In src/components/dashboard/DeploymentStatsCard.vue, cache entries are reused across different time windows, so moving from 30-day to longer billing cycles can hide early-cycle deployments and underreport activity — include the queried date range in the cache key or invalidate when the window changes.
  • In src/components/dashboard/BundleUploadsCard.vue, switching from billing-cycle to 30-day mode can reuse broader-window data keyed only by org, which can omit expected earlier days in the new view and mislead trend interpretation — key/invalidate cached rows by both org and active series window.
  • In src/utils/chartOptimizations.ts, rows fetched for one window are reindexed with a different seriesStart, which can shift day buckets and add/drop edge days, producing visibly incorrect daily counts — store and validate cached start/end bounds before remapping chart series.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/components/dashboard/DeploymentStatsCard.vue">

<violation number="1" location="src/components/dashboard/DeploymentStatsCard.vue:140">
P1: Switching from the default 30-day view to a billing cycle longer than 30 days omits early-cycle deployments because the per-org cache is reused despite its narrower query window. Store/query cache coverage with the range or force a refetch when billing mode needs an earlier `seriesStart`.</violation>
</file>

<file name="src/components/dashboard/BundleUploadsCard.vue">

<violation number="1" location="src/components/dashboard/BundleUploadsCard.vue:126">
P1: Switching from billing-cycle to 30-day mode can omit earlier days because cache entries are keyed only by org although this new window changes the query range. Key or invalidate cached rows by series window (and app set), or force a refetch when `useBillingPeriod` changes.</violation>
</file>

<file name="src/utils/chartOptimizations.ts">

<violation number="1" location="src/utils/chartOptimizations.ts:52">
P1: Switching billing mode reuses rows fetched for the prior window but reindexes them using this new `seriesStart`, shifting daily counts (and dropping/adding edge days). Cache the fetched window with its start/end or force a refetch when `useBillingPeriod` changes.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/components/dashboard/LineChartStats.vue
const billingStart = new Date(targetOrganization.subscription_start ?? new Date())
billingStart.setHours(0, 0, 0, 0)
const billingStart = normalizeToUtcStartOfDay(new Date(targetOrganization.subscription_start ?? new Date()))
const { seriesStart: last30DaysStart, exclusiveEnd, dayCount } = resolveDashboardDailySeriesWindow(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Switching from the default 30-day view to a billing cycle longer than 30 days omits early-cycle deployments because the per-org cache is reused despite its narrower query window. Store/query cache coverage with the range or force a refetch when billing mode needs an earlier seriesStart.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/dashboard/DeploymentStatsCard.vue, line 140:

<comment>Switching from the default 30-day view to a billing cycle longer than 30 days omits early-cycle deployments because the per-org cache is reused despite its narrower query window. Store/query cache coverage with the range or force a refetch when billing mode needs an earlier `seriesStart`.</comment>

<file context>
@@ -135,15 +135,16 @@ async function calculateStats(forceRefetch = false) {
-
     // Get billing period dates for filtering
     const billingStart = normalizeToUtcStartOfDay(new Date(targetOrganization.subscription_start ?? new Date()))
+    const { seriesStart: last30DaysStart, exclusiveEnd, dayCount } = resolveDashboardDailySeriesWindow(
+      props.useBillingPeriod,
+      billingStart,
</file context>

billingStart.setHours(0, 0, 0, 0)
const billingStart = normalizeToUtcStartOfDay(new Date(organizationStore.currentOrganization?.subscription_start ?? new Date()))
const { seriesStart: last30DaysStart, exclusiveEnd: last30DaysEnd, dayCount } = resolveDashboardDailySeriesWindow(
props.useBillingPeriod,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Switching from billing-cycle to 30-day mode can omit earlier days because cache entries are keyed only by org although this new window changes the query range. Key or invalidate cached rows by series window (and app set), or force a refetch when useBillingPeriod changes.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/dashboard/BundleUploadsCard.vue, line 126:

<comment>Switching from billing-cycle to 30-day mode can omit earlier days because cache entries are keyed only by org although this new window changes the query range. Key or invalidate cached rows by series window (and app set), or force a refetch when `useBillingPeriod` changes.</comment>

<file context>
@@ -120,12 +120,12 @@ async function calculateStats(forceRefetch = false) {
     // Get billing period dates for filtering
     const billingStart = normalizeToUtcStartOfDay(new Date(organizationStore.currentOrganization?.subscription_start ?? new Date()))
+    const { seriesStart: last30DaysStart, exclusiveEnd: last30DaysEnd, dayCount } = resolveDashboardDailySeriesWindow(
+      props.useBillingPeriod,
+      billingStart,
+    )
</file context>

if (useBillingPeriod && !Number.isNaN(cycleStart.getTime())) {
const elapsedDays = Math.floor((todayUtc.getTime() - cycleStart.getTime()) / DAY_MS)
if (elapsedDays >= 0 && elapsedDays <= 366)
seriesStart = cycleStart

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Switching billing mode reuses rows fetched for the prior window but reindexes them using this new seriesStart, shifting daily counts (and dropping/adding edge days). Cache the fetched window with its start/end or force a refetch when useBillingPeriod changes.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/utils/chartOptimizations.ts, line 52:

<comment>Switching billing mode reuses rows fetched for the prior window but reindexes them using this new `seriesStart`, shifting daily counts (and dropping/adding edge days). Cache the fetched window with its start/end or force a refetch when `useBillingPeriod` changes.</comment>

<file context>
@@ -20,33 +22,62 @@ export function incrementArrayValue(arr: (number | undefined)[], index: number,
+  if (useBillingPeriod && !Number.isNaN(cycleStart.getTime())) {
+    const elapsedDays = Math.floor((todayUtc.getTime() - cycleStart.getTime()) / DAY_MS)
+    if (elapsedDays >= 0 && elapsedDays <= 366)
+      seriesStart = cycleStart
   }
 
</file context>

Comment thread src/components/dashboard/UpdateStatsChart.vue
Import was renamed but two call sites still referenced getDaysInCurrentMonth,
breaking vue-tsc on Lint and typecheck.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr August 8, 2026 17:09 Inactive
@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_aead4611-69cf-4114-a8c7-721bfefff9ba)

@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_ccc84808-3ddd-44cb-a2d4-e24f2b58a032)

@riderx
riderx merged commit f86fa99 into main Aug 8, 2026
78 of 79 checks passed
@riderx
riderx deleted the cursor/dashboard-utc-timezone-1e2d branch August 8, 2026 17:13

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/dashboard/LineChartStats.vue (1)

32-32: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Use the billing-cycle label count for every chart series.

When useBillingPeriod is enabled, monthdays() uses cycleStart and cycleEnd, but projection and annotation calculations still use the calendar month, while cumulative filling uses the local calendar day. Use transformDailySeries or a cycle-relative UTC index. Size all arrays and annotation positions from labels.length. Add a test for a cycle that starts mid-month.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/dashboard/LineChartStats.vue` at line 32, Update the chart
data initialization and related projection, annotation, and cumulative-fill
calculations in LineChartStats.vue to use the billing-cycle label count and
cycle-relative UTC indices whenever useBillingPeriod is enabled, rather than
calendar-month or local-day values. Derive all series array sizes and annotation
positions from labels.length, reusing transformDailySeries where appropriate,
and add coverage for a billing cycle that starts mid-month.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/components/dashboard/LineChartStats.vue`:
- Line 32: Update the chart data initialization and related projection,
annotation, and cumulative-fill calculations in LineChartStats.vue to use the
billing-cycle label count and cycle-relative UTC indices whenever
useBillingPeriod is enabled, rather than calendar-month or local-day values.
Derive all series array sizes and annotation positions from labels.length,
reusing transformDailySeries where appropriate, and add coverage for a billing
cycle that starts mid-month.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 82786bf5-cff5-4444-ba45-50ba0766bddb

📥 Commits

Reviewing files that changed from the base of the PR and between 71e1ce8 and 711bd10.

📒 Files selected for processing (1)
  • src/components/dashboard/LineChartStats.vue
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

@sonarqubecloud

sonarqubecloud Bot commented Aug 8, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants