feat(frontend/dashboard): Potential Monthly Savings card mirrors Recommendations-page range (closes #293) by cristim · Pull Request #295 · LeanerCloud/cloud-commitments-cli · GitHub
Skip to content

feat(frontend/dashboard): Potential Monthly Savings card mirrors Recommendations-page range (closes #293) - #295

Merged
cristim merged 1 commit into
feat/multicloud-web-frontendfrom
feat/dashboard-savings-range-293
May 5, 2026
Merged

cristim merged 1 commit into
feat/multicloud-web-frontendfrom
feat/dashboard-savings-range-293

Conversation

@cristim

@cristim cristim commented May 5, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Dashboard's "Potential Monthly Savings" card was showing summary.potential_monthly_savings — a flat sum across every variant of every cell that overstates achievable savings by ~6x (same bug class as ux(frontend/recs): Potential Monthly Savings card sums all variants — should mirror Recommended range #272 on the Recommendations page)
  • Fix: loadDashboard now fetches /api/recommendations concurrently alongside the existing summary + upcoming calls, computes the per-cell range client-side using groupRecsByCell / pageLevelRange / formatSavingsRange (same helpers the Recommendations page uses), and renders savingsMin – savingsMax on the card
  • formatSavingsRange is exported from recommendations.ts to enable reuse

Behaviour change

Before: $X where X is the sum of every variant of every cell (overcounted)
After: $min – $max (or $X if min == max) — matches the Recommendations-page card

Implementation notes

  • Frontend-only: /api/dashboard/summary is left unchanged. A future backend PR can move range computation server-side
  • Failure isolation via Promise.allSettled: if /api/recommendations fails, the savings card falls back to $0; Active Commitments, Current Coverage, YTD Savings still render from the summary response
  • No selection narrowing on Dashboard — Dashboard is read-only (no checkboxes), card always reflects the full range

Test plan

  • npm run typecheck — clean
  • npm test -- --testPathPattern=dashboard — 21/21 pass (+3 new tests)
    • Potential Monthly Savings card renders per-cell range (#293) — asserts range shown, flat sum NOT shown
    • failure-isolation: rec fetch failure leaves other cards rendered (#293) — asserts other cards intact, savings falls back to $0
    • legacy summary.potential_monthly_savings is no longer read for the savings card (#293) — asserts $700 summary value not shown when recs give $300-$400
  • Full suite — 1464/1464 pass

Summary by CodeRabbit

  • New Features

    • Dashboard now derives "Potential Monthly Savings" from recommendation data for more accurate calculations.
    • Dashboard continues to display all cards even if recommendation data fails to load.
  • Tests

    • Added tests to verify savings calculations and dashboard resilience when recommendations are unavailable.

…mmendations-page range (closes #293)

Dashboard's "Potential Monthly Savings" card previously read
summary.potential_monthly_savings — a flat sum across every variant of
every cell that overstates achievable savings by ~6x (the same bug class
#272 closed on the Recommendations page).

Frontend-only fix: loadDashboard now fetches /api/recommendations
concurrently alongside /api/dashboard/summary and /api/upcoming via
Promise.allSettled (failure of any individual fetch is isolated — the
dashboard still renders with graceful fallbacks). The per-cell range is
computed client-side via the existing groupRecsByCell / pageLevelRange /
formatSavingsRange helpers already used by the Recommendations page.
formatSavingsRange is newly exported from recommendations.ts to enable reuse.

If getRecommendations fails, the savings card falls back to $0 and the
other three cards (Active Commitments, Current Coverage, YTD Savings)
render normally from the summary response.

The backend change to /dashboard/summary is deferred; a future PR can
move the range computation server-side if needed.
@coderabbitai

coderabbitai Bot commented May 5, 2026 •

Copy link
Copy Markdown
Contributor

@cristim cristim added triaged Item has been triaged priority/p2 Backlog-worthy severity/medium Moderate harm urgency/this-sprint Within the current sprint impact/many Affects most users effort/s Hours type/feat New capability labels May 5, 2026
@cristim

cristim commented May 5, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

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

Labels

effort/s Hours impact/many Affects most users priority/p2 Backlog-worthy severity/medium Moderate harm triaged Item has been triaged type/feat New capability urgency/this-sprint Within the current sprint

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant