({
mapped,
unmapped,
activeCategories,
onFlyTo,
onSelectMarket,
loading,
}: {
mapped: ProcessedMarket[];
unmapped: ProcessedMarket[];
activeCategories: Set<Category>;
onFlyTo: (coords: [number, number], marketId: string) => void;
onSelectMarket: (m: ProcessedMarket) => void;
loading?: boolean;
})
| 252 | |
| 253 | // --- Markets tab content --- |
| 254 | function MarketsTab({ |
| 255 | mapped, |
| 256 | unmapped, |
| 257 | activeCategories, |
| 258 | onFlyTo, |
| 259 | onSelectMarket, |
| 260 | loading, |
| 261 | }: { |
| 262 | mapped: ProcessedMarket[]; |
| 263 | unmapped: ProcessedMarket[]; |
| 264 | activeCategories: Set<Category>; |
| 265 | onFlyTo: (coords: [number, number], marketId: string) => void; |
| 266 | onSelectMarket: (m: ProcessedMarket) => void; |
| 267 | loading?: boolean; |
| 268 | }) { |
| 269 | const [search, setSearch] = useState(""); |
| 270 | const [renderNow] = useState(() => Date.now()); |
| 271 | |
| 272 | const all = [...mapped, ...unmapped]; |
| 273 | const filtered = all.filter((m) => activeCategories.has(m.category)); |
| 274 | |
| 275 | // Apply search filter |
| 276 | const searchFiltered = search.trim() |
| 277 | ? filtered.filter((m) => |
| 278 | m.title.toLowerCase().includes(search.toLowerCase()) || |
| 279 | (m.location && m.location.toLowerCase().includes(search.toLowerCase())) || |
| 280 | m.category.toLowerCase().includes(search.toLowerCase()) |
| 281 | ) |
| 282 | : null; |
| 283 | |
| 284 | const newMarkets = (searchFiltered || filtered) |
| 285 | .filter( |
| 286 | (m) => |
| 287 | m.createdAt && |
| 288 | renderNow - new Date(m.createdAt).getTime() < NEW_THRESHOLD_MS |
| 289 | ) |
| 290 | .sort( |
| 291 | (a, b) => |
| 292 | new Date(b.createdAt!).getTime() - new Date(a.createdAt!).getTime() |
| 293 | ) |
| 294 | .slice(0, 10); |
| 295 | |
| 296 | const movers = (searchFiltered || filtered) |
| 297 | .filter((i) => i.change !== null && !isNaN(i.change!)) |
| 298 | .sort((a, b) => Math.abs(b.change!) - Math.abs(a.change!)) |
| 299 | .slice(0, 10); |
| 300 | |
| 301 | const trending = [...(searchFiltered || filtered)] |
| 302 | .sort((a, b) => (b.volume24h || 0) - (a.volume24h || 0)) |
| 303 | .slice(0, 10); |
| 304 | |
| 305 | const global = searchFiltered |
| 306 | ? [] |
| 307 | : [...unmapped] |
| 308 | .filter((m) => activeCategories.has(m.category)) |
| 309 | .sort((a, b) => (b.volume24h || 0) - (a.volume24h || 0)) |
| 310 | .slice(0, 8); |
| 311 |
nothing calls this directly
no test coverage detected