Skip to content

fix(frontend): clarify channel adoption statistics#1847

Merged
riderx merged 2 commits into
mainfrom
codex/clarify-channel-adoption-stats
Mar 24, 2026
Merged

fix(frontend): clarify channel adoption statistics#1847
riderx merged 2 commits into
mainfrom
codex/clarify-channel-adoption-stats

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented Mar 24, 2026

Summary (AI generated)

  • clarify the channel adoption cards so the latest snapshot and selected period are presented separately
  • replace the ambiguous updated-devices wording with explicit adoption and current-version device counts
  • add period summary cards for period start, change across the selected range, and best day in the range

Motivation (AI generated)

Users were reading the adoption cards as if they all represented the same time scope. The page mixed a latest snapshot number with a chart over a selectable range, which made the values look inconsistent even when the underlying data was correct.

Business Impact (AI generated)

This reduces confusion on a customer-facing analytics page, which should improve trust in Capgo's update adoption reporting and lower support friction around rollout visibility.

Test Plan (AI generated)

  • Open the channel statistics page and verify the latest snapshot cards explain the denominator and scope clearly
  • Switch between 7, 14, and 30 days and verify the selected-period cards update with the chart
  • Confirm the status banner now refers to devices on current version instead of updated devices
  • Note: automated validation was limited in this worktree because repo-local eslint and vue-tsc are not installed

Generated with AI

Summary by CodeRabbit

  • New Features

    • Reorganized channel statistics into two grouped views: latest snapshot metrics and selected-period trends.
    • Default statistics window shortened and quick-period selector updated to show 1, 3, and 7 day options.
    • Added signed change, best-day-in-period, and clearer status labels in overview cards; added chart help text.
  • Documentation

    • Expanded localization strings for adoption, channel stats help, timeframe labels, and snapshot summaries.
  • Chores

    • Tightened backend period bounds to 1–7 days for statistics requests.

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 24, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3549606a-ba9f-45c1-9e56-39d945dc126c

📥 Commits

Reviewing files that changed from the base of the PR and between 3586a38 and a52dfbb.

📒 Files selected for processing (2)
  • src/pages/app/[app].channel.[channel].statistics.vue
  • supabase/functions/_backend/private/channel_stats.ts

📝 Walkthrough

Walkthrough

This PR adds new localization keys for adoption/channel stats, refactors the stats overview UI into "latest snapshot" and "selected period" sections with new formatters and computed properties, and tightens the stats API timeframe defaults and bounds from 14/30 to 3/7 days respectively.

Changes

Cohort / File(s) Summary
Localization Updates
messages/en.json
Added adoption- and channel-stats-related translation keys (start/latest snapshot, period comparison/help, channel-stats-latest-snapshot-help, channel-stats-period-help, change labels with {version}/{start}/{end}, devices on current version/status, timeframe & snapshot labels). Updated channel-stats-help copy.
Statistics Page UI & Logic
src/pages/app/[app].channel.[channel].statistics.vue
Default window changed from 14→3 days; chart period buttons updated to [1,3,7]; added formatters (formatPercent, formatSignedPoints, formatShortDate); new computed props (currentVersionDataset, selectedPeriodLabel, periodSummary); replaced 3-card grid with two sections (latest snapshot & selected period); updated status label token and added channel-stats-help under chart.
Backend Timeframe Enforcement
supabase/functions/_backend/private/channel_stats.ts
Changed default days from 14→3 and clamped allowed range to 1–7 (was 1–30), altering the computed start/end date window used for stats queries and labels.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Frontend
  participant Backend
  participant Database

  User->>Frontend: select period (days = 1|3|7)
  Frontend->>Frontend: update days, compute selectedPeriodLabel
  Frontend->>Backend: fetchStats(days)
  Backend->>Backend: clamp days to [1,7], compute startDate/endDate
  Backend->>Database: query stats between startDate and endDate
  Database-->>Backend: return time-series & metaCounts
  Backend-->>Frontend: return datasets, labels, currentVersion
  Frontend->>Frontend: compute currentVersionDataset, periodSummary
  Frontend-->>User: render latest snapshot & selected period cards, chart, help text
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

enhancement

Poem

🐰 I nibble keys and count the days,

Snapshots hop in bright new ways,
Periods, peaks, and signed-up shares,
Tiny formatters tidy cares,
Hooray — analytics that play!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(frontend): clarify channel adoption statistics' directly describes the main change—improving clarity of adoption statistics presentation on the channel statistics page.
Description check ✅ Passed The description includes a summary, motivation, business impact, and test plan; however, it lacks screenshots and does not fully complete the provided checklist with manual test confirmations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/clarify-channel-adoption-stats

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
src/pages/app/[app].channel.[channel].statistics.vue (3)

667-725: Consider handling null periodSummary more gracefully.

When periodSummary is null (e.g., no data for the current version in the selected period), the "Selected period" cards still render with 0.0% values and - dates. This could confuse users into thinking there's actual zero adoption rather than missing data.

Consider adding a conditional to show a "No period data available" message when periodSummary is null, similar to how the chart handles stats.totals.total_devices === 0.

