Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions frontend/src/__tests__/savings-history.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ describe('Savings History Module', () => {
<p class="help-text">Data will be collected hourly once you have active purchases.</p>
</div>
<div id="savings-stats">
<h4 id="period-savings-label">Period Savings</h4>
<span id="period-savings">$0</span>
<p id="period-savings-unit">shown in monthly equivalents</p>
<h4 id="avg-savings-label">Avg Monthly Savings</h4>
<span id="avg-hourly-savings">$0/mo</span>
<span id="peak-savings">$0/mo</span>
Expand Down Expand Up @@ -1278,21 +1280,24 @@ describe('Savings History Module', () => {
test('period savings (cumulative total) also converts with unit toggle', async () => {
(getSavingsAnalytics as jest.Mock).mockResolvedValue(mockData);

// Monthly
// Monthly: value is clean dollar total; sub-line reflects view mode
await loadSavingsHistory();
const periodElMonthly = document.getElementById('period-savings');
expect(periodElMonthly?.textContent).toBe('$730.00');
expect(document.getElementById('period-savings-unit')?.textContent).toContain('monthly');

// Hourly: 730 / 730 = 1.00
// Hourly: 730 / 730 = 1.00; sub-line updates to 'hourly'
const unitSelect = document.getElementById('savings-unit') as HTMLSelectElement;
unitSelect.value = 'hourly';
await loadSavingsHistory();
expect(document.getElementById('period-savings')?.textContent).toBe('$1.00');
expect(document.getElementById('period-savings-unit')?.textContent).toContain('hourly');

// Yearly: 730 * 12 = 8760 -> $8.76K
// Yearly: 730 * 12 = 8760 -> $8.76K; sub-line updates to 'yearly'
unitSelect.value = 'yearly';
await loadSavingsHistory();
expect(document.getElementById('period-savings')?.textContent).toBe('$8.76K');
expect(document.getElementById('period-savings-unit')?.textContent).toContain('yearly');
});

test('chart tooltip uses selected unit suffix for period savings dataset', async () => {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,9 @@ <h2>Savings History</h2>
<!-- Savings Stats Cards -->
<div id="savings-stats" class="stats-grid">
<div class="stat-card">
<h4>Period Savings</h4>
<h4 id="period-savings-label">Period Savings</h4>
<p id="period-savings" class="stat-value">$0.00</p>
<p class="stat-unit-context" id="period-savings-unit">shown in monthly equivalents</p>
</div>
<div class="stat-card">
<h4 id="avg-savings-label">Avg Monthly Savings</h4>
Expand Down
15 changes: 14 additions & 1 deletion frontend/src/modules/savings-history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,13 @@ function getPeriodDates(period: string): { start: Date; end: Date; interval: 'ho
*/
function renderSavingsStats(data: SavingsAnalyticsResponse): void {
const periodSavingsEl = document.getElementById('period-savings');
// The unit indicator belongs below the value, not inside the label.
// Period Savings is a cumulative dollar total over the selected date range,
// not a per-unit rate -- the label stays plain ("Period Savings") and the
// sub-line (#period-savings-unit) shows which view mode is active without
// implying a rate.
const periodSavingsLabelEl = document.getElementById('period-savings-label');
const periodSavingsUnitEl = document.getElementById('period-savings-unit');
const avgSavingsEl = document.getElementById('avg-hourly-savings');
const peakSavingsEl = document.getElementById('peak-savings');
const avgLabelEl = document.getElementById('avg-savings-label');
Expand Down Expand Up @@ -289,7 +296,13 @@ function renderSavingsStats(data: SavingsAnalyticsResponse): void {
if (periodSavingsEl) {
// Period Savings is the cumulative total over the selected date range
// (no per-unit rate suffix -- it is already a dollar total).
periodSavingsEl.textContent = formatCurrency(displayTotal) + ' ' + suffix;
periodSavingsEl.textContent = formatCurrency(displayTotal);
}
if (periodSavingsLabelEl) {
periodSavingsLabelEl.textContent = 'Period Savings';
}
if (periodSavingsUnitEl) {
periodSavingsUnitEl.textContent = `shown in ${adjective.toLowerCase()} equivalents`;
}
if (avgLabelEl) {
avgLabelEl.textContent = `Avg ${adjective} Savings`;
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/styles/charts.css
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,9 @@
font-weight: var(--cudly-fw-bold);
color: var(--cudly-primary);
}

.stat-unit-context {
font-size: 0.85rem;
color: var(--cudly-text-muted);
margin-top: 0.25rem;
}
Loading