Skip to content
AzuAzu

Trends

“Is revenue going up?” needs a line, not a number. A trend is a widget that counts along a date column in buckets.

app/admin/screens/overview.ts (part)
// A trend (FR-25), full width: days for 30 days, hours today, months
// for the year, against the period before
metric
.trend('Revenue over time')
.sum(orders, 'total')
.where((query) => query.whereIn('status', SOLD))
.date('placedAt')
.format('currency', 'NGN')
.compare(),

date() is required on a trend. Everything else in Widgets about aggregates, access, ranges, and formats applies.

The bucket follows the screen’s range:

Range Bucket
today hours
7d, 30d, 90d, month days
quarter weeks
year months

.by('hour' | 'day' | 'week' | 'month') fixes it instead, up to 100 buckets.

Buckets are in the panel’s timezone. Weeks start on Monday. Days across a clock change are 23 or 25 hours.

Note: azu:doctor reports a by() that can need more than 100 buckets in one of the screen’s ranges.

  • It’s a line by default, or bars with .bars().
  • .compare() adds the previous period as a muted line.
  • .lowerIsBetter() works as it does on values.
  • It spans the whole grid by default.
  • Hover or focus the chart for each bucket’s value.
  • Use the arrow keys to move between buckets.
  • Press Enter or click to open the list, filtered to that day, week, or month.
  • “View as table” shows the numbers.

These figures are p95, on 100,000 orders on Postgres, with an index on placed_at. The demo’s revenue trend with compare() takes 59 ms over 90 days by day. Over a year by month, it takes 26 ms.