add item list skeleton while loading

This commit is contained in:
Matt Dunn-Rankin 2020-04-22 15:24:38 -07:00
parent 7397243c7f
commit d1d98e2f72
2 changed files with 79 additions and 28 deletions

View file

@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { Box, Image, PseudoBox, Stack } from "@chakra-ui/core"; import { Box, Image, PseudoBox, Stack, Skeleton } from "@chakra-ui/core";
function ItemList({ items, wornItemIds, onWearItem }) { function ItemList({ items, wornItemIds, onWearItem }) {
return ( return (
@ -17,6 +17,22 @@ function ItemList({ items, wornItemIds, onWearItem }) {
); );
} }
function ItemListSkeleton() {
return (
<Stack spacing="3">
<Box>
<ItemSkeleton />
</Box>
<Box>
<ItemSkeleton />
</Box>
<Box>
<ItemSkeleton />
</Box>
</Stack>
);
}
function Item({ item, isWorn, onWear }) { function Item({ item, isWorn, onWear }) {
return ( return (
<PseudoBox <PseudoBox
@ -33,6 +49,16 @@ function Item({ item, isWorn, onWear }) {
); );
} }
function ItemSkeleton() {
return (
<Box d="flex" alignItems="center">
<Skeleton width="50px" height="50px" />
<Box width="3" />
<Skeleton height="1.5rem" width="12rem" />
</Box>
);
}
function ItemThumbnail({ src, isWorn }) { function ItemThumbnail({ src, isWorn }) {
return ( return (
<PseudoBox <PseudoBox
@ -82,3 +108,4 @@ function ItemName({ children, isWorn }) {
} }
export default ItemList; export default ItemList;
export { ItemListSkeleton };

View file

@ -15,12 +15,13 @@ import {
InputLeftElement, InputLeftElement,
InputRightElement, InputRightElement,
PseudoBox, PseudoBox,
Skeleton,
Stack, Stack,
Text, Text,
useToast, useToast,
} from "@chakra-ui/core"; } from "@chakra-ui/core";
import ItemList from "./ItemList"; import ItemList, { ItemListSkeleton } from "./ItemList";
import useOutfitState from "./useOutfitState.js"; import useOutfitState from "./useOutfitState.js";
import { ITEMS } from "./data"; import { ITEMS } from "./data";
@ -53,6 +54,18 @@ function WardrobePage() {
[toast, wearItem, hasSentToast, setHasSentToast] [toast, wearItem, hasSentToast, setHasSentToast]
); );
React.useEffect(() => {
if (error) {
toast({
title: "We couldn't load this outfit 😖",
description: "Please reload the page to try again. Sorry!",
status: "error",
isClosable: true,
duration: Infinity,
});
}
}, [error, toast]);
return ( return (
<Grid <Grid
// Fullscreen, split into a vertical stack on smaller screens // Fullscreen, split into a vertical stack on smaller screens
@ -97,6 +110,7 @@ function WardrobePage() {
) : ( ) : (
<ItemsPanel <ItemsPanel
zonesAndItems={data.zonesAndItems} zonesAndItems={data.zonesAndItems}
loading={loading}
onWearItem={wearItemAndToast} onWearItem={wearItemAndToast}
/> />
)} )}
@ -191,12 +205,20 @@ function SearchPanel({ query, wornItemIds, onWearItem }) {
); );
} }
function ItemsPanel({ zonesAndItems, onWearItem }) { function ItemsPanel({ zonesAndItems, loading, onWearItem }) {
return ( return (
<Box color="green.800"> <Box color="green.800">
<OutfitHeading /> <OutfitHeading />
<Stack spacing="10"> <Stack spacing="10">
{zonesAndItems.map(({ zoneName, items, wornItemId }) => ( {loading &&
[1, 2, 3].map((i) => (
<Box key={i}>
<Skeleton height="2.3rem" width="12rem" mb="3" />
<ItemListSkeleton />
</Box>
))}
{!loading &&
zonesAndItems.map(({ zoneName, items, wornItemId }) => (
<Box key={zoneName}> <Box key={zoneName}>
<Heading2 mb="3">{zoneName}</Heading2> <Heading2 mb="3">{zoneName}</Heading2>
<ItemList <ItemList
@ -213,6 +235,7 @@ function ItemsPanel({ zonesAndItems, onWearItem }) {
function OutfitHeading() { function OutfitHeading() {
return ( return (
<Box>
<PseudoBox role="group" d="inline-block" position="relative"> <PseudoBox role="group" d="inline-block" position="relative">
<Heading1 mb="6"> <Heading1 mb="6">
<Editable defaultValue="Zafara Agent (roopal27)"> <Editable defaultValue="Zafara Agent (roopal27)">
@ -228,6 +251,7 @@ function OutfitHeading() {
</Editable> </Editable>
</Heading1> </Heading1>
</PseudoBox> </PseudoBox>
</Box>
); );
} }