feat(frontend/dashboard): Potential Monthly Savings card mirrors Recommendations-page range · Issue #293 · LeanerCloud/cloud-commitments-cli · GitHub
Skip to content

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

Closed

Description

@cristim

Problem

PR #283 closed #279 by making every summary card on the
Recommendations page render a per-cell range (savings, upfront,
payback) and narrow on selection. The Dashboard view's "Potential
Monthly Savings" card (frontend/src/dashboard.ts:128) still renders
the flat summary.potential_monthly_savings from
/api/dashboard/summary — the same overcounting bug class #272 closed
on the Recommendations page (sums every variant of every cell, ~6×
overstates achievable totals).

Splitting this out of #279 because the Dashboard work is structurally
different from the Recommendations-page work that's already shipped:
it's a separate page, has no per-row selection state to narrow on, and
needs either a backend /dashboard/summary extension or a frontend
extra-fetch to source the per-cell range data.

Acceptance criteria

  • Dashboard's "Potential Monthly Savings" card renders the same
    per-cell range that the Recommendations page card does
    (pageLevelRange(groupRecsByCell(recs)).savingsMin /
    .savingsMax).
  • Implementation: frontend-only — dashboard.ts::loadDashboard
    fetches /api/recommendations alongside the existing
    /api/dashboard/summary + /api/upcoming calls, computes the range
    client-side using the existing pageLevelRange /
    groupRecsByCell helpers exported from recommendations.ts. The
    recs endpoint is served from Postgres cache so the extra API call
    is cheap. Backend change deferred — a future PR can move the range
    computation server-side if needed.
  • No selection narrowing on Dashboard — Dashboard is a read-only
    view, no checkboxes. Card always reflects the range across whatever
    recommendations the user's current provider/account filter exposes.
  • Other Dashboard cards (Active Commitments, Current Coverage,
    YTD Savings) keep their existing API-driven values — they're
    aggregates that don't have the variant-fan-out overcounting issue.
  • If /api/recommendations fails, the Dashboard still renders —
    the savings card falls back to formatCurrency(0) and the rest of
    the dashboard is unaffected (independent loaders).
  • Tests:
    • dashboard.test.ts (or wherever dashboard tests live): assert
      the savings card renders the range when recs are mocked.
    • Failure-isolation: when getRecommendations rejects, the other
      cards still render.

References

Activity

  1. added a commit that references this issue on May 5, 2026
    e4a52f9
  2. cristim commented on May 14, 2026

    @cristim
    MemberAuthor

    Already implemented and shipped on feat/multicloud-web-frontend via PR #295 (merged 2026-05-05, commit e4a52f9).

    Verification against the acceptance criteria:

    • Dashboard's Potential Monthly Savings card renders the per-cell range — frontend/src/dashboard.ts renderDashboardSummary calls groupRecsByCell + pageLevelRange + formatSavingsRange on the recs fetched alongside the summary.
    • Frontend-only: loadDashboard fetches /api/recommendations concurrently with /api/dashboard/summary and /api/upcoming via Promise.allSettled.
    • No selection narrowing — the dashboard has no checkboxes; the card reflects the range across the current provider/account filter.
    • Other cards (Active Commitments, Current Coverage, YTD Savings) keep their existing API-driven values.
    • Failure isolation — when getRecommendations rejects, the savings card falls back to formatCurrency(0) and the rest of the dashboard renders.
    • Tests in frontend/src/__tests__/dashboard.test.ts:
      • Potential Monthly Savings card renders per-cell range (#293) (line 514)
      • failure-isolation: rec fetch failure leaves other cards rendered (#293) (line 547)
      • legacy summary.potential_monthly_savings is no longer read for the savings card (#293) (line 577)

    The reused helpers (pageLevelRange, groupRecsByCell, formatSavingsRange) are exported from frontend/src/recommendations.ts (lines 473, 570, 689 on the current tip of base).

    Issue stayed open because GitHub's auto-close keyword only fires when the PR merges into the default branch; PR #295 merged into the long-lived feat/multicloud-web-frontend branch. Closing now.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions