misc search ui improvements!
This commit is contained in:
parent
5e3071db4f
commit
49718a96f7
2 changed files with 43 additions and 6 deletions
|
@ -30,8 +30,13 @@ function SearchResults({ query, outfitState, dispatchToOutfit }) {
|
||||||
const { speciesId, colorId } = outfitState;
|
const { speciesId, colorId } = outfitState;
|
||||||
|
|
||||||
const debouncedQuery = useDebounce(query, 300, { waitForFirstPause: true });
|
const debouncedQuery = useDebounce(query, 300, { waitForFirstPause: true });
|
||||||
|
const [isEndOfResults, setIsEndOfResults] = React.useState(false);
|
||||||
|
|
||||||
const { loading, error, data, fetchMore, variables } = useQuery(
|
React.useEffect(() => {
|
||||||
|
setIsEndOfResults(false);
|
||||||
|
}, [query]);
|
||||||
|
|
||||||
|
const { loading, error, data, fetchMore } = useQuery(
|
||||||
gql`
|
gql`
|
||||||
query($query: String!, $speciesId: ID!, $colorId: ID!, $offset: Int!) {
|
query($query: String!, $speciesId: ID!, $colorId: ID!, $offset: Int!) {
|
||||||
itemSearchToFit(
|
itemSearchToFit(
|
||||||
|
@ -70,6 +75,12 @@ function SearchResults({ query, outfitState, dispatchToOutfit }) {
|
||||||
variables: { query: debouncedQuery, speciesId, colorId, offset: 0 },
|
variables: { query: debouncedQuery, speciesId, colorId, offset: 0 },
|
||||||
skip: debouncedQuery === null,
|
skip: debouncedQuery === null,
|
||||||
notifyOnNetworkStatusChange: true,
|
notifyOnNetworkStatusChange: true,
|
||||||
|
onCompleted: (d) => {
|
||||||
|
const items = d && d.itemSearchToFit && d.itemSearchToFit.items;
|
||||||
|
if (items && items.length < 30) {
|
||||||
|
setIsEndOfResults(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -78,13 +89,27 @@ function SearchResults({ query, outfitState, dispatchToOutfit }) {
|
||||||
const items = (result && result.items) || [];
|
const items = (result && result.items) || [];
|
||||||
|
|
||||||
const onScrolledToBottom = React.useCallback(() => {
|
const onScrolledToBottom = React.useCallback(() => {
|
||||||
if (!loading) {
|
if (!loading && !isEndOfResults) {
|
||||||
fetchMore({
|
fetchMore({
|
||||||
variables: {
|
variables: {
|
||||||
offset: items.length,
|
offset: items.length,
|
||||||
},
|
},
|
||||||
updateQuery: (prev, { fetchMoreResult }) => {
|
updateQuery: (prev, { fetchMoreResult }) => {
|
||||||
if (!fetchMoreResult) return prev;
|
if (!fetchMoreResult) return prev;
|
||||||
|
|
||||||
|
// Note: This is a bit awkward because, if the results count ends on
|
||||||
|
// a multiple of 30, the user will see a flash of loading before
|
||||||
|
// getting told it's actually the end. Ah well :/
|
||||||
|
//
|
||||||
|
// We could maybe make this more rigorous later with
|
||||||
|
// react-virtualized to have a better scrollbar anyway, and then
|
||||||
|
// we'd need to return the total result count... a bit annoying to
|
||||||
|
// potentially double the query runtime? We'd need to see how slow it
|
||||||
|
// actually makes things.
|
||||||
|
if (fetchMoreResult.itemSearchToFit.items.length < 30) {
|
||||||
|
setIsEndOfResults(true);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
itemSearchToFit: {
|
itemSearchToFit: {
|
||||||
|
@ -98,7 +123,7 @@ function SearchResults({ query, outfitState, dispatchToOutfit }) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [loading, fetchMore, items.length]);
|
}, [loading, isEndOfResults, fetchMore, items.length]);
|
||||||
|
|
||||||
if (resultQuery !== query || (loading && items.length === 0)) {
|
if (resultQuery !== query || (loading && items.length === 0)) {
|
||||||
return (
|
return (
|
||||||
|
@ -144,7 +169,7 @@ function SearchResults({ query, outfitState, dispatchToOutfit }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ScrollTracker({ children, threshold, onScrolledToBottom }) {
|
function ScrollTracker({ children, query, threshold, onScrolledToBottom }) {
|
||||||
const containerRef = React.useRef();
|
const containerRef = React.useRef();
|
||||||
const scrollParent = React.useRef();
|
const scrollParent = React.useRef();
|
||||||
|
|
||||||
|
@ -167,7 +192,7 @@ function ScrollTracker({ children, threshold, onScrolledToBottom }) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (let el = containerRef.current; el.parentNode; el = el.parentNode) {
|
for (let el = containerRef.current; el.parentNode; el = el.parentNode) {
|
||||||
if (el.scrollHeight > el.clientHeight) {
|
if (getComputedStyle(el).overflow === "auto") {
|
||||||
scrollParent.current = el;
|
scrollParent.current = el;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ function WardrobePage() {
|
||||||
const { loading, error, outfitState, dispatchToOutfit } = useOutfitState();
|
const { loading, error, outfitState, dispatchToOutfit } = useOutfitState();
|
||||||
const [searchQuery, setSearchQuery] = React.useState("");
|
const [searchQuery, setSearchQuery] = React.useState("");
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
const searchContainerRef = React.useRef();
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -34,6 +35,12 @@ function WardrobePage() {
|
||||||
}
|
}
|
||||||
}, [error, toast]);
|
}, [error, toast]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (searchContainerRef.current) {
|
||||||
|
searchContainerRef.current.scrollTop = 0;
|
||||||
|
}
|
||||||
|
}, [searchQuery]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box position="absolute" top="0" bottom="0" left="0" right="0">
|
<Box position="absolute" top="0" bottom="0" left="0" right="0">
|
||||||
<Grid
|
<Grid
|
||||||
|
@ -67,7 +74,12 @@ function WardrobePage() {
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{searchQuery ? (
|
{searchQuery ? (
|
||||||
<Box gridArea="items" overflow="auto" key="search-panel">
|
<Box
|
||||||
|
gridArea="items"
|
||||||
|
overflow="auto"
|
||||||
|
key="search-panel"
|
||||||
|
ref={searchContainerRef}
|
||||||
|
>
|
||||||
<Box px="5" py="5">
|
<Box px="5" py="5">
|
||||||
<SearchPanel
|
<SearchPanel
|
||||||
query={searchQuery}
|
query={searchQuery}
|
||||||
|
|
Loading…
Reference in a new issue