Skip to content

Commit

Permalink
Refactor how commodity filter options are persisted
Browse files Browse the repository at this point in the history
Removed persisting options via localStorage and moved it to URL state.

This is more ephemeral, but is a less confusing user experience, and still allows links to views to be easily shared.

It's far from perfect and I expect to refine it further - and the render and network behaviour needs optimisation.
  • Loading branch information
iaincollins committed Oct 27, 2024
1 parent 9b2fd98 commit f360706
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 235 deletions.
10 changes: 1 addition & 9 deletions components/commodity-export-orders.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,6 @@ async function getExportsForCommodityBySystem (systemName, commodityName) {
}

export default ({ commodities }) => {
const [hideDistanceColumn, setHideDistanceColumn] = useState()

useEffect(() => {
setHideDistanceColumn((!window.localStorage?.getItem('locationFilter') || parseInt(window.localStorage?.getItem('distanceFilter')) === 1))
}, [commodities])

if (hideDistanceColumn === undefined) return

return (
<Table
className='data-table data-table--striped data-table--interactive data-table--animated'
Expand Down Expand Up @@ -70,7 +62,7 @@ export default ({ commodities }) => {
render: (v, r) => (
<>
<span style={{ opacity: 0.75 }}>{v}</span>
{hideDistanceColumn === false && <small className='text-no-transform' style={{ marginLeft: '.5rem', opacity: 0.5 }}>{Number.isInteger(r.distance) ? <>{r.distance.toLocaleString()} ly</> : ''}</small>}
{Number.isInteger(r.distance) && <small className='text-no-transform' style={{ marginLeft: '.5rem', opacity: 0.5 }}>{Number.isInteger(r.distance) ? <>{r.distance.toLocaleString()} ly</> : ''}</small>}
</>
)
},
Expand Down
10 changes: 1 addition & 9 deletions components/commodity-import-orders.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,6 @@ async function getImportsForCommodityBySystem (systemName, commodityName) {
}

export default ({ commodities }) => {
const [hideDistanceColumn, setHideDistanceColumn] = useState()

useEffect(() => {
setHideDistanceColumn((!window.localStorage?.getItem('locationFilter') || parseInt(window.localStorage?.getItem('distanceFilter')) === 1))
}, [commodities])

if (hideDistanceColumn === undefined) return

return (
<Table
className='data-table data-table--striped data-table--interactive data-table--animated'
Expand Down Expand Up @@ -70,7 +62,7 @@ export default ({ commodities }) => {
render: (v, r) => (
<>
<span style={{ opacity: 0.75 }}>{v}</span>
{hideDistanceColumn === false && <small className='text-no-transform' style={{ marginLeft: '.5rem', opacity: 0.5 }}>{Number.isInteger(r.distance) ? <>{r.distance.toLocaleString()} ly</> : ''}</small>}
{Number.isInteger(r.distance) && <small className='text-no-transform' style={{ marginLeft: '.5rem', opacity: 0.5 }}>{Number.isInteger(r.distance) ? <>{r.distance.toLocaleString()} ly</> : ''}</small>}
</>
)
},
Expand Down
35 changes: 1 addition & 34 deletions components/nearby-commodity-exporters.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,12 @@ import Table from 'rc-table'
import { timeBetweenTimestamps } from 'lib/utils/dates'
import TradeBracketIcon from './trade-bracket'
import StationIcon from './station-icon'
import {
API_BASE_URL
// COMMODITY_FILTER_MAX_DAYS_AGO_DEFAULT,
// COMMODITY_FILTER_FLEET_CARRIER_DEFAULT,
// COMMODITY_FILTER_MIN_VOLUME_DEFAULT
} from 'lib/consts'
import { API_BASE_URL } from 'lib/consts'

const MAX_ROWS_TO_DISPLAY = 10

async function getNearbyExportersOfCommodity (systemName, commodityName) {
let url = `${API_BASE_URL}/v1/system/name/${systemName}/commodity/name/${commodityName}/nearby/exports`
const options = []

/*
const lastUpdatedFilterValue = window.localStorage?.getItem('lastUpdatedFilter') ?? COMMODITY_FILTER_MAX_DAYS_AGO_DEFAULT
const minVolumeFilterValue = window.localStorage?.getItem('minVolumeFilter') ?? COMMODITY_FILTER_MIN_VOLUME_DEFAULT
const fleetCarrierFilterValue = window.localStorage?.getItem('fleetCarrierFilter') ?? COMMODITY_FILTER_FLEET_CARRIER_DEFAULT
options.push(`maxDaysAgo=${lastUpdatedFilterValue}`)
options.push(`minVolume=${minVolumeFilterValue}`)
if (fleetCarrierFilterValue === 'excluded') options.push('fleetCarriers=false')
if (fleetCarrierFilterValue === 'only') options.push('fleetCarriers=true')
*/

if (options.length > 0) {
url += `?${options.join('&')}`
}

// TODO
const res = await fetch(url)
return await res.json()
}
Expand All @@ -48,16 +25,6 @@ export default ({ commodity }) => {
})()
}, [commodity.commodityName, commodity.systemName])

useEffect(() => {
const eventHandler = async () => {
setNearbyExporters(
(await getNearbyExportersOfCommodity(commodity.systemName, commodity.symbol)).slice(0, MAX_ROWS_TO_DISPLAY)
)
}
window.addEventListener('CommodityFilterChangeEvent', eventHandler)
return () => window.removeEventListener('CommodityFilterChangeEvent', eventHandler)
}, [])

return (
<>
{!nearbyExporters && <div className='loading-bar' style={{ marginTop: 0, marginBottom: '1rem' }} />}
Expand Down
35 changes: 1 addition & 34 deletions components/nearby-commodity-importers.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,12 @@ import Table from 'rc-table'
import { timeBetweenTimestamps } from 'lib/utils/dates'
import TradeBracketIcon from './trade-bracket'
import StationIcon from './station-icon'
import {
API_BASE_URL,
// COMMODITY_FILTER_MAX_DAYS_AGO_DEFAULT,
// COMMODITY_FILTER_FLEET_CARRIER_DEFAULT,
// COMMODITY_FILTER_MIN_VOLUME_DEFAULT,
NO_DEMAND_TEXT
} from 'lib/consts'
import { API_BASE_URL, NO_DEMAND_TEXT } from 'lib/consts'

const MAX_ROWS_TO_DISPLAY = 10

async function getNearbyImportersOfCommodity (systemName, commodityName) {
let url = `${API_BASE_URL}/v1/system/name/${systemName}/commodity/name/${commodityName}/nearby/imports`
const options = []

/*
const lastUpdatedFilterValue = window.localStorage?.getItem('lastUpdatedFilter') ?? COMMODITY_FILTER_MAX_DAYS_AGO_DEFAULT
const minVolumeFilterValue = window.localStorage?.getItem('minVolumeFilter') ?? COMMODITY_FILTER_MIN_VOLUME_DEFAULT
const fleetCarrierFilterValue = window.localStorage?.getItem('fleetCarrierFilter') ?? COMMODITY_FILTER_FLEET_CARRIER_DEFAULT
options.push(`maxDaysAgo=${lastUpdatedFilterValue}`)
options.push(`minVolume=${minVolumeFilterValue}`)
if (fleetCarrierFilterValue === 'excluded') options.push('fleetCarriers=false')
if (fleetCarrierFilterValue === 'only') options.push('fleetCarriers=true')
*/

if (options.length > 0) {
url += `?${options.join('&')}`
}

const res = await fetch(url)
return await res.json()
}
Expand All @@ -48,16 +25,6 @@ export default ({ commodity }) => {
})()
}, [commodity.commodityName, commodity.systemName])

