forked from OpenNeo/impress-2020
similar to the layer zoning tools I just rolled out! not thrilled about the outfit state hacks here bc of how we cache restrict on the appearance rather than the item, but oh well! this escape hatch is pretty easy and solid, and it's a cleanup for another day Also did a code split here, now that this file is getting larger, to only load this for support users. I don't actually care about restricting console stuff to support users (I'd honestly rather not), but saving the bytes is worth it I think, since support mode is pretty easy to enter when we need to
113 lines
3.7 KiB
JavaScript
113 lines
3.7 KiB
JavaScript
import React from "react";
|
|
import { Box, Grid, useToast } from "@chakra-ui/core";
|
|
import loadable from "@loadable/component";
|
|
|
|
import ItemsAndSearchPanels from "./ItemsAndSearchPanels";
|
|
import OutfitPreview from "../components/OutfitPreview";
|
|
import SupportOnly from "./support/SupportOnly";
|
|
import useOutfitState, { OutfitStateContext } from "./useOutfitState";
|
|
import { usePageTitle } from "../util";
|
|
|
|
const OutfitControls = loadable(() =>
|
|
import(/* webpackPreload: true */ "./OutfitControls")
|
|
);
|
|
const WardrobeDevHacks = loadable(() => import("./WardrobeDevHacks"));
|
|
|
|
/**
|
|
* WardrobePage is the most fun page on the site - it's where you create
|
|
* outfits!
|
|
*
|
|
* This page has two sections: the OutfitPreview, where we show the outfit as a
|
|
* big image; and the ItemsAndSearchPanels, which let you manage which items
|
|
* are in the outfit and find new ones.
|
|
*
|
|
* This component manages shared outfit state, and the fullscreen responsive
|
|
* page layout.
|
|
*/
|
|
function WardrobePage() {
|
|
const toast = useToast();
|
|
const { loading, error, outfitState, dispatchToOutfit } = useOutfitState();
|
|
|
|
usePageTitle(`${outfitState.name || "Untitled outfit"} | Dress to Impress`);
|
|
|
|
// TODO: I haven't found a great place for this error UI yet, and this case
|
|
// isn't very common, so this lil toast notification seems good enough!
|
|
React.useEffect(() => {
|
|
if (error) {
|
|
console.log(error);
|
|
toast({
|
|
title: "We couldn't load this outfit 😖",
|
|
description: "Please reload the page to try again. Sorry!",
|
|
status: "error",
|
|
isClosable: true,
|
|
duration: 999999999,
|
|
});
|
|
}
|
|
}, [error, toast]);
|
|
|
|
// NOTE: Most components pass around outfitState directly, to make the data
|
|
// relationships more explicit... but there are some deep components
|
|
// that need it, where it's more useful and more performant to access
|
|
// via context.
|
|
return (
|
|
<OutfitStateContext.Provider value={outfitState}>
|
|
<SupportOnly>
|
|
<WardrobeDevHacks />
|
|
</SupportOnly>
|
|
<Box
|
|
position="absolute"
|
|
top="0"
|
|
bottom="0"
|
|
left="0"
|
|
right="0"
|
|
// Create a stacking context, so that our drawers and modals don't fight
|
|
// with the z-indexes in here!
|
|
zIndex="0"
|
|
>
|
|
<Grid
|
|
templateAreas={{
|
|
base: `"previewAndControls"
|
|
"itemsAndSearch"`,
|
|
lg: `"previewAndControls itemsAndSearch"`,
|
|
}}
|
|
templateRows={{
|
|
base: "minmax(100px, 45%) minmax(300px, 55%)",
|
|
lg: "100%",
|
|
}}
|
|
templateColumns={{
|
|
base: "100%",
|
|
lg: "50% 50%",
|
|
}}
|
|
height="100%"
|
|
width="100%"
|
|
>
|
|
<Box gridArea="previewAndControls" bg="gray.900" pos="relative">
|
|
<Box position="absolute" top="0" bottom="0" left="0" right="0">
|
|
<OutfitPreview
|
|
speciesId={outfitState.speciesId}
|
|
colorId={outfitState.colorId}
|
|
pose={outfitState.pose}
|
|
wornItemIds={outfitState.wornItemIds}
|
|
/>
|
|
</Box>
|
|
<Box position="absolute" top="0" bottom="0" left="0" right="0">
|
|
<OutfitControls
|
|
outfitState={outfitState}
|
|
dispatchToOutfit={dispatchToOutfit}
|
|
/>
|
|
</Box>
|
|
</Box>
|
|
<Box gridArea="itemsAndSearch">
|
|
<ItemsAndSearchPanels
|
|
loading={loading}
|
|
outfitState={outfitState}
|
|
dispatchToOutfit={dispatchToOutfit}
|
|
/>
|
|
</Box>
|
|
</Grid>
|
|
</Box>
|
|
</OutfitStateContext.Provider>
|
|
);
|
|
}
|
|
|
|
export default WardrobePage;
|