/** * Shared "which cities currently have events" derivation used by both the * `/city` hub page and `sitemap.ts`. Both previously re-implemented this * `Set` + filter independently after fetching discovery events; extracted * here so there's one place computing it. * * NOTE: there's no dedicated "cities with active events" aggregation * endpoint yet — this only reflects whatever discovery events the caller * passes in. `/city` intentionally samples just the first page of public * discovery events (backend max pageSize 100) to derive this cheaply; that * remains a stub, revisit with a real aggregation once saza1's foundation * lands if event volume grows past one page. `sitemap.ts` instead passes * every page (via `fetchAllSeoDiscoveryEvents`), so it isn't subject to * that same page-1 limit. */ interface ActiveCityEventCandidate { cityId: number } interface ActiveCityCandidate { id: number } /** Derives the set of city ids present among the given discovery events. */ export function getActiveCityIds(events: ActiveCityEventCandidate[]): Set { return new Set(events.map((event) => event.cityId)) } /** Filters `cities` down to those whose id is in `activeCityIds`. */ export function filterActiveCities(cities: T[], activeCityIds: Set): T[] { return cities.filter((city) => activeCityIds.has(city.id)) }