mirror of
https://github.com/vernu/textbee.git
synced 2026-07-30 17:07:46 -04:00
The home page was four all-time counters that could not answer either question a user actually opens the dashboard for: how much quota is left, and did my recent sends work. Removed fabricated data: - Every stat card rendered a green TrendingUp arrow whenever a value existed. Nothing computed a trend. The stats endpoint returns running totals with no time window, so there was nothing to compare against. - "Since last year" on the sent and received counts. getStatsForUser sums device counters with no date filter, so these are all-time totals. - "Active Devices" with a "Connected now" caption, over a number that counts every device including disabled ones. Enabled count is now derived from the device list we already fetch. - "Active keys" over a count that included revoked keys; now uses the active API key list. Added, all from fields the API already returns: - Usage cards leading the page: today and this month against their limits, with progress bars, an amber near-limit state past 80% and an upgrade link. Unlimited plans (-1) show usage with no meter, since there is no ceiling to measure against. - Recent activity: the last 5 messages for the connected device. Messages are only exposed per device, so the card names the device rather than implying account-wide coverage. - All-time totals compacted from four large cards into one honest strip. lib/usage.ts extracts the daily/monthly derivation that subscription-info already did inline, so the dashboard and billing page cannot disagree about remaining quota. Unit tested including the -1 sentinel, custom limit overrides, and an over-100 percentage (possible when a limit is lowered mid-period). No backend changes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
86 lines
2.4 KiB
TypeScript
86 lines
2.4 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { deriveUsage, UNLIMITED } from './usage'
|
|
|
|
describe('deriveUsage', () => {
|
|
it('reads the daily and monthly windows from usage', () => {
|
|
const { daily, monthly } = deriveUsage({
|
|
plan: { dailyLimit: 500, monthlyLimit: 5000 },
|
|
usage: {
|
|
dailyLimit: 500,
|
|
monthlyLimit: 5000,
|
|
processedSmsToday: 47,
|
|
processedSmsLastMonth: 1204,
|
|
dailyRemaining: 453,
|
|
monthlyRemaining: 3796,
|
|
dailyUsagePercentage: 9,
|
|
monthlyUsagePercentage: 24,
|
|
},
|
|
})
|
|
|
|
expect(daily.used).toBe(47)
|
|
expect(daily.limit).toBe(500)
|
|
expect(daily.remaining).toBe(453)
|
|
expect(daily.percentage).toBe(9)
|
|
expect(daily.unlimited).toBe(false)
|
|
|
|
expect(monthly.used).toBe(1204)
|
|
expect(monthly.percentage).toBe(24)
|
|
})
|
|
|
|
it('treats -1 as unlimited and suppresses the percentage', () => {
|
|
const { daily } = deriveUsage({
|
|
plan: { dailyLimit: UNLIMITED },
|
|
usage: { dailyLimit: UNLIMITED, processedSmsToday: 900 },
|
|
})
|
|
|
|
expect(daily.unlimited).toBe(true)
|
|
expect(daily.percentage).toBe(0)
|
|
expect(daily.nearLimit).toBe(false)
|
|
expect(daily.atLimit).toBe(false)
|
|
// Usage is still reported, there is just nothing to measure it against.
|
|
expect(daily.used).toBe(900)
|
|
})
|
|
|
|
it('prefers usage limits over plan limits (custom overrides)', () => {
|
|
const { daily } = deriveUsage({
|
|
plan: { dailyLimit: 50 },
|
|
usage: { dailyLimit: 5000, processedSmsToday: 100 },
|
|
})
|
|
|
|
expect(daily.limit).toBe(5000)
|
|
})
|
|
|
|
it('flags the near-limit threshold', () => {
|
|
const { daily } = deriveUsage({
|
|
usage: { dailyLimit: 100, processedSmsToday: 85, dailyUsagePercentage: 85 },
|
|
})
|
|
|
|
expect(daily.nearLimit).toBe(true)
|
|
expect(daily.atLimit).toBe(false)
|
|
})
|
|
|
|
it('flags being at the limit and clamps an over-100 percentage', () => {
|
|
// Happens when a limit is lowered mid-period.
|
|
const { daily } = deriveUsage({
|
|
usage: {
|
|
dailyLimit: 100,
|
|
processedSmsToday: 150,
|
|
dailyUsagePercentage: 150,
|
|
},
|
|
})
|
|
|
|
expect(daily.percentage).toBe(100)
|
|
expect(daily.atLimit).toBe(true)
|
|
expect(daily.nearLimit).toBe(false)
|
|
})
|
|
|
|
it('is safe on an undefined subscription', () => {
|
|
const { daily, monthly } = deriveUsage(undefined)
|
|
|
|
expect(daily.used).toBe(0)
|
|
expect(daily.limit).toBeUndefined()
|
|
expect(daily.unlimited).toBe(false)
|
|
expect(monthly.used).toBe(0)
|
|
})
|
|
})
|