mirror of
https://github.com/acid-info/logos-ordinals-dashboard.git
synced 2025-01-28 22:27:01 +00:00
feat: support filtering
This commit is contained in:
parent
b75923a9c2
commit
082843a0e8
71
constants/operators.ts
Normal file
71
constants/operators.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { Archetype } from '../types/operators'
|
||||||
|
|
||||||
|
export const ARCHETYPE: Archetype[] = [
|
||||||
|
'Alchemist',
|
||||||
|
'Artisan',
|
||||||
|
'Explorer',
|
||||||
|
'Illuminator',
|
||||||
|
'Magician',
|
||||||
|
'Memetic',
|
||||||
|
'Oracle',
|
||||||
|
'Outlaw',
|
||||||
|
'Philosopher',
|
||||||
|
'Polymath',
|
||||||
|
]
|
||||||
|
|
||||||
|
export const COMP = [
|
||||||
|
'Ascii',
|
||||||
|
'Ascii_RGB',
|
||||||
|
'RetroScreen',
|
||||||
|
'RetroVHS',
|
||||||
|
'SketchStar',
|
||||||
|
]
|
||||||
|
|
||||||
|
export const BACKGROUND = [
|
||||||
|
'[CAMOED]',
|
||||||
|
'Rust',
|
||||||
|
'[REDACTED]',
|
||||||
|
'[CYPHERED]',
|
||||||
|
'Mariana',
|
||||||
|
'Marooned',
|
||||||
|
'Void',
|
||||||
|
'Cypress',
|
||||||
|
'LimeWire',
|
||||||
|
'Sanguine',
|
||||||
|
'Nightfall',
|
||||||
|
'Sulphur',
|
||||||
|
'Phantom',
|
||||||
|
]
|
||||||
|
|
||||||
|
export const SKIN = [
|
||||||
|
'[CAMOED]',
|
||||||
|
'IC1',
|
||||||
|
'[REDACTED]',
|
||||||
|
'[CYPHERED]',
|
||||||
|
'IC4',
|
||||||
|
'IC2',
|
||||||
|
'IC6',
|
||||||
|
'IC3',
|
||||||
|
]
|
||||||
|
|
||||||
|
export const HELMET = [
|
||||||
|
'[CAMOED]',
|
||||||
|
'Verdant crested helm',
|
||||||
|
'[REDACTED]',
|
||||||
|
'[CYPHERED]',
|
||||||
|
'Ethereal crested helm',
|
||||||
|
'Celestial crested helm',
|
||||||
|
'Aurora crested helm',
|
||||||
|
'Regal crested helm',
|
||||||
|
]
|
||||||
|
|
||||||
|
export const JACKET = [
|
||||||
|
'[CAMOED]',
|
||||||
|
'Cobalt frock coat',
|
||||||
|
'Amethyst frock coat',
|
||||||
|
'[REDACTED]',
|
||||||
|
'[CYPHERED]',
|
||||||
|
'Sulphur frock coat',
|
||||||
|
'Carmine frock coat',
|
||||||
|
'Emerald frock coat',
|
||||||
|
]
|
@ -5,12 +5,14 @@ import Checkbox from './Checkbox' // Import the CustomCheckbox
|
|||||||
interface DropdownProps {
|
interface DropdownProps {
|
||||||
title: string
|
title: string
|
||||||
options: string[]
|
options: string[]
|
||||||
onSelectionChange: (selectedOptions: any) => void
|
filterType: string
|
||||||
|
onSelectionChange: (selectedOptions: string[], filterType: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const Dropdown: React.FC<DropdownProps> = ({
|
const Dropdown: React.FC<DropdownProps> = ({
|
||||||
title,
|
title,
|
||||||
options,
|
options,
|
||||||
|
filterType,
|
||||||
onSelectionChange,
|
onSelectionChange,
|
||||||
}) => {
|
}) => {
|
||||||
const [selectedOptions, setSelectedOptions] = useState<string[]>([])
|
const [selectedOptions, setSelectedOptions] = useState<string[]>([])
|
||||||
@ -25,17 +27,17 @@ const Dropdown: React.FC<DropdownProps> = ({
|
|||||||
newSelectedOptions = [...selectedOptions, option]
|
newSelectedOptions = [...selectedOptions, option]
|
||||||
}
|
}
|
||||||
setSelectedOptions(newSelectedOptions)
|
setSelectedOptions(newSelectedOptions)
|
||||||
onSelectionChange(newSelectedOptions)
|
onSelectionChange(newSelectedOptions, filterType)
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectAll = () => {
|
const selectAll = () => {
|
||||||
setSelectedOptions(options)
|
setSelectedOptions(options)
|
||||||
onSelectionChange(options)
|
onSelectionChange(options, filterType)
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearAll = () => {
|
const clearAll = () => {
|
||||||
setSelectedOptions([])
|
setSelectedOptions([])
|
||||||
onSelectionChange([])
|
onSelectionChange([], filterType)
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggleDropdown = () => {
|
const toggleDropdown = () => {
|
||||||
@ -104,9 +106,11 @@ const DropdownHeader = styled.div<{ isExpanded: boolean }>`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 1px solid white;
|
|
||||||
background-color: ${({ isExpanded }) => (isExpanded ? 'white' : 'black')};
|
background-color: ${({ isExpanded }) => (isExpanded ? 'white' : 'black')};
|
||||||
color: ${({ isExpanded }) => (isExpanded ? 'black' : 'white')};
|
color: ${({ isExpanded }) => (isExpanded ? 'black' : 'white')};
|
||||||
|
|
||||||
|
border: 1px solid white;
|
||||||
|
border-left: none;
|
||||||
`
|
`
|
||||||
|
|
||||||
const Chevron = styled.span<{ isExpanded: boolean }>`
|
const Chevron = styled.span<{ isExpanded: boolean }>`
|
||||||
|
@ -14,6 +14,7 @@ const OFFSET = 18
|
|||||||
|
|
||||||
const OperatorGrid: React.FC<OperatorGridProps> = ({ data, isLoading }) => {
|
const OperatorGrid: React.FC<OperatorGridProps> = ({ data, isLoading }) => {
|
||||||
const [itemsCount, setItemsCount] = useState(18)
|
const [itemsCount, setItemsCount] = useState(18)
|
||||||
|
|
||||||
const observerRef = useRef<IntersectionObserver | null>(null)
|
const observerRef = useRef<IntersectionObserver | null>(null)
|
||||||
const lastElementRef = useRef<HTMLDivElement | null>(null)
|
const lastElementRef = useRef<HTMLDivElement | null>(null)
|
||||||
|
|
||||||
|
@ -3,33 +3,64 @@ import { OperatorGrid } from '@/components/Explore/OperatorGrid'
|
|||||||
import styled from '@emotion/styled'
|
import styled from '@emotion/styled'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import useGetOperators from '../../../apis/operators/useGetOperators'
|
import useGetOperators from '../../../apis/operators/useGetOperators'
|
||||||
|
import {
|
||||||
|
ARCHETYPE,
|
||||||
|
BACKGROUND,
|
||||||
|
COMP,
|
||||||
|
HELMET,
|
||||||
|
JACKET,
|
||||||
|
SKIN,
|
||||||
|
} from '../../../constants/operators'
|
||||||
import { Archetype } from '../../../types/operators'
|
import { Archetype } from '../../../types/operators'
|
||||||
import { processOperators } from '../../../utils/operators'
|
import { processOperators } from '../../../utils/operators'
|
||||||
|
|
||||||
interface ExploreSectionProps {}
|
interface ExploreSectionProps {}
|
||||||
|
|
||||||
// one of Archetype
|
|
||||||
const archetypes: Archetype[] = [
|
|
||||||
'Alchemist',
|
|
||||||
'Artisan',
|
|
||||||
'Explorer',
|
|
||||||
'Illuminator',
|
|
||||||
'Magician',
|
|
||||||
'Memetic',
|
|
||||||
'Oracle',
|
|
||||||
'Outlaw',
|
|
||||||
'Philosopher',
|
|
||||||
'Polymath',
|
|
||||||
]
|
|
||||||
|
|
||||||
const ExploreSection: React.FC<ExploreSectionProps> = () => {
|
const ExploreSection: React.FC<ExploreSectionProps> = () => {
|
||||||
const { data, isLoading } = useGetOperators()
|
const { data, isLoading } = useGetOperators()
|
||||||
const [selectedArchetypes, setSelectedArchetypes] = useState<Archetype[]>([])
|
|
||||||
|
|
||||||
const processedOperators = processOperators(data as any, selectedArchetypes)
|
const [filter, setFilter] = useState<{
|
||||||
|
archetype: Archetype[]
|
||||||
|
comp: string[]
|
||||||
|
skin: string[]
|
||||||
|
helmet: string[]
|
||||||
|
jacket: string[]
|
||||||
|
background: string[]
|
||||||
|
}>({
|
||||||
|
archetype: [],
|
||||||
|
comp: [],
|
||||||
|
skin: [],
|
||||||
|
helmet: [],
|
||||||
|
jacket: [],
|
||||||
|
background: [],
|
||||||
|
})
|
||||||
|
|
||||||
const handleSelectionChange = (selectedOptions: Archetype[]) => {
|
const processedOperators = processOperators(data as any, filter.archetype)
|
||||||
setSelectedArchetypes(selectedOptions)
|
|
||||||
|
const selectedOperators = processedOperators?.filter((operator) => {
|
||||||
|
// filter by comp, skin, helmet, jacket, background
|
||||||
|
return (
|
||||||
|
(filter.comp.length === 0 ||
|
||||||
|
filter.comp.includes(operator.comp as string)) &&
|
||||||
|
(filter.skin.length === 0 ||
|
||||||
|
filter.skin.includes(operator.skin as string)) &&
|
||||||
|
(filter.helmet.length === 0 ||
|
||||||
|
filter.helmet.includes(operator.helmet as string)) &&
|
||||||
|
(filter.jacket.length === 0 ||
|
||||||
|
filter.jacket.includes(operator.jacket as string)) &&
|
||||||
|
(filter.background.length === 0 ||
|
||||||
|
filter.background.includes(operator.background as string))
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleFilterChange = (
|
||||||
|
selectedOptions: string[],
|
||||||
|
filterType: string,
|
||||||
|
) => {
|
||||||
|
setFilter((prevFilter) => ({
|
||||||
|
...prevFilter,
|
||||||
|
[filterType]: selectedOptions,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -38,13 +69,44 @@ const ExploreSection: React.FC<ExploreSectionProps> = () => {
|
|||||||
<DropdownContainer>
|
<DropdownContainer>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
title="Archetype"
|
title="Archetype"
|
||||||
options={archetypes}
|
options={ARCHETYPE}
|
||||||
onSelectionChange={handleSelectionChange}
|
onSelectionChange={handleFilterChange}
|
||||||
|
filterType="archetype"
|
||||||
|
/>
|
||||||
|
<Dropdown
|
||||||
|
title="Comp"
|
||||||
|
options={COMP}
|
||||||
|
onSelectionChange={handleFilterChange}
|
||||||
|
filterType="comp"
|
||||||
|
/>
|
||||||
|
<Dropdown
|
||||||
|
title="Skin"
|
||||||
|
options={SKIN}
|
||||||
|
onSelectionChange={handleFilterChange}
|
||||||
|
filterType="skin"
|
||||||
|
/>
|
||||||
|
<Dropdown
|
||||||
|
title="Helmet"
|
||||||
|
options={HELMET}
|
||||||
|
onSelectionChange={handleFilterChange}
|
||||||
|
filterType="helmet"
|
||||||
|
/>
|
||||||
|
<Dropdown
|
||||||
|
title="Jacket"
|
||||||
|
options={JACKET}
|
||||||
|
onSelectionChange={handleFilterChange}
|
||||||
|
filterType="jacket"
|
||||||
|
/>
|
||||||
|
<Dropdown
|
||||||
|
title="Background"
|
||||||
|
options={BACKGROUND}
|
||||||
|
onSelectionChange={handleFilterChange}
|
||||||
|
filterType="background"
|
||||||
/>
|
/>
|
||||||
</DropdownContainer>
|
</DropdownContainer>
|
||||||
<OperatorGrid
|
<OperatorGrid
|
||||||
key={selectedArchetypes.join(',')}
|
key={selectedOperators?.join(',')}
|
||||||
data={processedOperators as any}
|
data={selectedOperators as any}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
@ -70,6 +132,10 @@ const DropdownContainer = styled.div`
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: 70px;
|
margin-top: 70px;
|
||||||
|
|
||||||
|
& > div:first-of-type {
|
||||||
|
border-left: 1px solid white;
|
||||||
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export default ExploreSection
|
export default ExploreSection
|
||||||
|
Loading…
x
Reference in New Issue
Block a user