import { Component, useEffect, useState, type ErrorInfo, type ReactNode } from 'react'; import { useInventorySearch } from './useInventorySearch'; import { FilterSidebar } from './FilterSidebar'; import { ActiveChips } from './ActiveChips'; import { ResultsTable } from './ResultsTable'; import { DetailPanel } from './DetailPanel'; import type { InvItem } from './types'; /** Composite key used to re-match a selected item across refetches (objects are recreated each fetch). */ function itemKey(i: InvItem): string { return `${i.name} ${i.character_name} ${i.last_updated ?? ''}`; } class InventorySearchErrorBoundary extends Component<{ children: ReactNode }, { hasError: boolean }> { constructor(props: { children: ReactNode }) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(): { hasError: boolean } { return { hasError: true }; } componentDidCatch(error: Error, info: ErrorInfo): void { console.error('Inventory search crashed:', error, info); } render(): ReactNode { if (this.state.hasError) { return (

Something went wrong loading the inventory search page.

); } return this.props.children; } } function InventorySearchPageInner() { const search = useInventorySearch(); const [selected, setSelected] = useState(null); // Selection is by object identity; every refetch produces new item objects, so re-match the // previously selected item by composite key in the new result set (or clear it if it's gone). useEffect(() => { if (!selected) return; const items = search.result?.items ?? []; const key = itemKey(selected); const match = items.find(i => itemKey(i) === key); if (match && match !== selected) setSelected(match); else if (!match) setSelected(null); }, [search.result]); return (
⚔ Inventory Search search.update({ text: e.target.value })} /> {search.error ? {search.error} : search.result ? <>{search.result.total_count.toLocaleString()} items {search.queryMs != null && <> · {search.queryMs} ms} {search.loading && ' · …'} : 'loading…'}
{selected && setSelected(null)} />}
); } export function InventorySearchPage() { return ( ); }