Skip to contentVibraUI

Global headline

Sessions over the last day, the countries they came from, p95 response weighted by where the traffic was, and booked revenue across the paid orders; reads globalStats().

Preview

Install

npx shadcn@latest add @vibra/widget-saas-global-global-stats

Needs the @vibra registry in your components.json — set it up once.

Source

app/saas/global/components/global-stats.tsx
import { BanknoteIcon, GaugeIcon, MapPinnedIcon, UsersIcon } from "lucide-react"

import { formatCurrency, formatNumber } from "@/lib/format"
import { StatCard } from "@/components/ui/stat-card"
import { StatCardGroup } from "@/components/ui/stat-card-group"

import { type GlobalStat } from "../data"

// One icon per headline, keyed by the stat rather than its position, so the row
// can be reordered without the icons following the wrong numbers.
const ICONS: Record<string, React.ReactNode> = {
  sessions: <UsersIcon />,
  countries: <MapPinnedIcon />,
  p95: <GaugeIcon />,
  revenue: <BanknoteIcon />,
}

function print(stat: GlobalStat): string {
  if (stat.format === "currency")
    return formatCurrency(stat.value, "USD", { maximumFractionDigits: 0 })
  if (stat.format === "duration") return `${formatNumber(stat.value, { maximumFractionDigits: 0 })} ms`
  return formatNumber(stat.value, { maximumFractionDigits: 0 })
}

/** How much traffic, from how many places, how fast, and worth how much. */
export function GlobalStats({ stats }: { stats: GlobalStat[] }) {
  return (
    <StatCardGroup data-widget="widget-saas-global-global-stats" columns={4}>
      {stats.map((stat) => (
        <StatCard
          key={stat.key}
          label={stat.label}
          value={print(stat)}
          description={stat.description}
          icon={ICONS[stat.key]}
        />
      ))}
    </StatCardGroup>
  )
}
app/saas/global/data.ts
/**
 * What /global reads. Traffic is `db.sessions` — one row per country per hour
 * over the last day, each carrying where the country is — and money is
 * `db.orders`, joined to `db.customers` for the account behind an order. The
 * region an order belongs to is not a column on the order: it is the region the
 * session rows already record for that country, so the two halves of the page
 * agree by construction rather than by a second list written by hand. Nothing
 * reads a clock: the window ends at REFERENCE_DATE.
 */
import { getInitials } from "@/lib/format"
import {
  db,
  REFERENCE_DATE,
  type Member,
  type Order,
  type Session,
} from "@/lib/sample-data"

// The sessions are a read-only day of traffic. The orders and the accounts are
// read per call, never held at module scope: a sale rung up or refunded since
// the server started is in the next render's figures.
const SESSIONS = db.sessions.all()
const orders = (): Order[] => db.orders.all()

/** How many hours of traffic the page covers. */
export const WINDOW_HOURS = 24

const dollars = (cents: number): number => cents / 100

/** An order counts towards revenue once it is paid and until it is refunded. */
const billable = (order: Order): boolean =>
  order.status === "paid" || order.status === "fulfilled"

type Place = { country: string; region: Session["region"]; lat: number; lng: number }

// One entry per country, folded out of the hourly rows: every hour of a country
// carries the same place, so the first one seen settles it.
const PLACES = new Map<string, Place>()
for (const row of SESSIONS) {
  if (!PLACES.has(row.country)) {
    PLACES.set(row.country, { country: row.country, region: row.region, lat: row.lat, lng: row.lng })
  }
}

/** The region a country trades in, read off the traffic rather than a second list. */
export function regionOf(country: string): string {
  return PLACES.get(country)?.region ?? "Rest of world"
}

export type CountryTraffic = {
  country: string
  region: string
  lat: number
  lng: number
  sessions: number
  /** Sessions weighted p95, in milliseconds. */
  p95Ms: number
  errorRate: number
}

// Every country's day, rolled up once: sessions summed, and latency and errors
// weighted by the sessions behind them — an hour with 12 sessions cannot pull
// the day's p95 as hard as one with 900.
const BY_COUNTRY: CountryTraffic[] = [...PLACES.values()]
  .map((place) => {
    const hours = SESSIONS.filter((row) => row.country === place.country)
    const sessions = hours.reduce((total, row) => total + row.sessions, 0)
    const weighted = (read: (row: Session) => number) =>
      sessions === 0
        ? 0
        : hours.reduce((total, row) => total + read(row) * row.sessions, 0) / sessions

    return {
      country: place.country,
      region: place.region,
      lat: place.lat,
      lng: place.lng,
      sessions,
      p95Ms: Math.round(weighted((row) => row.p95Ms)),
      errorRate: weighted((row) => row.errorRate),
    }
  })
  .sort((a, b) => b.sessions - a.sessions)

