Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added location-based quick filters #26

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
166 changes: 166 additions & 0 deletions src/components/Filter/Filter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import React, { useState, useEffect, useMemo } from 'react';
import { Flex, Button } from '@chakra-ui/core';
import Fuse from 'fuse.js';

export interface FilterProps {
collection: unknown[];
onSearch: (results: any[]) => void;
}

const Filter = ({ onSearch, collection }: FilterProps) => {
const areaList = [
{ name: 'HF/LLR', query: ['HF', 'LLR'] },
{ name: 'Castle/Market', query: ['Market', 'ToT', 'HC', 'OGC'] },
{ name: 'KF/LW', query: ['KF', 'LW', 'Deku Theater', 'SFM'] },
{ name: 'Kak', query: ['Kak', 'Graveyard'] },
{ name: 'DM/GC', query: ['DMT', 'GC', 'DMC'] },
{ name: 'ZR/ZD/ZF', query: ['ZR', 'ZD', 'ZF'] },
{ name: 'LH', query: ['LH'] },
{ name: 'GD', query: ['GV', 'GF', 'Wasteland', 'Colossus'] },
];
const dungeonList = [
{ name: 'Deku Tree', query: ['Queen Gohma', 'Deku Tree'] },
{ name: 'Dodongo', query: ['King Dodongo', 'Dodongos Cavern'] },
{ name: 'Jabu Jabu', query: ['Barinade', 'Jabu Jabus Belly '] },
{ name: 'Forest', query: ['Phantom Ganon', 'Forest Temple '] },
{ name: 'Fire', query: ['Volvagia', 'Fire Temple'] },
{ name: 'Ice Cavern', query: ['Ice Cavern'] },
{ name: 'Water', query: ['Morpha', 'Water Temple '] },
{ name: 'BotW', query: ['Bottom of the Well'] },
{ name: 'Shadow', query: ['Bongo Bongo', 'Shadow Temple'] },
{ name: 'GTG', query: ['Gerudo Training Ground'] },
{ name: 'Spirit', query: ['Twinrova', 'Spirit Temple'] },
{ name: "Ganon's Castle", query: ['Ganons Castle'] },
];
const songQuery = ['song', 'sheik'];

const [query, setQuery] = useState(''),
serializedCollection = JSON.stringify(collection),
fuse = useMemo(
() =>
new Fuse(collection, {
useExtendedSearch: true,
keys: ['location'],
threshold: 0.25,
}),
[collection]
),
searchResult = useMemo(
() =>
JSON.stringify(fuse.search(query).map((result) => result.item)),
[fuse, query]
);

useEffect(() => {
onSearch(
!!query
? JSON.parse(searchResult)
: JSON.parse(serializedCollection)
);
}, [onSearch, searchResult, serializedCollection, query]);

const loopQuery = (queries: string[]) => {
let searchString = '';
queries.forEach((e, i) => {
if (i === 0) {
searchString = `^${e}`;
} else {
searchString = `${searchString} | ^${e}`;
}
});
setQuery(searchString);
};

const handleClick = (queries: string[]) => {
if (query.startsWith(`^${queries[0]}`)) {
setQuery('');
} else {
loopQuery(queries);
}
};

return (
<Flex
marginTop={[1, 0]}
marginBottom={[2, 3]}
width="100%"
direction="column"
>
<Flex wrap="wrap" direction="column">
<b>Areas</b>

<Flex marginTop={[1, 1]} wrap="wrap">
{areaList.map((e) => {
return (
<Button
marginRight={[2, 2]}
marginBottom={[2, 2]}
_hover={{
color: 'white',
backgroundColor: 'blue.600',
}}
_active={{
color: 'white',
backgroundColor: 'blue.700',
}}
key={e.name}
onClick={() => {
handleClick(e.query);
}}
>
{e.name}
</Button>
);
})}
</Flex>
</Flex>
<Flex wrap="wrap" direction="column">
<b>Dungeons</b>
<Flex marginTop={[1, 1]} wrap="wrap">
{dungeonList.map((e) => {
return (
<Button
marginRight={[2, 2]}
marginBottom={[2, 2]}
_hover={{
color: 'white',
backgroundColor: 'blue.600',
}}
_active={{
color: 'white',
backgroundColor: 'blue.700',
}}
key={e.name}
onClick={() => {
handleClick(e.query);
}}
>
{e.name}
</Button>
);
})}
</Flex>
</Flex>
<Flex direction="column" align="start">
<Button
marginTop={[4, 4]}
_hover={{
color: 'white',
backgroundColor: 'blue.600',
}}
_active={{
color: 'white',
backgroundColor: 'blue.700',
}}
onClick={() => {
handleClick(songQuery);
}}
>
<b>Songs</b>
</Button>
</Flex>
</Flex>
);
};

export { Filter };
1 change: 1 addition & 0 deletions src/components/Filter/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Filter } from './Filter';
6 changes: 6 additions & 0 deletions src/components/ItemList/ItemList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ import {
import { useMediaQuery } from 'react-responsive';
import sortBy from 'lodash/sortBy';
import { Item as IItem } from '../../types/Item';
import { Filter } from '../Filter';

interface ItemListProps {
title?: string;
itemList: IItem[];
hideSearch?: boolean;
hideFilter?: boolean;
disablePagination?: boolean;
hideSpoilers?: boolean;
}
Expand All @@ -31,6 +33,7 @@ const ItemList = ({
title = 'Items',
itemList,
hideSearch = false,
hideFilter = false,
disablePagination = false,
hideSpoilers = false,
}: ItemListProps) => {
Expand Down Expand Up @@ -90,6 +93,9 @@ const ItemList = ({
</Box>
)}
</Flex>
{!hideFilter && (
<Filter collection={sortedData} onSearch={setFilteredData} />
)}
<Grid
templateColumns={`repeat(auto-fill, minmax(${
isMobile ? '1fr' : '350px'
Expand Down
1 change: 1 addition & 0 deletions src/features/Dashboard/Playthrough/Playthrough.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const Playthrough = ({
title={`Sphere ${step.sphere}`}
itemList={step.items}
hideSearch
hideFilter
disablePagination
hideSpoilers={hideSpoilers}
/>
Expand Down