embed item page in wardrobe page drawer
This commit is contained in:
parent
056b238462
commit
dcf2ec6a26
5 changed files with 77 additions and 27 deletions
|
@ -23,16 +23,24 @@ import OutfitPreview from "./components/OutfitPreview";
|
|||
|
||||
function ItemPage() {
|
||||
const { itemId } = useParams();
|
||||
return <ItemPageContent itemId={itemId} />;
|
||||
}
|
||||
|
||||
/**
|
||||
* ItemPageContent is the content of ItemPage, but we also use it as the
|
||||
* entry point for ItemPageDrawer! When embedded in ItemPageDrawer, the
|
||||
* `isEmbedded` prop is true, so we know not to e.g. set the page title.
|
||||
*/
|
||||
export function ItemPageContent({ itemId, isEmbedded }) {
|
||||
return (
|
||||
<VStack spacing="6">
|
||||
<ItemPageHeader itemId={itemId} />
|
||||
<ItemPageHeader itemId={itemId} isEmbedded={isEmbedded} />
|
||||
<ItemPageOutfitPreview itemId={itemId} />
|
||||
</VStack>
|
||||
);
|
||||
}
|
||||
|
||||
function ItemPageHeader({ itemId }) {
|
||||
function ItemPageHeader({ itemId, isEmbedded }) {
|
||||
const { error, data } = useQuery(
|
||||
gql`
|
||||
query ItemPage($itemId: ID!) {
|
||||
|
@ -47,7 +55,7 @@ function ItemPageHeader({ itemId }) {
|
|||
{ variables: { itemId }, returnPartialData: true }
|
||||
);
|
||||
|
||||
usePageTitle(data?.item?.name);
|
||||
usePageTitle(data?.item?.name, { skip: isEmbedded });
|
||||
|
||||
if (error) {
|
||||
return <Box color="red.400">{error.message}</Box>;
|
||||
|
@ -67,7 +75,14 @@ function ItemPageHeader({ itemId }) {
|
|||
</Skeleton>
|
||||
<Box>
|
||||
<Skeleton isLoaded={item?.name}>
|
||||
<Heading1 lineHeight="1.1">{item?.name || "Item name here"}</Heading1>
|
||||
<Heading1
|
||||
lineHeight="1.1"
|
||||
// Nudge down the size a bit in the embed case, to better fit the
|
||||
// tighter layout!
|
||||
size={isEmbedded ? "xl" : "2xl"}
|
||||
>
|
||||
{item?.name || "Item name here"}
|
||||
</Heading1>
|
||||
</Skeleton>
|
||||
<ItemPageBadges item={item} />
|
||||
</Box>
|
||||
|
@ -131,7 +146,7 @@ function ItemPageBadges({ item }) {
|
|||
encodeURIComponent(item.name)
|
||||
}
|
||||
>
|
||||
Trades
|
||||
Trade Post
|
||||
</LinkBadge>
|
||||
)}
|
||||
</Skeleton>
|
||||
|
|
30
src/app/ItemPageDrawer.js
Normal file
30
src/app/ItemPageDrawer.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
import React from "react";
|
||||
import {
|
||||
Drawer,
|
||||
DrawerBody,
|
||||
DrawerContent,
|
||||
DrawerCloseButton,
|
||||
DrawerOverlay,
|
||||
useBreakpointValue,
|
||||
} from "@chakra-ui/core";
|
||||
|
||||
import { ItemPageContent } from "./ItemPage";
|
||||
|
||||
function ItemPageDrawer({ item, isOpen, onClose }) {
|
||||
const placement = useBreakpointValue({ base: "bottom", lg: "right" });
|
||||
|
||||
return (
|
||||
<Drawer placement={placement} size="md" isOpen={isOpen} onClose={onClose}>
|
||||
<DrawerOverlay>
|
||||
<DrawerContent>
|
||||
<DrawerCloseButton />
|
||||
<DrawerBody>
|
||||
<ItemPageContent itemId={item.id} isEmbedded />
|
||||
</DrawerBody>
|
||||
</DrawerContent>
|
||||
</DrawerOverlay>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
export default ItemPageDrawer;
|
|
@ -16,6 +16,7 @@ import {
|
|||
InfoIcon,
|
||||
NotAllowedIcon,
|
||||
} from "@chakra-ui/icons";
|
||||
import { Link } from "react-router-dom";
|
||||
import loadable from "@loadable/component";
|
||||
|
||||
import {
|
||||
|
@ -27,6 +28,7 @@ import {
|
|||
} from "../components/ItemCard";
|
||||
import SupportOnly from "./support/SupportOnly";
|
||||
|
||||
const LoadableItemPageDrawer = loadable(() => import("../ItemPageDrawer"));
|
||||
const LoadableItemSupportDrawer = loadable(() =>
|
||||
import("./support/ItemSupportDrawer")
|
||||
);
|
||||
|
@ -58,6 +60,7 @@ function Item({
|
|||
onRemove,
|
||||
isDisabled = false,
|
||||
}) {
|
||||
const [infoDrawerIsOpen, setInfoDrawerIsOpen] = React.useState(false);
|
||||
const [supportDrawerIsOpen, setSupportDrawerIsOpen] = React.useState(false);
|
||||
|
||||
return (
|
||||
|
@ -97,13 +100,25 @@ function Item({
|
|||
<ItemActionButton
|
||||
icon={<InfoIcon />}
|
||||
label="More info"
|
||||
href={`https://impress.openneo.net/items/${
|
||||
item.id
|
||||
}-${item.name.replace(/ /g, "-")}`}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
to={`/items/${item.id}`}
|
||||
onClick={(e) => {
|
||||
const willProbablyOpenInNewTab =
|
||||
e.metaKey || e.shiftKey || e.altKey || e.ctrlKey;
|
||||
if (willProbablyOpenInNewTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
setInfoDrawerIsOpen(true);
|
||||
e.preventDefault();
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</ItemContainer>
|
||||
<LoadableItemPageDrawer
|
||||
item={item}
|
||||
isOpen={infoDrawerIsOpen}
|
||||
onClose={() => setInfoDrawerIsOpen(false)}
|
||||
/>
|
||||
<SupportOnly>
|
||||
<LoadableItemSupportDrawer
|
||||
item={item}
|
||||
|
@ -220,7 +235,7 @@ function ItemBadges({ item }) {
|
|||
/**
|
||||
* ItemActionButton is one of a list of actions a user can take for this item.
|
||||
*/
|
||||
function ItemActionButton({ icon, label, href, onClick }) {
|
||||
function ItemActionButton({ icon, label, to, onClick }) {
|
||||
const theme = useTheme();
|
||||
|
||||
const focusBackgroundColor = useColorModeValue(
|
||||
|
@ -235,13 +250,12 @@ function ItemActionButton({ icon, label, href, onClick }) {
|
|||
return (
|
||||
<Tooltip label={label} placement="top">
|
||||
<IconButton
|
||||
as={href ? "a" : "button"}
|
||||
as={to ? Link : "button"}
|
||||
icon={icon}
|
||||
aria-label={label}
|
||||
variant="ghost"
|
||||
color="gray.400"
|
||||
href={href}
|
||||
target={href ? "_blank" : null}
|
||||
to={to}
|
||||
onClick={onClick}
|
||||
className={css`
|
||||
opacity: 0;
|
||||
|
|
|
@ -41,22 +41,12 @@ import useSupport from "./useSupport";
|
|||
* from another lazy-loaded component!
|
||||
*/
|
||||
function ItemSupportDrawer({ item, isOpen, onClose }) {
|
||||
const placement = useBreakpointValue({
|
||||
base: "bottom",
|
||||
lg: "right",
|
||||
|
||||
// TODO: There's a bug in the Chakra RC that doesn't read the breakpoint
|
||||
// specification correctly - we need these extra keys until it's fixed!
|
||||
// https://github.com/chakra-ui/chakra-ui/issues/1444
|
||||
0: "bottom",
|
||||
1: "bottom",
|
||||
2: "right",
|
||||
3: "right",
|
||||
});
|
||||
const placement = useBreakpointValue({ base: "bottom", lg: "right" });
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
placement={placement}
|
||||
size="md"
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
// blockScrollOnMount doesn't matter on our fullscreen UI, but the
|
||||
|
|
|
@ -111,10 +111,11 @@ export function useDebounce(
|
|||
/**
|
||||
* usePageTitle sets the page title!
|
||||
*/
|
||||
export function usePageTitle(title) {
|
||||
export function usePageTitle(title, { skip = false } = {}) {
|
||||
React.useEffect(() => {
|
||||
if (skip) return;
|
||||
document.title = title ? `${title} | Dress to Impress` : "Dress to Impress";
|
||||
}, [title]);
|
||||
}, [title, skip]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue