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 useOutfitState, { OutfitStateContext } from "./useOutfitState.js"; import { usePageTitle } from "../util"; const OutfitControls = loadable(() => import(/* webpackPreload: true */ "./OutfitControls") ); /** * 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}> <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;