@@ -16,9 +16,9 @@ import type { TimelineBucket } from "./sections";
1616import { SettingsPanel , type ExpandedSections } from "./SettingsPanel" ;
1717import { TimelineBar } from "./TimelineBar" ;
1818
19- import { useFieldReports } from "@/hooks/dashboard" ;
19+ import { useFieldReports , useImagePreloader } from "@/hooks/dashboard" ;
2020import type { DataResponse } from "@/pages/api/data" ;
21- import type { FieldReportsResponse } from "@/types" ;
21+ import type { FieldReportsResponse , Pool , PoolsResponse } from "@/types" ;
2222import type { Voucher } from "@/types/voucher" ;
2323
2424// Fetcher function for SWR
@@ -51,11 +51,24 @@ export function Dashboard() {
5151 }
5252 ) ;
5353
54+ // Fetch pools
55+ const { data : poolsData , isLoading : poolsLoading } = useSWR < PoolsResponse > (
56+ "/api/pools" ,
57+ fetcher ,
58+ {
59+ refreshInterval : 5 * 60 * 1000 ,
60+ revalidateOnFocus : false ,
61+ }
62+ ) ;
63+
5464 // Panel states
5565 const [ optionsOpen , setOptionsOpen ] = React . useState ( false ) ;
5666 const [ graphType , setGraphType ] = React . useState < "2D" | "3D" > ( "3D" ) ;
5767 const [ showTimelineBar , setShowTimelineBar ] = React . useState ( true ) ;
5868
69+ // Pool filtering
70+ const [ selectedPools , setSelectedPools ] = React . useState < Pool [ ] > ( [ ] ) ;
71+
5972 // Token filtering
6073 const [ selectedTokens , setSelectedTokens ] = React . useState < Voucher [ ] > ( [ ] ) ;
6174 const [ filteredByToken , setFilteredByToken ] = React . useState <
@@ -91,6 +104,7 @@ export function Dashboard() {
91104 // Collapsible sections state
92105 const [ expandedSections , setExpandedSections ] =
93106 React . useState < ExpandedSections > ( {
107+ pools : false ,
94108 vouchers : true ,
95109 animation : false ,
96110 display : false ,
@@ -107,6 +121,23 @@ export function Dashboard() {
107121 return ( ) => clearTimeout ( timer ) ;
108122 } , [ chargeStrengthInput , linkDistanceInput , centerGravityInput ] ) ;
109123
124+ // Compute available vouchers based on selected pools
125+ const availableVouchers = React . useMemo ( ( ) => {
126+ if ( ! data ?. vouchers ) return [ ] ;
127+ if ( selectedPools . length === 0 ) return data . vouchers ;
128+
129+ // Union of all allowed tokens from selected pools
130+ const allowedSet = new Set < string > ( ) ;
131+ for ( const pool of selectedPools ) {
132+ for ( const token of pool . allowed_tokens ) {
133+ allowedSet . add ( token . toLowerCase ( ) ) ;
134+ }
135+ }
136+ return data . vouchers . filter ( ( v ) =>
137+ allowedSet . has ( v . contract_address . toLowerCase ( ) )
138+ ) ;
139+ } , [ data ?. vouchers , selectedPools ] ) ;
140+
110141 // Initialize selected tokens when data loads
111142 React . useEffect ( ( ) => {
112143 if ( data ) {
@@ -115,6 +146,26 @@ export function Dashboard() {
115146 }
116147 } , [ data ] ) ;
117148
149+ // Auto-select pool tokens when pools change
150+ React . useEffect ( ( ) => {
151+ if ( ! data ?. vouchers ) return ;
152+
153+ if ( selectedPools . length > 0 ) {
154+ // Union of all allowed tokens from selected pools
155+ const allowedSet = new Set < string > ( ) ;
156+ for ( const pool of selectedPools ) {
157+ for ( const token of pool . allowed_tokens ) {
158+ allowedSet . add ( token . toLowerCase ( ) ) ;
159+ }
160+ }
161+ const poolTokens = data . vouchers . filter ( ( v ) =>
162+ allowedSet . has ( v . contract_address . toLowerCase ( ) )
163+ ) ;
164+ setSelectedTokens ( poolTokens ) ;
165+ }
166+ // When no pools selected, keep current selection
167+ } , [ selectedPools , data ?. vouchers ] ) ;
168+
118169 // Filter graph data by selected tokens
119170 React . useEffect ( ( ) => {
120171 if ( ! data ) return ;
@@ -287,12 +338,20 @@ export function Dashboard() {
287338 maxVisible : 3 ,
288339 } ) ;
289340
290- // Reset dismissed reports when animation restarts from beginning
341+ // Image preloading for field reports
342+ const { resetPreloaded } = useImagePreloader ( {
343+ reports : reportsData ?. reports ?? [ ] ,
344+ currentDate : date ,
345+ selectedVoucherAddresses,
346+ } ) ;
347+
348+ // Reset dismissed reports and preloaded images when animation restarts from beginning
291349 React . useEffect ( ( ) => {
292350 if ( date === dateRange . start ) {
293351 resetDismissed ( ) ;
352+ resetPreloaded ( ) ;
294353 }
295- } , [ date , dateRange . start , resetDismissed ] ) ;
354+ } , [ date , dateRange . start , resetDismissed , resetPreloaded ] ) ;
296355
297356 // Callbacks
298357 const toggleSection = React . useCallback ( ( section : keyof ExpandedSections ) => {
@@ -410,8 +469,12 @@ export function Dashboard() {
410469 voucherCount = { selectedTokens . length }
411470 expandedSections = { expandedSections }
412471 toggleSection = { toggleSection }
472+ pools = { poolsData ?. pools ?? [ ] }
473+ poolsLoading = { poolsLoading }
474+ selectedPools = { selectedPools }
475+ onSelectPools = { setSelectedPools }
413476 selectedTokens = { selectedTokens }
414- allVouchers = { data . vouchers }
477+ allVouchers = { availableVouchers }
415478 onSelectTokens = { setSelectedTokens }
416479 date = { date }
417480 setDate = { setDate }
0 commit comments