💡 Suggested approach
+          <div v-if="!periodSummary" class="p-4 text-center text-slate-500 dark:text-slate-400">
+            {{ t('no-data-available') }}
+          </div>
+
+          <div v-else class="grid grid-cols-1 gap-4 sm:grid-cols-3">
-          <div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
             <!-- ... cards ... -->
           </div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/app/`[app].channel.[channel].statistics.vue around lines 667 - 725,
The cards always show zeros when periodSummary is null, which is misleading;
update the template around selectedPeriodLabel to check periodSummary and, if
null, render a single centered "No period data available" message (or similar)
instead of the three metric cards; otherwise render the existing card group that
uses periodSummary?.startShare, periodSummary?.changeShare,
periodSummary?.peakShare and helpers formatPercent/formatSignedPoints and
stats.currentVersion as before. Ensure the conditional uses the same truthiness
check the chart uses (e.g., periodSummary === null or periodSummary?.startCount
=== undefined) so the UI consistently hides metrics when no period data exists.

268-269: Optional: Redundant length check.

The check if (normalizedShares.length === 0) at line 268 is unreachable because labels.length === 0 already returns null at line 253, and normalizedShares is derived from labels.map(...).

♻️ Remove redundant check
   const normalizedCounts = labels.map((_, index) => {
     const rawValue = dataset.metaCounts?.[index]
     const numeric = typeof rawValue === 'number' ? rawValue : Number(rawValue)
     return Number.isFinite(numeric) ? Math.max(0, Math.round(numeric)) : 0
   })

-  if (normalizedShares.length === 0)
-    return null
-
   const startShare = normalizedShares[0] ?? 0
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/app/`[app].channel.[channel].statistics.vue around lines 268 - 269,
The guard `if (normalizedShares.length === 0) return null` is redundant because
`labels.length === 0` already returns null earlier and `normalizedShares` is
derived from `labels.map(...)`; remove that unreachable check (the
`normalizedShares` length check) to simplify the control flow while keeping the
existing early-return on `labels.length === 0` intact — search for `labels`,
`normalizedShares`, and the `labels.length === 0` return to locate and remove
the redundant `normalizedShares` check.

221-227: Minor: formatSignedPoints(0) will display "+0.0 pts".

The condition value > 0 means exactly zero gets a + prefix, resulting in "+0.0 pts". This is likely unintentional from a UX perspective.

💡 Suggested fix to show "0.0 pts" for zero
 function formatSignedPoints(value: number) {
   if (!Number.isFinite(value))
-    return `0.0 ${t('points-short')}`
+    return '-'

-  const sign = value > 0 ? '+' : ''
+  const sign = value > 0 ? '+' : value < 0 ? '' : ''
   return `${sign}${value.toFixed(1)} ${t('points-short')}`
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/app/`[app].channel.[channel].statistics.vue around lines 221 - 227,
formatSignedPoints currently can prefix zero with a plus; update the sign logic
in function formatSignedPoints so zero shows no "+": compute sign as an explicit
three-way check (if value === 0 -> '', else if value > 0 -> '+', else -> ''),
then return `${sign}${value.toFixed(1)} ${t('points-short')}` so negatives keep
their built-in "-" from toFixed and zero is "0.0 pts".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/pages/app/`[app].channel.[channel].statistics.vue:
- Around line 667-725: The cards always show zeros when periodSummary is null,
which is misleading; update the template around selectedPeriodLabel to check
periodSummary and, if null, render a single centered "No period data available"
message (or similar) instead of the three metric cards; otherwise render the
existing card group that uses periodSummary?.startShare,
periodSummary?.changeShare, periodSummary?.peakShare and helpers
formatPercent/formatSignedPoints and stats.currentVersion as before. Ensure the
conditional uses the same truthiness check the chart uses (e.g., periodSummary
=== null or periodSummary?.startCount === undefined) so the UI consistently
hides metrics when no period data exists.
- Around line 268-269: The guard `if (normalizedShares.length === 0) return
null` is redundant because `labels.length === 0` already returns null earlier
and `normalizedShares` is derived from `labels.map(...)`; remove that
unreachable check (the `normalizedShares` length check) to simplify the control
flow while keeping the existing early-return on `labels.length === 0` intact —
search for `labels`, `normalizedShares`, and the `labels.length === 0` return to
locate and remove the redundant `normalizedShares` check.
- Around line 221-227: formatSignedPoints currently can prefix zero with a plus;
update the sign logic in function formatSignedPoints so zero shows no "+":
compute sign as an explicit three-way check (if value === 0 -> '', else if value
> 0 -> '+', else -> ''), then return `${sign}${value.toFixed(1)}
${t('points-short')}` so negatives keep their built-in "-" from toFixed and zero
is "0.0 pts".

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 53cd33ba-fb72-400b-8287-c99e2b24ff88

📥 Commits

Reviewing files that changed from the base of the PR and between 25057d4 and 3586a38.

📒 Files selected for processing (2)
  • messages/en.json
  • src/pages/app/[app].channel.[channel].statistics.vue

@riderx riderx merged commit 81cf923 into main Mar 24, 2026
12 of 13 checks passed
@riderx riderx deleted the codex/clarify-channel-adoption-stats branch March 24, 2026 13:24
@sonarqubecloud
Copy link
Copy Markdown

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant