The Wave list (/campaigns/) is the entry surface for activation. It uses the same GET /events/ endpoint as the Lookout Events list, with Wave-specific filter defaults. Opening a row shows a drawer (desktop) or navigates to the full-page Campaign detail (mobile).

What you’ll build

  • The same filterable, infinite-scroll events table as Lookout.
  • A drawer that opens inline on desktop (?drawer-open=true&event-id=...).
  • Mobile: navigate to /campaigns/:id.

Prerequisites

  • An authenticated user with Permissions.wave — the route is gated; without it the user can’t reach the list at all.
  • X-Preferred-Partner-Id set.

The call chain

On mount:
#MethodPathPurpose
1GET/events/?...First page of events with the URL-driven filter set.
When a row is opened via the drawer (URL has ?drawer-open=true&event-id=...):
#MethodPathPurpose
2GET/events/{eid}Selected event for the drawer.
The reference FE /campaigns/ page does not fetch /campaigns/statistics on mount and has no KPI strip. Campaign statistics are used on the Dashboard (and partially in the status bar), not here. Don’t add a stats call to the Wave list mount chain — or mark it explicitly as target-UX, not reference.

Filter parameters

Same set as Events list. Wave differs from Lookout mainly in that it does not force exclude_products=true. The reference FE builds filters with fetchEvents(...) and getEventFetchFilters(...), using local page reducers — there is no useEventsList hook. If you build your own hook, that’s fine; just don’t expect to find one in the reference source.

Reference implementation

export function WaveList() {
  const canAccess = useHasPermission("wave");
  if (!canAccess) return <NoWaveAccess />;     // route is gated entirely

  const events  = useEvents(getEventFetchFilters(filters));  // your own fetch
  const isMobile = useIsMobile();

  const onRow = (eid: string) => {
    if (isMobile) navigate(`/campaigns/${eid}`);            // full-page detail
    else          setDrawer({ open: true, eventId: eid });  // inline drawer
  };

  return <EventTable events={events.data} onRowClick={onRow} />;
}

Pagination

The shared table/filter components come from Lookout. Pagination is infinite scroll, not classic page-number pagination — append on scroll-near-bottom.

Gotchas

The reference Wave list doesn’t load statistics. That’s a Dashboard concern.
Users without Wave permission can’t open the list — not “see it but can’t click rows”.
Desktop opens ?drawer-open=true&event-id=... inline; mobile navigates to /campaigns/:id. It’s not “always navigate”.
It was not removed. drawer-open=true in the URL restores it.
That’s a Lookout default. Wave includes product events.