impress/app/javascript/wardrobe-2020/WardrobePage/useSearchResults.js
Emi Matchu fc71f5b5a5 Filter by Alt Style in item search and item appearance API calls
I'm not planning to port full Alt Style support over to the 2020
frontend, I really am winding that down, but adding a couple lil API
parameters are *by far* the easiest way to get Alt Styles working in
the main app because of how it calls the 2020 API. So here we are, just
using new parameters for DTI 2020 that I'm gonna deploy to impress-2020
first!
2024-02-01 04:58:30 -08:00

143 lines
4.1 KiB
JavaScript

import gql from "graphql-tag";
import { useQuery } from "@apollo/client";
import { useDebounce } from "../util";
import { emptySearchQuery } from "./SearchToolbar";
import { itemAppearanceFragment } from "../components/useOutfitAppearance";
import { SEARCH_PER_PAGE } from "./SearchPanel";
/**
* useSearchResults manages the actual querying and state management of search!
*/
export function useSearchResults(
query,
outfitState,
currentPageNumber,
{ skip = false } = {},
) {
const { speciesId, colorId, altStyleId } = outfitState;
// We debounce the search query, so that we don't resend a new query whenever
// the user types anything.
const debouncedQuery = useDebounce(query, 300, {
waitForFirstPause: true,
initialValue: emptySearchQuery,
});
// NOTE: This query should always load ~instantly, from the client cache.
const { data: zoneData } = useQuery(gql`
query SearchPanelZones {
allZones {
id
label
}
}
`);
const allZones = zoneData?.allZones || [];
const filterToZones = query.filterToZoneLabel
? allZones.filter((z) => z.label === query.filterToZoneLabel)
: [];
const filterToZoneIds = filterToZones.map((z) => z.id);
const currentPageIndex = currentPageNumber - 1;
const offset = currentPageIndex * SEARCH_PER_PAGE;
// Here's the actual GQL query! At the bottom we have more config than usual!
const {
loading: loadingGQL,
error,
data,
} = useQuery(
gql`
query SearchPanel(
$query: String!
$fitsPet: FitsPetSearchFilter
$itemKind: ItemKindSearchFilter
$currentUserOwnsOrWants: OwnsOrWants
$zoneIds: [ID!]!
$speciesId: ID!
$colorId: ID!
$altStyleId: ID
$offset: Int!
$perPage: Int!
) {
itemSearch: itemSearchV2(
query: $query
fitsPet: $fitsPet
itemKind: $itemKind
currentUserOwnsOrWants: $currentUserOwnsOrWants
zoneIds: $zoneIds
) {
id
numTotalItems
items(offset: $offset, limit: $perPage) {
# TODO: De-dupe this from useOutfitState?
id
name
thumbnailUrl
isNc
isPb
currentUserOwnsThis
currentUserWantsThis
appearanceOn(
speciesId: $speciesId
colorId: $colorId
altStyleId: $altStyleId
) {
# This enables us to quickly show the item when the user clicks it!
...ItemAppearanceForOutfitPreview
# This is used to group items by zone, and to detect conflicts when
# wearing a new item.
layers {
zone {
id
label
}
}
restrictedZones {
id
label
isCommonlyUsedByItems
}
}
}
}
}
${itemAppearanceFragment}
`,
{
variables: {
query: debouncedQuery.value,
fitsPet: { speciesId, colorId, altStyleId },
itemKind: debouncedQuery.filterToItemKind,
currentUserOwnsOrWants: debouncedQuery.filterToCurrentUserOwnsOrWants,
zoneIds: filterToZoneIds,
speciesId,
colorId,
altStyleId,
offset,
perPage: SEARCH_PER_PAGE,
},
context: { sendAuth: true },
skip:
skip ||
(!debouncedQuery.value &&
!debouncedQuery.filterToItemKind &&
!debouncedQuery.filterToZoneLabel &&
!debouncedQuery.filterToCurrentUserOwnsOrWants),
onError: (e) => {
console.error("Error loading search results", e);
},
// Return `numTotalItems` from the GQL cache while waiting for next page!
returnPartialData: true,
},
);
const loading = debouncedQuery !== query || loadingGQL;
const items = data?.itemSearch?.items ?? [];
const numTotalItems = data?.itemSearch?.numTotalItems ?? null;
const numTotalPages = Math.ceil(numTotalItems / SEARCH_PER_PAGE);
return { loading, error, items, numTotalPages };
}