2021-07-06 20:41:47 +00:00
|
|
|
import React, { useMemo, useState } from "react";
|
|
|
|
import Fuse from "fuse.js";
|
|
|
|
|
2021-07-09 03:10:04 +00:00
|
|
|
import { Button, Center, Heading, Icon, Input } from "@chakra-ui/react";
|
2021-07-06 20:41:47 +00:00
|
|
|
import { FaUserCircle, FaArrowAltCircleRight } from "react-icons/fa";
|
|
|
|
import { Link } from "react-router-dom";
|
2021-07-09 03:10:04 +00:00
|
|
|
import { AutoSizer, WindowScroller, List } from "react-virtualized";
|
2021-07-09 05:01:42 +00:00
|
|
|
import prettifyStatisticName from "./PrettifyStatisticName";
|
2021-07-06 20:41:47 +00:00
|
|
|
|
|
|
|
const Search = ({ statistics, players }) => {
|
|
|
|
const [searchTerm, setSearchTerm] = useState("");
|
|
|
|
|
|
|
|
const searchEngine = useMemo(() => {
|
|
|
|
const fullList = statistics
|
|
|
|
.map((s) => {
|
|
|
|
return {
|
|
|
|
type: "statistic",
|
|
|
|
value: s,
|
2021-07-09 05:01:42 +00:00
|
|
|
searchTerm: prettifyStatisticName(s.type, s.name),
|
2021-07-06 20:41:47 +00:00
|
|
|
};
|
|
|
|
})
|
|
|
|
.concat(
|
|
|
|
players.map((p) => {
|
|
|
|
return {
|
|
|
|
type: "player",
|
|
|
|
value: p,
|
|
|
|
searchTerm: p.name,
|
|
|
|
};
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
return new Fuse(fullList, {
|
|
|
|
minMatchCharLength: 3,
|
|
|
|
ignoreLocation: true,
|
|
|
|
shouldSort: true,
|
|
|
|
keys: ["searchTerm"],
|
|
|
|
});
|
|
|
|
}, [statistics, players]);
|
|
|
|
|
|
|
|
const searchResults = useMemo(() => {
|
|
|
|
return searchEngine.search(`'"${searchTerm}"'`);
|
|
|
|
}, [searchEngine, searchTerm]);
|
|
|
|
|
2021-07-09 03:10:04 +00:00
|
|
|
const renderRow = ({
|
|
|
|
index, // Index of row
|
|
|
|
isScrolling, // The List is currently being scrolled
|
|
|
|
isVisible, // This row is visible within the List (eg it is not an overscanned row)
|
|
|
|
key, // Unique key within array of rendered rows
|
|
|
|
parent, // Reference to the parent List (instance)
|
|
|
|
style, // Style object to be applied to row (to position it);
|
|
|
|
// This must be passed through to the rendered row element.
|
|
|
|
}) => {
|
|
|
|
const x = searchResults[index];
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Link
|
|
|
|
key={
|
|
|
|
x.item.type === "player"
|
|
|
|
? `/${x.item.type}/${x.item.value.id}`
|
|
|
|
: `/${x.item.type}/${x.item.value.type}/${x.item.value.name}`
|
|
|
|
}
|
|
|
|
to={
|
|
|
|
x.item.type === "player"
|
|
|
|
? `/${x.item.type}/${x.item.value.id}`
|
|
|
|
: `/${x.item.type}/${x.item.value.type}/${x.item.value.name}`
|
|
|
|
}
|
|
|
|
style={style}
|
|
|
|
>
|
|
|
|
<Button
|
|
|
|
size="sm"
|
|
|
|
leftIcon={
|
|
|
|
x.item.type === "player" ? (
|
|
|
|
<Icon as={FaUserCircle} />
|
|
|
|
) : (
|
|
|
|
<Icon as={FaArrowAltCircleRight} transform="rotate(-45deg)" />
|
|
|
|
)
|
|
|
|
}
|
|
|
|
variant="ghost"
|
|
|
|
my="0.5"
|
|
|
|
display="block"
|
|
|
|
textAlign="left"
|
|
|
|
width="100%"
|
|
|
|
>
|
|
|
|
{x.item.searchTerm}
|
|
|
|
</Button>
|
|
|
|
</Link>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2021-07-06 20:41:47 +00:00
|
|
|
return (
|
2021-07-09 03:10:04 +00:00
|
|
|
<WindowScroller>
|
|
|
|
{({ height, isScrolling, onChildScroll, scrollTop, registerChild }) => (
|
|
|
|
<>
|
|
|
|
<Heading as="h1" size="4xl" my="8">
|
|
|
|
<Center>📈</Center>
|
|
|
|
</Heading>
|
|
|
|
<Input
|
|
|
|
placeholder="Find statistics or players"
|
|
|
|
size="lg"
|
|
|
|
variant="filled"
|
|
|
|
value={searchTerm}
|
|
|
|
onChange={(event) => setSearchTerm(event.target.value)}
|
|
|
|
/>
|
|
|
|
<div ref={registerChild}>
|
|
|
|
<AutoSizer disableHeight>
|
|
|
|
{({ width }) => (
|
|
|
|
<List
|
|
|
|
autoHeight
|
|
|
|
height={height}
|
|
|
|
isScrolling={isScrolling}
|
|
|
|
onScroll={onChildScroll}
|
|
|
|
scrollTop={scrollTop}
|
|
|
|
rowCount={searchResults.length}
|
|
|
|
rowHeight={36}
|
|
|
|
rowRenderer={renderRow}
|
|
|
|
width={width}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</AutoSizer>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</WindowScroller>
|
2021-07-06 20:41:47 +00:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default Search;
|