Skip to content

Commit

Permalink
refactor: use query params for yields filters (DefiLlama#471)
Browse files Browse the repository at this point in the history
* update chain filter

* update project filter

* update yields search routes to query params
  • Loading branch information
mintdart authored Jul 1, 2022
1 parent c752f66 commit be22821
Show file tree
Hide file tree
Showing 15 changed files with 176 additions and 255 deletions.
15 changes: 15 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,21 @@ const nextConfig = {
source: '/langs',
destination: '/languages',
permanent: true
},
{
source: '/yields/project/:path*',
destination: '/yields?project=:path*',
permanent: true
},
{
source: '/yields/token/:path*',
destination: '/yields?token=:path*',
permanent: true
},
{
source: '/yields/chain/:path*',
destination: '/yields?chain=:path*',
permanent: true
}
]
},
Expand Down
37 changes: 30 additions & 7 deletions src/components/Filters/FiltersByChain.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
import * as React from 'react'
import { useRouter } from 'next/router'
import { MenuButtonArrow, useComboboxState, useSelectState } from 'ariakit'
import { ApplyFilters, Checkbox } from '~/components'
import { Input, List } from '~/components/Combobox'
import { FilterButton } from '~/components/Select/AriakitSelect'
import { Dropdown, Item, Stats } from './shared'

interface IFiltersByChainProps {
chains: string[]
setChainsToFilter: React.Dispatch<React.SetStateAction<string[]>>
chainList: string[]
selectedChains: string[]
}

