Skip to content

Latest commit

 

History

History
206 lines (156 loc) · 5.76 KB

File metadata and controls

206 lines (156 loc) · 5.76 KB

API Usage & Billing Dashboard

React 19 + TypeScript + Vite (rolldown-vite@7.2.2) + SWC

A demo internal tool for an AI API startup to track customer usage, monitor costs, and manage billing.

Environment

  • Node: >=22.12.0
  • Package Manager: pnpm >=8.0.0 (required)
  • Install: pnpm install
  • Dev: major app start

Resource Clients

CRITICAL: All resource access MUST go through auto-generated clients from @major-tech/resource-client.

Using Generated Clients

Import and use the auto-generated clients from /src/clients/:

import { demoDbClient } from './clients';

const result = await demoDbClient.invoke(
  'SELECT * FROM customers WHERE plan_tier = $1',
  ['enterprise'],
  'fetch-enterprise-customers'
);

if (result.ok) {
  console.log(result.result.rows);
}

Database Schema (Demo DB - READ ONLY)

Tables

  • customers - Customer information
  • models - AI models available via API
  • api_keys - Customer API keys
  • usage_events - Individual API call events
  • invoices - Generated invoices

Views (use these for aggregated queries)

  • daily_usage_summary - Pre-aggregated daily usage per customer/model
  • customer_overview - Customer summary with total usage
  • model_usage_stats - Model popularity and revenue

Important Notes

  • Database credentials are READ-ONLY
  • All mutations (invoices, alerts) are simulated in the frontend
  • Data contains last 90 days of usage events

UI Components

shadcn/ui: Use exclusively for all UI components.

Install new components:

pnpm dlx shadcn@latest add [component-name]

Already installed: button, card, badge, input, select, popover, calendar, dropdown-menu, dialog, table, skeleton, separator, tooltip, command, scroll-area, switch, checkbox

Architecture

src/
├── actions/          # All database queries (REQUIRED for DB access)
│   ├── kpi.actions.ts
│   ├── chart.actions.ts
│   ├── table.actions.ts
│   └── filter.actions.ts
├── components/
│   ├── ui/           # shadcn/ui components (auto-generated)
│   └── dashboard/    # Dashboard components
│       ├── charts/   # Recharts visualizations
│       ├── filters/  # Filter bar components
│       ├── table/    # TanStack Table implementation
│       └── actions/  # Simulated action modals
├── hooks/            # Custom React hooks
├── lib/              # Utilities, formatters, constants
├── providers/        # React context providers
└── types/            # TypeScript type definitions

Key Libraries

Library Purpose
@tanstack/react-query Data fetching & caching
@tanstack/react-table Headless table with pagination
recharts Charts (Area, Pie, Bar, Line)
date-fns Date formatting & manipulation
lucide-react Icons
zod Schema validation

Developing

Run the app

pnpm install
major app start

Lint before committing

pnpm lint

Adding new data queries

  1. Create query function in /src/actions/:
// src/actions/my-feature.actions.ts
import { demoDbClient } from '@/clients';

export async function fetchMyData(param: string) {
  const sql = `SELECT * FROM my_table WHERE column = $1`;
  const result = await demoDbClient.invoke(sql, [param], 'fetch-my-data');

  if (!result.ok) {
    throw new Error(result.error.message);
  }

  return result.result.rows;
}
  1. Use with TanStack Query in components:
const { data, isLoading } = useQuery({
  queryKey: ['my-data', param],
  queryFn: () => fetchMyData(param),
});

Adding new UI components

  1. Install from shadcn:
pnpm dlx shadcn@latest add [component]
  1. Import from @/components/ui/[component]

Adding new charts

Use Recharts components. See existing examples in /src/components/dashboard/charts/:

  • UsageOverTimeChart.tsx - Stacked area chart
  • RevenueByModelChart.tsx - Pie/donut chart
  • TopCustomersChart.tsx - Horizontal bar chart
  • SuccessRateSparkline.tsx - Mini line chart

Filter URL State

Filters sync to URL for shareable links. Use useFilterState hook:

const { filters, setDateRange, setPlanTiers } = useFilterState();

Demo Mode Actions

Since the database is read-only, these actions are simulated:

  • Generate Invoice - Creates fake invoice in local state
  • Send Alert - Shows success toast (no actual email)
  • Flag for Review - Toggles local flag state
  • Export CSV - Real functionality (client-side generation)

All simulated actions show "Demo Mode" indicators.

Extending the Dashboard

Add a new KPI card

  1. Add query to src/actions/kpi.actions.ts
  2. Add card to src/components/dashboard/KpiSection.tsx

Add a new chart

  1. Create chart component in src/components/dashboard/charts/
  2. Add query to src/actions/chart.actions.ts
  3. Export from src/components/dashboard/charts/index.ts
  4. Add to dashboard layout in src/App.tsx

Add a new filter

  1. Create filter component in src/components/dashboard/filters/
  2. Add state to src/hooks/useFilterState.ts
  3. Add to FilterBar.tsx

Add a new table column

  1. Edit src/components/dashboard/table/UsageTableColumns.tsx
  2. Add column definition with cell renderer

Add a new simulated action

  1. Create modal in src/components/dashboard/actions/
  2. Add state management to src/providers/DemoStateProvider.tsx
  3. Wire up in src/App.tsx

Type Safety

All database rows are typed in /src/types/database.ts. Extend these types when adding new queries.

Performance Notes

  • Table uses server-side pagination (50 rows/page)
  • Charts aggregate data server-side via SQL
  • TanStack Query caches results (5 min stale time)
  • Filters debounce text inputs (300ms)