Category linking update #172
@ -8,6 +8,7 @@ import {
|
|||||||
flattenCategories
|
flattenCategories
|
||||||
} from 'utils'
|
} from 'utils'
|
||||||
import { useLocalStorage } from 'hooks'
|
import { useLocalStorage } from 'hooks'
|
||||||
|
import { useSearchParams } from 'react-router-dom'
|
||||||
import styles from './CategoryFilterPopup.module.scss'
|
import styles from './CategoryFilterPopup.module.scss'
|
||||||
import categoriesData from './../../assets/categories/categories.json'
|
import categoriesData from './../../assets/categories/categories.json'
|
||||||
|
|
||||||
@ -26,15 +27,32 @@ export const CategoryFilterPopup = ({
|
|||||||
setHierarchies,
|
setHierarchies,
|
||||||
handleClose
|
handleClose
|
||||||
}: CategoryFilterPopupProps) => {
|
}: CategoryFilterPopupProps) => {
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams()
|
||||||
|
const linkedHierarchy = searchParams.get('h')
|
||||||
|
|
||||||
const [userHierarchies, setUserHierarchies] = useLocalStorage<
|
const [userHierarchies, setUserHierarchies] = useLocalStorage<
|
||||||
(string | Category)[]
|
(string | Category)[]
|
||||||
>('user-hierarchies', [])
|
>('user-hierarchies', [])
|
||||||
const [filterCategories, setFilterCategories] = useState(categories)
|
const [filterCategories, setFilterCategories] = useState(categories)
|
||||||
const [filterHierarchies, setFilterHierarchies] = useState(hierarchies)
|
const [filterHierarchies, setFilterHierarchies] = useState(hierarchies)
|
||||||
const handleApply = () => {
|
const handleApply = () => {
|
||||||
setCategories(filterCategories)
|
// Update selection with linked category if it exists
|
||||||
|
if (linkedHierarchy !== null && linkedHierarchy !== '') {
|
||||||
|
// Combine existing selection with the linked
|
||||||
|
setFilterHierarchies((prev) => {
|
||||||
|
prev.push(linkedHierarchy)
|
||||||
|
const newFilterHierarchies = Array.from(new Set([...prev]))
|
||||||
|
setHierarchies(newFilterHierarchies)
|
||||||
|
return newFilterHierarchies
|
||||||
|
})
|
||||||
|
// Clear hierarchy link in search params
|
||||||
|
searchParams.delete('h')
|
||||||
|
setSearchParams(searchParams)
|
||||||
|
} else {
|
||||||
setHierarchies(filterHierarchies)
|
setHierarchies(filterHierarchies)
|
||||||
}
|
}
|
||||||
|
setCategories(filterCategories)
|
||||||
|
}
|
||||||
const [inputValue, setInputValue] = useState<string>('')
|
const [inputValue, setInputValue] = useState<string>('')
|
||||||
const userHierarchiesMatching = useMemo(
|
const userHierarchiesMatching = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@ -290,6 +308,11 @@ export const CategoryFilterPopup = ({
|
|||||||
className='btn btnMain btnMainPopup'
|
className='btn btnMain btnMainPopup'
|
||||||
type='button'
|
type='button'
|
||||||
onPointerDown={() => {
|
onPointerDown={() => {
|
||||||
|
// Clear the linked hierarchy
|
||||||
|
searchParams.delete('h')
|
||||||
|
setSearchParams(searchParams)
|
||||||
|
|
||||||
|
// Clear current filters
|
||||||
setFilterCategories([])
|
setFilterCategories([])
|
||||||
setFilterHierarchies([])
|
setFilterHierarchies([])
|
||||||
}}
|
}}
|
||||||
@ -340,11 +363,14 @@ const CategoryCheckbox: React.FC<CategoryCheckboxProps> = ({
|
|||||||
indentLevel = 0,
|
indentLevel = 0,
|
||||||
handleRemove
|
handleRemove
|
||||||
}) => {
|
}) => {
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams()
|
||||||
|
const linkedHierarchy = searchParams.get('h')
|
||||||
const name = typeof category === 'string' ? category : category.name
|
const name = typeof category === 'string' ? category : category.name
|
||||||
const isMatching = path
|
const hierarchy = path.join(' > ').toLowerCase()
|
||||||
.join(' > ')
|
const isMatching = hierarchy.includes(inputValue.toLowerCase())
|
||||||
.toLowerCase()
|
const isLinked =
|
||||||
.includes(inputValue.toLowerCase())
|
linkedHierarchy !== null &&
|
||||||
|
hierarchy === linkedHierarchy.replace(/:/g, ' > ')
|
||||||
const [isSingleChecked, setIsSingleChecked] = useState<boolean>(false)
|
const [isSingleChecked, setIsSingleChecked] = useState<boolean>(false)
|
||||||
const [isCombinationChecked, setIsCombinationChecked] =
|
const [isCombinationChecked, setIsCombinationChecked] =
|
||||||
useState<boolean>(false)
|
useState<boolean>(false)
|
||||||
@ -390,9 +416,15 @@ const CategoryCheckbox: React.FC<CategoryCheckboxProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleCombinationChange = () => {
|
const handleCombinationChange = () => {
|
||||||
|
// If combination is linked, clicking it again we will delete it
|
||||||
|
if (isLinked) {
|
||||||
|
searchParams.delete('h')
|
||||||
|
setSearchParams(searchParams)
|
||||||
|
} else {
|
||||||
setIsCombinationChecked(!isCombinationChecked)
|
setIsCombinationChecked(!isCombinationChecked)
|
||||||
handleCombinationSelection(path, !isCombinationChecked)
|
handleCombinationSelection(path, !isCombinationChecked)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -421,7 +453,7 @@ const CategoryCheckbox: React.FC<CategoryCheckboxProps> = ({
|
|||||||
className={`CheckboxMain ${
|
className={`CheckboxMain ${
|
||||||
isIndeterminate ? 'CheckboxIndeterminate' : ''
|
isIndeterminate ? 'CheckboxIndeterminate' : ''
|
||||||
}`}
|
}`}
|
||||||
checked={isCombinationChecked}
|
checked={isCombinationChecked || isLinked}
|
||||||
onChange={handleCombinationChange}
|
onChange={handleCombinationChange}
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
|
@ -237,40 +237,6 @@ export const GamePage = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ModFilter>
|
<ModFilter>
|
||||||
{linkedHierarchy && linkedHierarchy !== '' ? (
|
|
||||||
<span
|
|
||||||
className='IBMSMSMBSSTagsTag'
|
|
||||||
style={{
|
|
||||||
display: 'flex',
|
|
||||||
gap: '10px',
|
|
||||||
alignItems: 'center'
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
searchParams.delete('h')
|
|
||||||
setSearchParams(searchParams)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns='http://www.w3.org/2000/svg'
|
|
||||||
viewBox='0 0 576 512'
|
|
||||||
width='1em'
|
|
||||||
height='1em'
|
|
||||||
fill='currentColor'
|
|
||||||
>
|
|
||||||
<path d='M 3.9,22.9 C 10.5,8.9 24.5,0 40,0 h 432 c 15.5,0 29.5,8.9 36.1,22.9 6.6,14 4.6,30.5 -5.2,42.5 L 396.4,195.6 C 316.2,212.1 256,283 256,368 c 0,27.4 6.3,53.4 17.5,76.5 -1.6,-0.8 -3.2,-1.8 -4.7,-2.9 l -64,-48 C 196.7,387.6 192,378.1 192,368 V 288.9 L 9,65.3 C -0.7,53.4 -2.8,36.8 3.9,22.9 Z M 432,224 c 79.52906,0 143.99994,64.471 143.99994,144 0,79.529 -64.47088,144 -143.99994,144 -79.52906,0 -143.99994,-64.471 -143.99994,-144 0,-79.529 64.47088,-144 143.99994,-144 z' />
|
|
||||||
</svg>
|
|
||||||
{linkedHierarchy.replace(/:/g, ' > ')}
|
|
||||||
<svg
|
|
||||||
xmlns='http://www.w3.org/2000/svg'
|
|
||||||
viewBox='0 0 512 512'
|
|
||||||
width='0.8em'
|
|
||||||
height='0.8em'
|
|
||||||
fill='currentColor'
|
|
||||||
>
|
|
||||||
<path d='M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM175 175c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z' />
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<div className='FiltersMainElement'>
|
<div className='FiltersMainElement'>
|
||||||
<button
|
<button
|
||||||
className='btn btnMain btnMainDropdown'
|
className='btn btnMain btnMainDropdown'
|
||||||
@ -280,7 +246,8 @@ export const GamePage = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Categories
|
Categories
|
||||||
{isCategoryFilterActive ? (
|
{isCategoryFilterActive ||
|
||||||
|
(linkedHierarchy && linkedHierarchy !== '') ? (
|
||||||
<svg
|
<svg
|
||||||
xmlns='http://www.w3.org/2000/svg'
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
viewBox='0 0 576 512'
|
viewBox='0 0 576 512'
|
||||||
@ -303,7 +270,6 @@ export const GamePage = () => {
|
|||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</ModFilter>
|
</ModFilter>
|
||||||
|
|
||||||
<div className='IBMSecMain IBMSMListWrapper'>
|
<div className='IBMSecMain IBMSMListWrapper'>
|
||||||
|
@ -553,6 +553,7 @@ const Body = ({
|
|||||||
return (
|
return (
|
||||||
<ReactRouterLink
|
<ReactRouterLink
|
||||||
className='IBMSMSMBSSCategoriesBoxItem'
|
className='IBMSMSMBSSCategoriesBoxItem'
|
||||||
|
key={`category-${i}`}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
to={{
|
to={{
|
||||||
pathname: getGamePageRoute(game),
|
pathname: getGamePageRoute(game),
|
||||||
@ -563,9 +564,12 @@ const Body = ({
|
|||||||
</ReactRouterLink>
|
</ReactRouterLink>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.reduce((prev, curr) => [
|
.reduce((prev, curr, i) => [
|
||||||
prev,
|
prev,
|
||||||
<div className='IBMSMSMBSSCategoriesBoxSeparator'>
|
<div
|
||||||
|
key={`separator-${i}`}
|
||||||
|
className='IBMSMSMBSSCategoriesBoxSeparator'
|
||||||
|
>
|
||||||
<p>></p>
|
<p>></p>
|
||||||
</div>,
|
</div>,
|
||||||
curr
|
curr
|
||||||
|
Loading…
x
Reference in New Issue
Block a user