/** Every country's day, busiest first. */
export function countryTraffic(): CountryTraffic[] {
  return BY_COUNTRY
}

export type MapMarker = { id: string; lat: number; lng: number; value: number; label: string }

/** The same rows as markers, which is all the map needs. */
export function mapMarkers(): MapMarker[] {
  return BY_COUNTRY.map((row) => ({
    id: row.country,
    lat: row.lat,
    lng: row.lng,
    value: row.sessions,
    label: row.country,
  }))
}

export type GlobalStat = {
  key: string
  label: string
  value: number
  description: string
  format: "number" | "currency" | "duration" | "percent"
}

const TOTAL_SESSIONS = BY_COUNTRY.reduce((total, row) => total + row.sessions, 0)

/** The four headline numbers: how much traffic, from how far, how fast, worth how much. */
export function globalStats(): GlobalStat[] {
  const p95 =
    TOTAL_SESSIONS === 0
      ? 0
      : BY_COUNTRY.reduce((total, row) => total + row.p95Ms * row.sessions, 0) / TOTAL_SESSIONS
  const paid = orders().filter(billable)
  const revenue = paid.reduce((total, order) => total + order.totalCents, 0)

  return [
    {
      key: "sessions",
      label: "Sessions",
      value: TOTAL_SESSIONS,
      description: `in the last ${WINDOW_HOURS} hours`,
      format: "number",
    },
    {
      key: "countries",
      label: "Countries",
      value: BY_COUNTRY.length,
      description: `led by ${BY_COUNTRY[0]?.country ?? "nowhere"}`,
      format: "number",
    },
    {
      key: "p95",
      label: "p95 response",
      value: Math.round(p95),
      description: "weighted by where the traffic came from",
      format: "duration",
    },
    {
      key: "revenue",
      label: "Booked revenue",
      value: Math.round(dollars(revenue)),
      description: `across ${paid.length} paid orders`,
      format: "currency",
    },
  ]
}

export type RegionRevenue = { region: string; revenue: number }

const REGION_ORDER = ["Americas", "EMEA", "APAC", "Rest of world"]

/** Booked value per region, in the order a reader reads a map. */
export function revenueByRegion(): RegionRevenue[] {
  const totals = new Map<string, number>()
  for (const order of orders()) {
    if (!billable(order)) continue
    const region = regionOf(order.country)
    totals.set(region, (totals.get(region) ?? 0) + order.totalCents)
  }

  return REGION_ORDER.filter((region) => totals.has(region)).map((region) => ({
    region,
    revenue: Math.round(dollars(totals.get(region) ?? 0)),
  }))
}

export type OrderRow = {
  id: string
  number: string
  account: string
  country: string
  region: string
  status: Order["status"]
  total: number
  placedAt: Date
}

/** How many of the newest orders the table shows. */
const RECENT = 8

/** The newest orders, wherever they came from. */
export function recentOrders(): OrderRow[] {
  const accounts = new Map(db.customers.all().map((customer) => [customer.id, customer]))
  return orders()
    .sort((a, b) => b.placedAt.getTime() - a.placedAt.getTime())
    .slice(0, RECENT)
    .map((order) => ({
      id: order.id,
      number: order.number,
      // A sale the till rang up for nobody in particular has no account.
      account: accounts.get(order.customerId)?.company ?? (order.customerId || "Walk-in"),
      country: order.country,
      region: regionOf(order.country),
      status: order.status,
      total: dollars(order.totalCents),
      placedAt: order.placedAt,
    }))
}

/** The bell's contents: the newest notifications, unread first in the panel. */
export function shellNotifications() {
  return db.notifications
    .all()
    .sort((a, b) => b.at.getTime() - a.at.getTime())
    .slice(0, 6)
    .map(({ id, title, description, at, read, href }) => ({ id, title, description, at, read, href }))
}

function ownerRow(): Member {
  return db.members.all().find((member) => member.role === "owner") ?? db.members.all()[0]
}

/** The person looking at the page: whoever owns this workspace. */
export function currentUser() {
  const owner = ownerRow()
  return { name: owner.name, email: owner.email, initials: getInitials(owner.name), avatarUrl: owner.avatarUrl }
}

const STAMP = new Intl.DateTimeFormat("en-US", {
  month: "short",
  day: "numeric",
  hour: "2-digit",
  minute: "2-digit",
  timeZone: "UTC",
})

/** The window the traffic covers, as a line under the title. */
export function lastUpdated(): string {
  return `${WINDOW_HOURS} hours to ${STAMP.format(REFERENCE_DATE)} UTC`
}

Its page

On its page the card sits among the rest of the dashboard and shares its range and its data with them.

From the Global analytics dashboard page