start building item page

This commit is contained in:
Emi Matchu 2020-09-11 23:56:47 -07:00
parent ebb8c63ac6
commit 4f6f3640bb
3 changed files with 156 additions and 10 deletions

View file

@ -12,6 +12,7 @@ import PageLayout from "./PageLayout";
import WardrobePageLayout from "./WardrobePage/WardrobePageLayout"; import WardrobePageLayout from "./WardrobePage/WardrobePageLayout";
const HomePage = loadable(() => import("./HomePage")); const HomePage = loadable(() => import("./HomePage"));
const ItemPage = loadable(() => import("./ItemPage"));
const ModelingPage = loadable(() => import("./ModelingPage")); const ModelingPage = loadable(() => import("./ModelingPage"));
const UserItemsPage = loadable(() => import("./UserItemsPage")); const UserItemsPage = loadable(() => import("./UserItemsPage"));
const WardrobePage = loadable(() => import("./WardrobePage"), { const WardrobePage = loadable(() => import("./WardrobePage"), {
@ -63,6 +64,11 @@ function App() {
<ChakraProvider theme={theme}> <ChakraProvider theme={theme}>
<CSSReset /> <CSSReset />
<Switch> <Switch>
<Route path="/items/:itemId">
<PageLayout>
<ItemPage />
</PageLayout>
</Route>
<Route path="/outfits/new"> <Route path="/outfits/new">
<WardrobePage /> <WardrobePage />
</Route> </Route>

127
src/app/ItemPage.js Normal file
View file

@ -0,0 +1,127 @@
import React from "react";
import { Badge, Box, Center } from "@chakra-ui/core";
import { ExternalLinkIcon } from "@chakra-ui/icons";
import gql from "graphql-tag";
import { useQuery } from "@apollo/client";
import { useParams } from "react-router-dom";
import HangerSpinner from "./components/HangerSpinner";
import {
ItemBadgeList,
ItemThumbnail,
NcBadge,
NpBadge,
} from "./components/ItemCard";
import { Heading1, usePageTitle } from "./util";
function ItemPage() {
const { itemId } = useParams();
const { loading, error, data } = useQuery(
gql`
query ItemPage($itemId: ID!) {
item(id: $itemId) {
id
name
isNc
thumbnailUrl
}
}
`,
{ variables: { itemId } }
);
usePageTitle(data?.item?.name);
if (loading) {
return (
<Center>
<HangerSpinner />
</Center>
);
}
if (error) {
return <Box color="red.400">{error.message}</Box>;
}
const { item } = data;
return (
<Box display="flex" alignItems="center">
<ItemThumbnail
item={item}
size="lg"
isActive
marginRight="4"
flex="0 0 auto"
/>
<Box>
<Heading1 lineHeight="1.1">{item.name}</Heading1>
<ItemBadgeList>
{item.isNc ? <NcBadge /> : <NpBadge />}
<LinkBadge
href={
"https://items.jellyneo.net/search/?name=" +
encodeURIComponent(item.name) +
"&name_type=3"
}
>
Jellyneo
</LinkBadge>
{!item.isNc && (
<LinkBadge
href={
"http://www.neopets.com/market.phtml?type=wizard&string=" +
encodeURIComponent(item.name)
}
>
Shop Wiz
</LinkBadge>
)}
{!item.isNc && (
<LinkBadge
href={
"http://www.neopets.com/portal/supershopwiz.phtml?string=" +
encodeURIComponent(item.name)
}
>
Super Wiz
</LinkBadge>
)}
{!item.isNc && (
<LinkBadge
href={
"http://www.neopets.com/island/tradingpost.phtml?type=browse&criteria=item_exact&search_string=" +
encodeURIComponent(item.name)
}
>
Trades
</LinkBadge>
)}
{!item.isNc && (
<LinkBadge
href={
"http://www.neopets.com/genie.phtml?type=process_genie&criteria=exact&auctiongenie=" +
encodeURIComponent(item.name)
}
>
Auctions
</LinkBadge>
)}
</ItemBadgeList>
</Box>
</Box>
);
}
function LinkBadge({ children, href }) {
return (
<Badge as="a" href={href} display="flex" alignItems="center">
{children}
<ExternalLinkIcon marginLeft="1" />
</Badge>
);
}
export default ItemPage;

View file

@ -3,7 +3,6 @@ import { css } from "emotion";
import { import {
Badge, Badge,
Box, Box,
Image,
SimpleGrid, SimpleGrid,
Tooltip, Tooltip,
Wrap, Wrap,
@ -52,8 +51,8 @@ export function ItemCardContent({
<Box display="flex"> <Box display="flex">
<Box flex="0 0 auto" marginRight="3"> <Box flex="0 0 auto" marginRight="3">
<ItemThumbnail <ItemThumbnail
src={safeImageUrl(item.thumbnailUrl)} item={item}
isWorn={isWorn} isActive={isWorn}
isDisabled={isDisabled} isDisabled={isDisabled}
focusSelector={focusSelector} focusSelector={focusSelector}
/> />
@ -78,7 +77,14 @@ export function ItemCardContent({
* ItemThumbnail shows a small preview image for the item, including some * ItemThumbnail shows a small preview image for the item, including some
* hover/focus and worn/unworn states. * hover/focus and worn/unworn states.
*/ */
function ItemThumbnail({ src, isWorn, isDisabled, focusSelector }) { export function ItemThumbnail({
item,
size = "md",
isActive,
isDisabled,
focusSelector,
...props
}) {
const theme = useTheme(); const theme = useTheme();
const borderColor = useColorModeValue( const borderColor = useColorModeValue(
@ -93,8 +99,8 @@ function ItemThumbnail({ src, isWorn, isDisabled, focusSelector }) {
return ( return (
<Box <Box
width="50px" width={size === "lg" ? "80px" : "50px"}
height="50px" height={size === "lg" ? "80px" : "50px"}
transition="all 0.15s" transition="all 0.15s"
transformOrigin="center" transformOrigin="center"
position="relative" position="relative"
@ -103,18 +109,19 @@ function ItemThumbnail({ src, isWorn, isDisabled, focusSelector }) {
transform: "scale(0.8)", transform: "scale(0.8)",
}, },
!isDisabled && !isDisabled &&
!isWorn && { !isActive && {
[focusSelector]: { [focusSelector]: {
opacity: "0.9", opacity: "0.9",
transform: "scale(0.9)", transform: "scale(0.9)",
}, },
}, },
!isDisabled && !isDisabled &&
isWorn && { isActive && {
opacity: 1, opacity: 1,
transform: "none", transform: "none",
}, },
])} ])}
{...props}
> >
<Box <Box
borderRadius="lg" borderRadius="lg"
@ -128,14 +135,20 @@ function ItemThumbnail({ src, isWorn, isDisabled, focusSelector }) {
borderColor: `${borderColor} !important`, borderColor: `${borderColor} !important`,
}, },
!isDisabled && !isDisabled &&
!isWorn && { !isActive && {
[focusSelector]: { [focusSelector]: {
borderColor: `${focusBorderColor} !important`, borderColor: `${focusBorderColor} !important`,
}, },
}, },
])} ])}
> >
<Image width="100%" height="100%" src={src} alt="" /> <Box
as="img"
width="100%"
height="100%"
src={safeImageUrl(item.thumbnailUrl)}
alt={`Thumbnail art for ${item.name}`}
/>
</Box> </Box>
</Box> </Box>
); );