useEffect(() => {
const eventHandler = async () => {
setNearbyImporters(
(await getNearbyImportersOfCommodity(commodity.systemName, commodity.symbol)).slice(0, MAX_ROWS_TO_DISPLAY)
)
}
window.addEventListener('CommodityFilterChangeEvent', eventHandler)
return () => window.removeEventListener('CommodityFilterChangeEvent', eventHandler)
}, [])

return (
<>
{!nearbyImporters && <div className='loading-bar' style={{ marginTop: 0 }} />}
Expand Down
141 changes: 54 additions & 87 deletions components/tab-options/commodities.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,59 +19,68 @@ const DEFAULT_LOCATION_OPTIONS = ['Any location', 'Core Systems', 'Colonia Regio
export default ({ disabled = false }) => {
const router = useRouter()
const componentMounted = useRef(false)
const [lastUpdatedFilter, setLastUpdatedFilter] = useState(window.localStorage?.getItem('lastUpdatedFilter') ?? COMMODITY_FILTER_MAX_DAYS_AGO_DEFAULT)
const [fleetCarrierFilter, setFleetCarrierFilter] = useState(window.localStorage?.getItem('fleetCarrierFilter') ?? COMMODITY_FILTER_FLEET_CARRIER_DEFAULT)
const [minVolumeFilter, setMinVolumeFilter] = useState(window.localStorage?.getItem('minVolumeFilter') ?? COMMODITY_FILTER_MIN_VOLUME_DEFAULT)
const [locationFilter, setLocationFilter] = useState(window.localStorage?.getItem('locationFilter') ?? COMMODITY_FILTER_LOCATION_DEFAULT)
const [distanceFilter, setDistanceFilter] = useState(window.localStorage?.getItem('distanceFilter') ?? COMMODITY_FILTER_DISTANCE_DEFAULT)
const [lastUpdatedFilter, setLastUpdatedFilter] = useState()
const [minVolumeFilter, setMinVolumeFilter] = useState()
const [fleetCarrierFilter, setFleetCarrierFilter] = useState()
const [locationFilter, setLocationFilter] = useState()
const [distanceFilter, setDistanceFilter] = useState()

function updateUrlWithFilterOptions (router) {
const commodityName = window.location?.pathname?.replace(/\/(importers|exporters)$/, '').replace(/.*\//, '')

let activeTab = 'importers'
if (window?.location?.pathname?.endsWith('exporters')) activeTab = 'exporters'

let url = `/commodity/${commodityName}/${activeTab}`
const options = []
options.push(`maxDaysAgo=${lastUpdatedFilter}`)
options.push(`minVolume=${minVolumeFilter}`)
options.push(`fleetCarriers=${fleetCarrierFilter}`)
if (locationFilter && locationFilter !== COMMODITY_FILTER_LOCATION_DEFAULT) {
options.push(`location=${encodeURIComponent(locationFilter)}`)
if (distanceFilter) {
options.push(`maxDistance=${distanceFilter}`)
}
}

if (options.length > 0) {
url += `?${options.join('&')}`
}

router.push(url)
}

useEffect(() => {
if (componentMounted.current === true) {
window.dispatchEvent(new CustomEvent('CommodityFilterChangeEvent'))
updateUrlWithFilterOptions(router)
} else {
componentMounted.current = true
}
}, [lastUpdatedFilter, fleetCarrierFilter, minVolumeFilter, locationFilter, distanceFilter])

useEffect(() => {
if (router.query?.maxDaysAgo && parseInt(router.query.maxDaysAgo) !== parseInt(lastUpdatedFilter)) {
setLastUpdatedFilter(router.query.maxDaysAgo)
window.localStorage.setItem('lastUpdatedFilter', router.query.maxDaysAgo)
}
if (router.query?.fleetCarriers && router.query.fleetCarriers !== parseInt(fleetCarrierFilter)) {
setFleetCarrierFilter(router.query.fleetCarriers)
window.localStorage.setItem('fleetCarrierFilter', router.query.fleetCarriers)
}
if (router.query?.minVolume && parseInt(router.query.minVolume) !== parseInt(minVolumeFilter)) {
setMinVolumeFilter(router.query.minVolume)
window.localStorage.setItem('minVolumeFilter', router.query.minVolume)
}
if (router.query?.location && router.query.location !== locationFilter) {
setLocationFilter(router.query.location.trim())
window.localStorage.setItem('locationFilter', router.query.location.trim())
document.getElementById('location').value = router.query.location.trim()
}
if (router.query?.maxDistance && parseInt(router.query.maxDaysAgo) !== parseInt(distanceFilter)) {
setDistanceFilter(router.query.maxDistance)
window.localStorage.setItem('distanceFilter', router.query.maxDistance)
}
setLastUpdatedFilter(router.query?.maxDaysAgo ?? COMMODITY_FILTER_MAX_DAYS_AGO_DEFAULT)
setMinVolumeFilter(router.query?.minVolume ?? COMMODITY_FILTER_MIN_VOLUME_DEFAULT)
setFleetCarrierFilter(router.query?.fleetCarriers ?? COMMODITY_FILTER_FLEET_CARRIER_DEFAULT)
setLocationFilter(router.query?.location ?? COMMODITY_FILTER_LOCATION_DEFAULT)
setDistanceFilter(router.query?.maxDistance ?? COMMODITY_FILTER_DISTANCE_DEFAULT)
}, [router.query])

return (
<div className='tab-options'>
<form method='GET' action='/' onSubmit={(e) => {
<form
method='GET' action='/' onSubmit={(e) => {
e.preventDefault()
document.activeElement.blur()
}}>
}}
>
<label>
<span className='tab-options__label-text'>Updated</span>
<select
name='last-updated' value={lastUpdatedFilter}
disabled={disabled}
onChange={(e) => {
setLastUpdatedFilter(e.target.value)
window.localStorage.setItem('lastUpdatedFilter', parseInt(e.target.value))
}}
>
<option value='1'>Today</option>
Expand All @@ -83,35 +92,33 @@ export default ({ disabled = false }) => {
</label>

<label>
<span className='tab-options__label-text'>Carriers</span>
<span className='tab-options__label-text'>Quantity</span>
<select
name='fleet-carriers' value={fleetCarrierFilter}
name='commodity-quantity' value={minVolumeFilter}
disabled={disabled}
onChange={(e) => {
setFleetCarrierFilter(e.target.value)
window.localStorage.setItem('fleetCarrierFilter', e.target.value)
setMinVolumeFilter(e.target.value)
}}
>
<option value='included'>Included</option>
<option value='excluded'>Excluded</option>
<option value='only'>Only</option>
<option value='1'>Any quantity</option>
<option value='100'>&gt; 100 T</option>
<option value='1000'>&gt; 1,000 T</option>
<option value='10000'>&gt; 10,000 T</option>
</select>
</label>

<label>
<span className='tab-options__label-text'>Quantity</span>
<span className='tab-options__label-text'>Carriers</span>
<select
name='commodity-quantity' value={minVolumeFilter}
name='fleet-carriers' value={fleetCarrierFilter}
disabled={disabled}
onChange={(e) => {
setMinVolumeFilter(e.target.value)
window.localStorage.setItem('minVolumeFilter', parseInt(e.target.value))
setFleetCarrierFilter(e.target.value)
}}
>
<option value='1'>Any quantity</option>
<option value='100'>&gt; 100 T</option>
<option value='1000'>&gt; 1,000 T</option>
<option value='10000'>&gt; 10,000 T</option>
<option value='included'>Included</option>
<option value='excluded'>Excluded</option>
<option value='only'>Only</option>
</select>
</label>

Expand Down Expand Up @@ -141,32 +148,26 @@ export default ({ disabled = false }) => {
const locationValue = value
if (locationValue === '' || locationValue === COMMODITY_FILTER_LOCATION_DEFAULT) {
e.target.value = ''
window.localStorage.removeItem('distanceFilter')
setDistanceFilter(COMMODITY_FILTER_DISTANCE_DEFAULT)
setLocationFilter(COMMODITY_FILTER_LOCATION_DEFAULT)
window.localStorage.removeItem('locationFilter')
} else {
let newLocationValue = locationValue
if (locationValue === 'Core Systems') {
newLocationValue = 'Sol'
e.target.value = newLocationValue
window.localStorage.setItem('distanceFilter', 500)
setDistanceFilter(500)
} else if (locationValue === 'Colonia Region') {
newLocationValue = 'Colonia'
e.target.value = newLocationValue
window.localStorage.setItem('distanceFilter', 100)
setDistanceFilter(100)
} else {
e.target.value = value // trimmed value
if (distanceFilter === COMMODITY_FILTER_DISTANCE_DEFAULT) {
setDistanceFilter(COMMODITY_FILTER_DISTANCE_WITH_LOCATION_DEFAULT)
window.localStorage.setItem('distanceFilter', COMMODITY_FILTER_DISTANCE_WITH_LOCATION_DEFAULT)
}
document.getElementById('location-list').innerHTML = ''
}
setLocationFilter(newLocationValue)
window.localStorage.setItem('locationFilter', newLocationValue)
}
}
}}
Expand Down Expand Up @@ -211,10 +212,9 @@ export default ({ disabled = false }) => {
disabled={disabled || locationFilter === COMMODITY_FILTER_LOCATION_DEFAULT || locationFilter === ZERO_WIDTH_SPACE}
value={distanceFilter}
onChange={(e) => {
setDistanceFilter(e.target.value)
; (e.target.value === COMMODITY_FILTER_DISTANCE_DEFAULT)
? window.localStorage.removeItem('distanceFilter')
: window.localStorage.setItem('distanceFilter', parseInt(e.target.value))
? setDistanceFilter(undefined)
: setDistanceFilter(e.target.value)
}}
>
<option value={COMMODITY_FILTER_DISTANCE_DEFAULT}>Any distance</option>
Expand Down Expand Up @@ -244,11 +244,6 @@ export default ({ disabled = false }) => {
setMinVolumeFilter(COMMODITY_FILTER_MIN_VOLUME_DEFAULT)
setLocationFilter(COMMODITY_FILTER_LOCATION_DEFAULT)
setDistanceFilter(COMMODITY_FILTER_DISTANCE_DEFAULT)
window.localStorage.removeItem('lastUpdatedFilter')
window.localStorage.removeItem('fleetCarrierFilter')
window.localStorage.removeItem('minVolumeFilter')
window.localStorage.removeItem('locationFilter')
window.localStorage.removeItem('distanceFilter')
}}
>
Reset
Expand All @@ -265,31 +260,3 @@ async function findSystemsByName (systemName) {
const res = await fetch(`${API_BASE_URL}/v1/search/system/name/${systemName}/`)
return await res.json()
}

function updateUrlWithFilterOptions (router) {
const commodityName = window.location?.pathname?.replace(/\/(importers|exporters)$/, '').replace(/.*\//, '')

let activeTab = 'importers'
if (window?.location?.pathname?.endsWith('exporters')) activeTab = 'exporters'

let url = `/commodity/${commodityName}/${activeTab}`
const options = []

const lastUpdatedFilterValue = window.localStorage?.getItem('lastUpdatedFilter') ?? COMMODITY_FILTER_MAX_DAYS_AGO_DEFAULT
const minVolumeFilterValue = window.localStorage?.getItem('minVolumeFilter') ?? COMMODITY_FILTER_MIN_VOLUME_DEFAULT
const fleetCarrierFilterValue = window.localStorage?.getItem('fleetCarrierFilter') ?? COMMODITY_FILTER_FLEET_CARRIER_DEFAULT
const locationFilterValue = window.localStorage?.getItem('locationFilter') ?? null
const distanceFilterValue = window.localStorage?.getItem('distanceFilter') ?? null

options.push(`maxDaysAgo=${lastUpdatedFilterValue}`)
options.push(`minVolume=${minVolumeFilterValue}`)
options.push(`fleetCarriers=${fleetCarrierFilterValue}`)
if (locationFilterValue !== null) options.push(`systemName=${encodeURIComponent(locationFilterValue)}`)
if (distanceFilterValue !== null) options.push(`maxDistance=${distanceFilterValue}`)

if (options.length > 0) {
url += `?${options.join('&')}`
}

return router.push(url)
}
Loading

0 comments on commit f360706

Please sign in to comment.