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 { Box, Image, PseudoBox, Stack } from "@chakra-ui/core";
import { Box, Image, PseudoBox, Stack, Skeleton } from "@chakra-ui/core";
function ItemList({ items, wornItemIds, onWearItem }) {
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 }) {
return (
<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 }) {
return (
<PseudoBox
@ -82,3 +108,4 @@ function ItemName({ children, isWorn }) {
}
export default ItemList;
export { ItemListSkeleton };

View file

@ -15,12 +15,13 @@ import {
InputLeftElement,
InputRightElement,
PseudoBox,
Skeleton,
Stack,
Text,
useToast,
} from "@chakra-ui/core";
import ItemList from "./ItemList";
import ItemList, { ItemListSkeleton } from "./ItemList";
import useOutfitState from "./useOutfitState.js";
import { ITEMS } from "./data";
@ -53,6 +54,18 @@ function WardrobePage() {
[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 (
<Grid
// Fullscreen, split into a vertical stack on smaller screens
@ -97,6 +110,7 @@ function WardrobePage() {
) : (
<ItemsPanel
zonesAndItems={data.zonesAndItems}
loading={loading}
onWearItem={wearItemAndToast}
/>
)}
@ -191,21 +205,29 @@ function SearchPanel({ query, wornItemIds, onWearItem }) {
);
}
function ItemsPanel({ zonesAndItems, onWearItem }) {
function ItemsPanel({ zonesAndItems, loading, onWearItem }) {
return (
<Box color="green.800">
<OutfitHeading />
<Stack spacing="10">
{zonesAndItems.map(({ zoneName, items, wornItemId }) => (
<Box key={zoneName}>
<Heading2 mb="3">{zoneName}</Heading2>
<ItemList
items={items}
wornItemIds={[wornItemId]}
onWearItem={onWearItem}
/>
</Box>
))}
{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}>
<Heading2 mb="3">{zoneName}</Heading2>
<ItemList
items={items}
wornItemIds={[wornItemId]}
onWearItem={onWearItem}
/>
</Box>
))}
</Stack>
</Box>
);
@ -213,21 +235,23 @@ function ItemsPanel({ zonesAndItems, onWearItem }) {
function OutfitHeading() {
return (
<PseudoBox role="group" d="inline-block" position="relative">
<Heading1 mb="6">
<Editable defaultValue="Zafara Agent (roopal27)">
{({ isEditing, onRequestEdit }) => (
<>
<EditablePreview />
<EditableInput />
{!isEditing && (
<OutfitNameEditButton onRequestEdit={onRequestEdit} />
)}
</>
)}
</Editable>
</Heading1>
</PseudoBox>
<Box>
<PseudoBox role="group" d="inline-block" position="relative">
<Heading1 mb="6">
<Editable defaultValue="Zafara Agent (roopal27)">
{({ isEditing, onRequestEdit }) => (
<>
<EditablePreview />
<EditableInput />
{!isEditing && (
<OutfitNameEditButton onRequestEdit={onRequestEdit} />
)}
</>
)}
</Editable>
</Heading1>
</PseudoBox>
</Box>
);
}