import * as React from 'react' ; import { useDispatch , useSelector } from 'react-redux' ; import { Incident , FirestoreCollections } from '@rdrnt/tps-calls-shared' ; import { useDebouncedCallback } from 'use-debounce' ; import { isPointWithinRadius } from 'geolib' ; import { Firebase , DateHelper } from '../../helpers' ; import { setIncidentList , setFilterNewestDate , setFilterOldestDate , } from '../../store/incidents/actions' ; import { AppState } from '../../store' ; import { IncidentFilterState } from '../../store/incidents' ; const IncidentListener = ( { } ) => { const dispatch = useDispatch ( ) ; const { incidents , user } = useSelector ( ( state ) => state ) ; const { filter , list } = incidents ; const [ defaultIncidentList , setDefaultIncidentList ] = React . useState < Incident < any > [ ] > ( [ ] ) ; const [ setIncidents ] = useDebouncedCallback ( ( incidents ) => { dispatch ( setIncidentList ( incidents ) ) ; } , 300 ) ; const [ previousFilters , setPreviousFilters ] = React . useState < IncidentFilterState > ( { } ) ; const [ incidentsAtDate , setIncidentsAtDate ] = React . useState < Incident < any > [ ] > ( [ ] ) ; const loadOldestIncidentDate = async ( ) => { const oldestIncident = await Firebase . incidents . getOldestIncident ( ) ; dispatch ( setFilterOldestDate ( oldestIncident . date ) ) ; } ; React . useEffect ( ( ) => { const incidentListener = Firebase . incidents . listener ( newIncidents => { setIncidents ( newIncidents ) ; setDefaultIncidentList ( newIncidents ) ; const newestIncident = newIncidents . reduce ( ( pre , current ) => { const previousDate = DateHelper . convertTimestampToDate ( pre . date ) ; const currentDateToCompare = DateHelper . convertTimestampToDate ( current . date ) ; return previousDate > currentDateToCompare ? pre : current ; } ) ; dispatch ( setFilterNewestDate ( newestIncident . date ) ) ; } ) ; loadOldestIncidentDate ( ) ; return ( ) => { if ( incidentListener ) { incidentListener ( ) ; } } ; } , [ ] ) ; const applyFilters = async ( ) => { try { const filteredIncidents = [ ] ; const getIncidentsToFilter = async ( ) => { const hasDateFilters = Boolean ( filter . startDate && filter . endDate ) ; const dateFiltersDifferent = previousFilters . startDate !== filter . startDate || previousFilters . endDate !== filter . endDate ; if ( hasDateFilters ) { if ( dateFiltersDifferent ) { const incidentsForDate = await Firebase . incidents . getIncidentsAtDate ( { startDate : filter . startDate ! , endDate : filter . endDate ! , } ) ; setIncidentsAtDate ( incidentsForDate ) ; return incidentsForDate ; } else { return incidentsAtDate ; } } return defaultIncidentList ; } ; const incidentsToFilter = await getIncidentsToFilter ( ) ; if ( filter . startDate && filter . endDate && Object . keys ( filter ) . length == 2 ) { filteredIncidents . push ( ... incidentsToFilter ) ; } if ( filter . distance && filter . distance !== 0 && user . location . coordinates ) { const withinPoint = incidentsToFilter . filter ( incident => isPointWithinRadius ( incident . coordinates , user . location . coordinates ! , filter . distance ! * 1000 ) ) ; filteredIncidents . push ( ... withinPoint ) ; } if ( filter . search ) { const matchingSearchIncidents = incidentsToFilter . filter ( incident => { const nameMatch = incident . name . toLowerCase ( ) . includes ( filter . search ! . toLowerCase ( ) ) ; const locationMatch = incident . location . toLowerCase ( ) . includes ( filter . search ! . toLowerCase ( ) ) ; return nameMatch || locationMatch ; } ) ; filteredIncidents . push ( ... matchingSearchIncidents ) ; } if ( filteredIncidents . length ) { const filteredDuplicateIncidents = filteredIncidents . reduce ( ( acc , current ) => { const x = acc . find ( item => item . id === current . id ) ; if ( ! x ) { return acc . concat ( [ current ] ) ; } else { return acc ; } } , [ ] ) ; setIncidents ( filteredDuplicateIncidents ) ; } setPreviousFilters ( filter ) ; } catch ( error ) { console . log ( 'Error filtering' , error ) ; } } ; React . useEffect ( ( ) => { const doesHaveFilter = Object . keys ( filter ) . length > 0 ; if ( ! doesHaveFilter && list . length !== defaultIncidentList . length ) { setIncidents ( defaultIncidentList ) ; } else { applyFilters ( ) ; } } , [ filter ] ) ; return null ; } ; export default IncidentListener ;