From a9d50bd0c324dfe0cf2086f31200ba5dcaf8ac80 Mon Sep 17 00:00:00 2001 From: Matt Dunn-Rankin Date: Fri, 24 Apr 2020 19:16:24 -0700 Subject: [PATCH] stop using hardcoded items entirely! --- src/OutfitPreview.js | 10 +++--- src/WardrobePage.js | 38 +++++++++++---------- src/data.js | 56 ------------------------------- src/useItemData.js | 13 +++----- src/useOutfitState.js | 77 +++++++++++++++++++++++++++---------------- 5 files changed, 80 insertions(+), 114 deletions(-) delete mode 100644 src/data.js diff --git a/src/OutfitPreview.js b/src/OutfitPreview.js index b26185d..dce292c 100644 --- a/src/OutfitPreview.js +++ b/src/OutfitPreview.js @@ -8,10 +8,12 @@ import { Delay } from "./util"; import "./OutfitPreview.css"; -function OutfitPreview({ itemIds, speciesId, colorId }) { +function OutfitPreview({ outfitState }) { + const { wornItemIds, speciesId, colorId } = outfitState; + const { loading, error, data } = useQuery( gql` - query($itemIds: [ID!]!, $speciesId: ID!, $colorId: ID!) { + query($wornItemIds: [ID!]!, $speciesId: ID!, $colorId: ID!) { petAppearance(speciesId: $speciesId, colorId: $colorId) { layers { id @@ -27,7 +29,7 @@ function OutfitPreview({ itemIds, speciesId, colorId }) { } } - items(ids: $itemIds) { + items(ids: $wornItemIds) { id appearanceOn(speciesId: $speciesId, colorId: $colorId) { layers { @@ -47,7 +49,7 @@ function OutfitPreview({ itemIds, speciesId, colorId }) { } `, { - variables: { itemIds, speciesId, colorId }, + variables: { wornItemIds, speciesId, colorId }, } ); diff --git a/src/WardrobePage.js b/src/WardrobePage.js index f59184c..6c0ade6 100644 --- a/src/WardrobePage.js +++ b/src/WardrobePage.js @@ -19,7 +19,6 @@ import { useToast, } from "@chakra-ui/core"; -import { ITEMS } from "./data"; import ItemList, { ItemListSkeleton } from "./ItemList"; import useItemData from "./useItemData"; import useOutfitState from "./useOutfitState.js"; @@ -27,7 +26,7 @@ import OutfitPreview from "./OutfitPreview"; import { Delay } from "./util"; function WardrobePage() { - const { loading, error, data, dispatch: dispatchToOutfit } = useOutfitState(); + const { loading, error, outfitState, dispatchToOutfit } = useOutfitState(); const [searchQuery, setSearchQuery] = React.useState(""); const toast = useToast(); @@ -67,11 +66,7 @@ function WardrobePage() { width="100%" > - + @@ -83,13 +78,13 @@ function WardrobePage() { {searchQuery ? ( ) : ( )} @@ -135,8 +130,13 @@ function SearchToolbar({ query, onChange }) { ); } -function SearchPanel({ query, wornItemIds, dispatchToOutfit }) { - const { loading, error, itemsById } = useItemData(ITEMS.map((i) => i.id)); +function SearchPanel({ query, outfitState, dispatchToOutfit }) { + const { allItemIds, wornItemIds, speciesId, colorId } = outfitState; + const { loading, error, itemsById } = useItemData( + allItemIds, + speciesId, + colorId + ); const normalize = (s) => s.toLowerCase(); const results = Object.values(itemsById).filter((item) => @@ -172,7 +172,7 @@ function SearchResults({ if (error) { return ( - We hit an error trying to load your search results + We hit an error trying to load your search results{" "} 😓 {" "} @@ -202,7 +202,9 @@ function SearchResults({ ); } -function ItemsPanel({ zonesAndItems, loading, dispatchToOutfit }) { +function ItemsPanel({ outfitState, loading, dispatchToOutfit }) { + const { zonesAndItems, wornItemIds } = outfitState; + return ( @@ -217,12 +219,14 @@ function ItemsPanel({ zonesAndItems, loading, dispatchToOutfit }) { ))} {!loading && - zonesAndItems.map(({ zoneName, items, wornItemId }) => ( - - {zoneName} + zonesAndItems.map(({ zone, items }) => ( + + {zone.label} i.id) + .filter((id) => wornItemIds.includes(id))} dispatchToOutfit={dispatchToOutfit} /> diff --git a/src/data.js b/src/data.js deleted file mode 100644 index 52d9313..0000000 --- a/src/data.js +++ /dev/null @@ -1,56 +0,0 @@ -export const ITEMS = [ - { - id: "38913", - // name: "Zafara Agent Gloves", - // thumbnailSrc: "http://images.neopets.com/items/clo_zafara_agent_gloves.gif", - zoneName: "Gloves", - }, - { - id: "38911", - // name: "Zafara Agent Hood", - // thumbnailSrc: "http://images.neopets.com/items/clo_zafara_agent_hood.gif", - zoneName: "Hat", - }, - { - id: "38912", - // name: "Zafara Agent Robe", - // thumbnailSrc: "http://images.neopets.com/items/clo_zafara_agent_robe.gif", - zoneName: "Jacket", - }, - { - id: "37375", - // name: "Moon and Stars Background", - // thumbnailSrc: "http://images.neopets.com/items/bg_moonstars.gif", - zoneName: "Background", - }, - { - id: "74166", - // name: "Altador Forest Background", - // thumbnailSrc: "http://images.neopets.com/items/bg_ddy18_altadorforest.gif", - zoneName: "Background", - }, - { - id: "48313", - // name: "Altador Cup Brooch", - // thumbnailSrc: "http://images.neopets.com/items/clo_altcuplogo_brooch.gif", - zoneName: "Collar", - }, - { - id: "37229", - // name: "Magic Ball Table", - // thumbnailSrc: "http://images.neopets.com/items/gif_magicball_table.gif", - zoneName: "Lower Foreground Item", - }, - { - id: "43014", - // name: "Green Leaf String Lights", - // thumbnailSrc: "http://images.neopets.com/items/toy_stringlight_illleaf.gif", - zoneName: "Background Item", - }, - { - id: "43397", - // name: "Jewelled Staff", - // thumbnailSrc: "http://images.neopets.com/items/mall_staff_jewelled.gif", - zoneName: "Left-hand item", - }, -]; diff --git a/src/useItemData.js b/src/useItemData.js index a1b63f6..a9c1b79 100644 --- a/src/useItemData.js +++ b/src/useItemData.js @@ -1,8 +1,6 @@ import gql from "graphql-tag"; import { useQuery } from "@apollo/react-hooks"; -import { ITEMS } from "./data"; - function useItemData(itemIds, speciesId, colorId) { const { loading, error, data } = useQuery( gql` @@ -12,12 +10,13 @@ function useItemData(itemIds, speciesId, colorId) { name thumbnailUrl - # This is used for wearItem actions, to resolve conflicts. We don't - # use it directly; we just expect it to be in the cache! + # This is used to group items by zone, and to detect conflicts when + # wearing a new item. appearanceOn(speciesId: $speciesId, colorId: $colorId) { layers { zone { id + label } } } @@ -30,11 +29,7 @@ function useItemData(itemIds, speciesId, colorId) { const items = (data && data.items) || []; const itemsById = {}; for (const item of items) { - const hardcodedItem = ITEMS.find((i) => i.id === item.id); - itemsById[item.id] = { - ...hardcodedItem, - ...item, - }; + itemsById[item.id] = item; } return { loading, error, itemsById }; diff --git a/src/useOutfitState.js b/src/useOutfitState.js index f3a90c8..8cee207 100644 --- a/src/useOutfitState.js +++ b/src/useOutfitState.js @@ -9,21 +9,24 @@ enableMapSet(); function useOutfitState() { const apolloClient = useApolloClient(); - const [state, dispatch] = React.useReducer(outfitStateReducer(apolloClient), { - wornItemIds: new Set([ - "38913", - "38911", - "38912", - "37375", - "48313", - "37229", - "43014", - "43397", - ]), - closetedItemIds: new Set(["74166"]), - speciesId: "54", // Starry - colorId: "75", // Zafara - }); + const [state, dispatchToOutfit] = React.useReducer( + outfitStateReducer(apolloClient), + { + wornItemIds: new Set([ + "38913", + "38911", + "38912", + "37375", + "48313", + "37229", + "43014", + "43397", + ]), + closetedItemIds: new Set(["74166", "68626", "40319"]), + speciesId: "54", // Starry + colorId: "75", // Zafara + } + ); const { speciesId, colorId } = state; @@ -45,16 +48,22 @@ function useOutfitState() { closetedItemIds ); - const data = { zonesAndItems, wornItemIds, speciesId, colorId }; + const outfitState = { + zonesAndItems, + wornItemIds, + allItemIds, + speciesId, + colorId, + }; - return { loading, error, data, dispatch }; + return { loading, error, outfitState, dispatchToOutfit }; } const outfitStateReducer = (apolloClient) => (baseState, action) => { switch (action.type) { case "wearItem": return produce(baseState, (state) => { - const { wornItemIds, closetedItemIds, speciesId, colorId } = state; + const { wornItemIds, closetedItemIds } = state; const { itemId } = action; // Move the item out of the closet. @@ -131,6 +140,7 @@ function findItemConflicts(itemIdToAdd, state, apolloClient) { return conflictingIds; } +// TODO: Get this out of here, tbh... function getZonesAndItems(itemsById, wornItemIds, closetedItemIds) { const wornItems = wornItemIds.map((id) => itemsById[id]).filter((i) => i); const closetedItems = closetedItemIds @@ -138,17 +148,28 @@ function getZonesAndItems(itemsById, wornItemIds, closetedItemIds) { .filter((i) => i); const allItems = [...wornItems, ...closetedItems]; - const allZoneNames = [...new Set(allItems.map((item) => item.zoneName))]; - allZoneNames.sort(); + const zonesById = new Map(); + const itemsByZoneId = new Map(); + for (const item of allItems) { + for (const layer of item.appearanceOn.layers) { + const zoneId = layer.zone.id; + zonesById.set(zoneId, layer.zone); - const zonesAndItems = allZoneNames.map((zoneName) => { - const items = allItems.filter((item) => item.zoneName === zoneName); - items.sort((a, b) => a.name.localeCompare(b.name)); - const wornItemId = - items.map((item) => item.id).find((id) => wornItemIds.includes(id)) || - null; - return { zoneName, items, wornItemId }; - }); + if (!itemsByZoneId.has(zoneId)) { + itemsByZoneId.set(zoneId, []); + } + itemsByZoneId.get(zoneId).push(item); + } + } + + const zonesAndItems = Array.from(itemsByZoneId.entries()).map( + ([zoneId, items]) => ({ + zone: zonesById.get(zoneId), + items: [...items].sort((a, b) => a.name.localeCompare(b.name)), + }) + ); + + zonesAndItems.sort((a, b) => a.zone.label.localeCompare(b.zone.label)); return zonesAndItems; }