The Wave list is the entry surface for activation. It uses the same GET /events/ endpoint as the Lookout Events list, but presents events as “campaigns” with a Wave KPI strip — total / running / open / closed campaigns. Clicking a row opens the Campaign detail page.

What you’ll build

  • A KPI strip at the top (4 tiles).
  • The same filterable, paginated table as Lookout — but click navigates to /campaigns/{eid} instead of /events/{eid}.
  • Permission gating: rows only clickable if the user has Wave permission.

Prerequisites

  • An authenticated user.
  • X-Preferred-Partner-Id set.
  • Optional: Permissions.wave controls clickability.

The call chain

On mount (parallel):
#MethodPathPurpose
1GET/campaigns/statisticsKPI strip: { total, running, open, closed, ignored }.
2GET/events/?...First page of events with the URL-driven filter set. Note: exclude_products is not forced to true here, unlike the Lookout list.
If the URL has ?drawer-open=true&event-id=...:
#MethodPathPurpose
3GET/events/{eid}Selected event for drawer highlight (legacy; v3 navigates instead of drawer).

Filter parameters

Same set as Events list, minus the forced exclude_products=true. Common Wave-specific defaults:
const WAVE_DEFAULT_FILTERS = {
  page:  1,
  limit: 50,
  frontend_status: ["DEFAULT", "FLAGGED"],
  // include products (don't send exclude_products)
};

Reference implementation

export function WaveList() {
  const stats   = useFd<CampaignStats>("/campaigns/statistics");
  const events  = useEventsList({ exclude_products: undefined });  // do NOT send true

  const canOpen = useHasPermission("wave");
  const onRow   = (eid: string) => canOpen && navigate(`/campaigns/${eid}`);

  return (
    <>
      <WaveKpiStrip
        total={stats.data?.total}
        running={stats.data?.running}
        open={stats.data?.open}
        closed={stats.data?.closed}
        ignored={stats.data?.ignored}
      />
      <EventTable events={events.data} onRowClick={onRow} canOpen={canOpen} />
    </>
  );
}
The useEventsList hook is the same one you wrote for the Lookout Events list. Reuse it.

Gotchas

Lookout sends exclude_products=true; Wave doesn’t. Sending it on Wave hides product events the user can run campaigns against.
Users without Permissions.wave still see the list (because they may have Lookout) — they just can’t click into the campaign detail. Show a disabled state rather than hiding rows.
The reference webapp’s v3 removed the inline drawer but still respects ?drawer-open=true&event-id= from deep links. Mirror that for backwards-compat with bookmarks.
{ total, running, open, closed, ignored }. The hero subtitle uses running / open / closed. ignored is rendered in the “Total” tile.