export function FiltersByChain({ chains = [], setChainsToFilter }: IFiltersByChainProps) {
const combobox = useComboboxState({ list: chains })
export function FiltersByChain({ chainList = [], selectedChains }: IFiltersByChainProps) {
const router = useRouter()

const combobox = useComboboxState({ list: chainList })

const [chains, setChains] = React.useState<string[]>([])

React.useEffect(() => {
if (selectedChains) {
setChains(selectedChains)
}
}, [selectedChains])

// value and setValue shouldn't be passed to the select state because the
// select value and the combobox value are different things.
const { value, setValue, ...selectProps } = combobox
const select = useSelectState({
...selectProps,
defaultValue: chains,
value: chains,
setValue: (v) => setChains(v),
gutter: 8
})

Expand All @@ -27,11 +40,21 @@ export function FiltersByChain({ chains = [], setChainsToFilter }: IFiltersByCha
}

const filterChains = () => {
setChainsToFilter(select.value)
router.push(
{
pathname: '/yields',
query: {
...router.query,
chain: select.value.length === chainList.length ? 'All' : select.value
}
},
undefined,
{ shallow: true }
)
}

const toggleAll = () => {
select.setValue(select.value.length === chains.length ? [] : chains)
select.setValue(select.value.length === chainList.length ? [] : chainList)
}

return (
Expand Down
15 changes: 12 additions & 3 deletions src/components/Filters/yields/Attributes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
STABLECOINS,
useLocalStorageContext
} from '~/contexts/LocalStorage'
import { Stats } from '../shared'

const options = [
{
Expand Down Expand Up @@ -45,7 +46,7 @@ export function YieldAttributes() {

const [value, setValue] = useState<string[]>(options.map((o) => o.key).filter((o) => state[o]))

const menu = useSelectState({
const select = useSelectState({
value,
setValue: (values) => setValue(values),
gutter: 8
Expand All @@ -62,13 +63,21 @@ export function YieldAttributes() {
})
}

const toggleAll = () => {
select.setValue(select.value.length === options.length ? [] : options.map((o) => o.key))
}

return (
<>
<FilterButton state={menu}>
<FilterButton state={select}>
Filter by Attribute
<MenuButtonArrow />
</FilterButton>
<FilterPopover state={menu}>
<FilterPopover state={select}>
<Stats>
<p>{`${select.value.length} selected`}</p>
<button onClick={toggleAll}>toggle all</button>
</Stats>
{options.map((option) => (
<FilterItem key={option.key} value={option.key}>
{option.help ? <HeadHelp title={option.name} text={option.help} /> : option.name}
Expand Down
10 changes: 5 additions & 5 deletions src/components/Filters/yields/Projects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import { FilterButton } from '~/components/Select/AriakitSelect'
import { Dropdown, Item, Stats } from '../shared'

interface IYieldProjectsProps {
projectNameList: string[]
projectList: string[]
selectedProjects: string[]
}

export function YieldProjects({ projectNameList = [], selectedProjects }: IYieldProjectsProps) {
export function YieldProjects({ projectList = [], selectedProjects }: IYieldProjectsProps) {
const router = useRouter()

const [projects, setProjects] = useState<string[]>([])
Expand All @@ -22,7 +22,7 @@ export function YieldProjects({ projectNameList = [], selectedProjects }: IYield
}
}, [selectedProjects])

const combobox = useComboboxState({ list: projectNameList })
const combobox = useComboboxState({ list: projectList })
// value and setValue shouldn't be passed to the select state because the
// select value and the combobox value are different things.
const { value, setValue, ...selectProps } = combobox
Expand All @@ -45,7 +45,7 @@ export function YieldProjects({ projectNameList = [], selectedProjects }: IYield
pathname: '/yields',
query: {
...router.query,
project: select.value
project: select.value.length === projectList.length ? 'All' : select.value
}
},
undefined,
Expand All @@ -54,7 +54,7 @@ export function YieldProjects({ projectNameList = [], selectedProjects }: IYield
}

const toggleAll = () => {
select.setValue(select.value.length === projectNameList.length ? [] : projectNameList)
select.setValue(select.value.length === projectList.length ? [] : projectList)
}

return (
Expand Down
2 changes: 1 addition & 1 deletion src/components/IconsRow/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const Link = styled(BasicLink)`

export const ChainLogo = ({ chain, url, iconType }) => {
return (
<Link key={chain} href={`${url}/${chain}`}>
<Link key={chain} href={url.includes('/yields?chain') ? `${url}=${chain}` : `${url}/${chain}`}>
<TokenLogo address={chain} logo={iconType === 'token' ? tokenIconUrl(chain) : chainIconUrl(chain)} />
</Link>
)
Expand Down
7 changes: 5 additions & 2 deletions src/components/Search/BaseSearch/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,11 @@ const Row = ({ index, style, data }) => {
key={value}
value={value}
onClick={() => {
if (onItemClick) onItemClick(item)
router.push(item.route)
if (onItemClick) {
onItemClick(item)
} else {
router.push(item.route)
}
}}
style={style}
>
Expand Down
28 changes: 17 additions & 11 deletions src/components/Search/YieldsSearch/Advanced.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,35 @@ import styled from 'styled-components'
import { ToggleSearch } from './shared'
import ReactSelect from '~/components/Select/ReactSelect'
import { useFetchYieldsList } from '~/utils/categories/yield'
import { useRouter } from 'next/router'

interface IAdvancedYieldSearchProps {
setAdvancedSearch: React.Dispatch<React.SetStateAction<boolean>>
setTokensToFilter: React.Dispatch<
React.SetStateAction<{
includeTokens: string[]
excludeTokens: string[]
}>
>
}

export function AdvancedYieldsSearch({ setAdvancedSearch, setTokensToFilter }: IAdvancedYieldSearchProps) {
export function AdvancedYieldsSearch({ setAdvancedSearch }: IAdvancedYieldSearchProps) {
const router = useRouter()

const [includeTokens, setIncludeTokens] = React.useState([])
const [excludeTokens, setExcludeTokens] = React.useState([])

const { data, loading } = useFetchYieldsList()

const handleSubmit = (e) => {
e.preventDefault()
setTokensToFilter({
includeTokens: includeTokens.map((t) => t.label.toLowerCase()),
excludeTokens: excludeTokens.map((t) => t.label.toLowerCase())
})

router.push(
{
pathname: '/yields',
query: {
...router.query,
token: includeTokens.map((t) => t.label),
excludeToken: excludeTokens.map((t) => t.label)
}
},
undefined,
{ shallow: true }
)
}

const options = React.useMemo(() => {
Expand Down
33 changes: 21 additions & 12 deletions src/components/Search/YieldsSearch/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,13 @@ import type { IBaseSearchProps, ICommonSearchProps } from '~/components/Search/B
import { useFetchYieldsList } from '~/utils/categories/yield'
import { AdvancedYieldsSearch } from './Advanced'
import { ToggleSearch } from './shared'
import { useRouter } from 'next/router'

interface IYieldSearchProps extends ICommonSearchProps {
setTokensToFilter?: React.Dispatch<
React.SetStateAction<{
includeTokens: string[]
excludeTokens: string[]
}>
>
}

export default function YieldsSearch({ setTokensToFilter, ...props }: IYieldSearchProps) {
export default function YieldsSearch(props: ICommonSearchProps) {
const [advancedSearch, setAdvancedSearch] = React.useState(false)

const router = useRouter()

const { data, loading } = useFetchYieldsList()

const searchData: IBaseSearchProps['data'] =
Expand All @@ -25,21 +19,36 @@ export default function YieldsSearch({ setTokensToFilter, ...props }: IYieldSear
data?.map((el) => ({
name: `${el.name} (${el.symbol.toUpperCase()})`,
symbol: el.symbol.toUpperCase(),
route: `/yields/token/${el.symbol.toUpperCase()}`,
route: `/yields?token=${el.symbol.toUpperCase()}`,
logo: el.image
})) ?? []
)
}, [data]) ?? []

const handleTokenRoute = (token) => {
router.push(
{
pathname: '/yields',
query: {
...router.query,
token: token.symbol
}
},
undefined,
{ shallow: true }
)
}

if (!props.step?.hideOptions && advancedSearch) {
return <AdvancedYieldsSearch setAdvancedSearch={setAdvancedSearch} setTokensToFilter={setTokensToFilter} />
return <AdvancedYieldsSearch setAdvancedSearch={setAdvancedSearch} />
}

return (
<BaseSearch
{...props}
data={searchData}
loading={loading}
onItemClick={handleTokenRoute}
filters={
!props.step?.hideOptions && (
<ToggleSearch onClick={() => setAdvancedSearch(true)}>Switch to Advanced Search</ToggleSearch>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Table/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ interface INameYield extends Omit<NameProps, 'type'> {

export function NameYield({ project, projectslug, rowType, ...props }: INameYield) {
const iconUrl = tokenIconUrl(project)
const tokenUrl = `/yields/project/${projectslug}`
const tokenUrl = `/yields?project=${projectslug}`

return (
<Index {...props}>
Expand Down
Loading

0 comments on commit be22821

Please sign in to comment.