create ItemCard, use it in ItemsPage too
extracted from modeling page!
This commit is contained in:
parent
9cb6cc2120
commit
0df57818e3
4 changed files with 102 additions and 68 deletions
|
@ -1,11 +1,16 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Box, Image, Wrap } from "@chakra-ui/core";
|
import { Box, Wrap } from "@chakra-ui/core";
|
||||||
import gql from "graphql-tag";
|
import gql from "graphql-tag";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { useQuery } from "@apollo/client";
|
import { useQuery } from "@apollo/client";
|
||||||
|
|
||||||
import HangerSpinner from "./components/HangerSpinner";
|
import HangerSpinner from "./components/HangerSpinner";
|
||||||
import { Heading1 } from "./util";
|
import { Heading1 } from "./util";
|
||||||
|
import ItemCard, {
|
||||||
|
ItemBadgeList,
|
||||||
|
NcBadge,
|
||||||
|
NpBadge,
|
||||||
|
} from "./components/ItemCard";
|
||||||
import useCurrentUser from "./components/useCurrentUser";
|
import useCurrentUser from "./components/useCurrentUser";
|
||||||
|
|
||||||
function ItemsPage() {
|
function ItemsPage() {
|
||||||
|
@ -21,6 +26,7 @@ function ItemsPage() {
|
||||||
username
|
username
|
||||||
itemsTheyOwn {
|
itemsTheyOwn {
|
||||||
id
|
id
|
||||||
|
isNc
|
||||||
name
|
name
|
||||||
thumbnailUrl
|
thumbnailUrl
|
||||||
}
|
}
|
||||||
|
@ -49,17 +55,15 @@ function ItemsPage() {
|
||||||
</Heading1>
|
</Heading1>
|
||||||
<Wrap justify="center">
|
<Wrap justify="center">
|
||||||
{data.user.itemsTheyOwn.map((item) => (
|
{data.user.itemsTheyOwn.map((item) => (
|
||||||
<Box key={item.id} width="100px" textAlign="center">
|
<ItemCard
|
||||||
<Image
|
key={item.id}
|
||||||
src={item.thumbnailUrl}
|
item={item}
|
||||||
alt=""
|
badges={
|
||||||
height="80px"
|
<ItemBadgeList>
|
||||||
width="80px"
|
{item.isNc ? <NcBadge /> : <NpBadge />}
|
||||||
boxShadow="md"
|
</ItemBadgeList>
|
||||||
margin="0 auto"
|
}
|
||||||
/>
|
/>
|
||||||
{item.name}
|
|
||||||
</Box>
|
|
||||||
))}
|
))}
|
||||||
</Wrap>
|
</Wrap>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Badge, Box, SimpleGrid, useColorModeValue } from "@chakra-ui/core";
|
import { Badge, Box, SimpleGrid } from "@chakra-ui/core";
|
||||||
import { StarIcon } from "@chakra-ui/icons";
|
import { StarIcon } from "@chakra-ui/icons";
|
||||||
import gql from "graphql-tag";
|
import gql from "graphql-tag";
|
||||||
import { useQuery } from "@apollo/client";
|
import { useQuery } from "@apollo/client";
|
||||||
|
@ -7,7 +7,8 @@ import { useQuery } from "@apollo/client";
|
||||||
import { Delay } from "./util";
|
import { Delay } from "./util";
|
||||||
import HangerSpinner from "./components/HangerSpinner";
|
import HangerSpinner from "./components/HangerSpinner";
|
||||||
import { Heading1, Heading2 } from "./util";
|
import { Heading1, Heading2 } from "./util";
|
||||||
import ItemSummary, { ItemSummaryBadgeList } from "./components/ItemSummary";
|
import ItemCard from "./components/ItemCard";
|
||||||
|
import { ItemBadgeList } from "./components/ItemCard";
|
||||||
|
|
||||||
function ModelingPage() {
|
function ModelingPage() {
|
||||||
return (
|
return (
|
||||||
|
@ -83,38 +84,16 @@ function ItemModelsList() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ItemModelCard({ item, currentUserOwnsItem, ...props }) {
|
function ItemModelCard({ item, currentUserOwnsItem, ...props }) {
|
||||||
const borderColor = useColorModeValue("gray.100", "green.500");
|
const badges = (
|
||||||
|
<ItemModelBadges item={item} currentUserOwnsItem={currentUserOwnsItem} />
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
as="a"
|
|
||||||
href={`https://impress.openneo.net/items/${item.id}`}
|
|
||||||
p="2"
|
|
||||||
boxShadow="lg"
|
|
||||||
borderRadius="lg"
|
|
||||||
width="400px"
|
|
||||||
border="1px"
|
|
||||||
borderColor={borderColor}
|
|
||||||
className="item-model-card"
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<ItemSummary
|
|
||||||
item={item}
|
|
||||||
badges={
|
|
||||||
<ItemModelBadges
|
|
||||||
item={item}
|
|
||||||
currentUserOwnsItem={currentUserOwnsItem}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
focusSelector=".item-model-card:hover &, .item-model-card:focus &"
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return <ItemCard item={item} badges={badges} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ItemModelBadges({ item, currentUserOwnsItem }) {
|
function ItemModelBadges({ item, currentUserOwnsItem }) {
|
||||||
return (
|
return (
|
||||||
<ItemSummaryBadgeList>
|
<ItemBadgeList>
|
||||||
{currentUserOwnsItem && (
|
{currentUserOwnsItem && (
|
||||||
<Badge colorScheme="yellow" display="flex" alignItems="center">
|
<Badge colorScheme="yellow" display="flex" alignItems="center">
|
||||||
<StarIcon aria-label="Star" marginRight="1" />
|
<StarIcon aria-label="Star" marginRight="1" />
|
||||||
|
@ -124,7 +103,7 @@ function ItemModelBadges({ item, currentUserOwnsItem }) {
|
||||||
{item.speciesThatNeedModels.map((species) => (
|
{item.speciesThatNeedModels.map((species) => (
|
||||||
<Badge>{species.name}</Badge>
|
<Badge>{species.name}</Badge>
|
||||||
))}
|
))}
|
||||||
</ItemSummaryBadgeList>
|
</ItemBadgeList>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,13 @@ import {
|
||||||
} from "@chakra-ui/icons";
|
} from "@chakra-ui/icons";
|
||||||
import loadable from "@loadable/component";
|
import loadable from "@loadable/component";
|
||||||
|
|
||||||
import ItemSummary, { ItemSummaryBadgeList } from "../components/ItemSummary";
|
import {
|
||||||
|
ItemCardContent,
|
||||||
|
ItemBadgeList,
|
||||||
|
ItemBadgeTooltip,
|
||||||
|
NcBadge,
|
||||||
|
NpBadge,
|
||||||
|
} from "../components/ItemCard";
|
||||||
import SupportOnly from "./support/SupportOnly";
|
import SupportOnly from "./support/SupportOnly";
|
||||||
|
|
||||||
const LoadableItemSupportDrawer = loadable(() =>
|
const LoadableItemSupportDrawer = loadable(() =>
|
||||||
|
@ -58,7 +64,7 @@ function Item({
|
||||||
<>
|
<>
|
||||||
<ItemContainer isDisabled={isDisabled}>
|
<ItemContainer isDisabled={isDisabled}>
|
||||||
<Box flex="1 1 0" minWidth="0">
|
<Box flex="1 1 0" minWidth="0">
|
||||||
<ItemSummary
|
<ItemCardContent
|
||||||
item={item}
|
item={item}
|
||||||
badges={<ItemBadges item={item} />}
|
badges={<ItemBadges item={item} />}
|
||||||
itemNameId={itemNameId}
|
itemNameId={itemNameId}
|
||||||
|
@ -189,11 +195,9 @@ function ItemBadges({ item }) {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ItemSummaryBadgeList>
|
<ItemBadgeList>
|
||||||
{item.isNc ? (
|
{item.isNc ? (
|
||||||
<ItemBadgeTooltip label="Neocash">
|
<NcBadge />
|
||||||
<Badge colorScheme="purple">NC</Badge>
|
|
||||||
</ItemBadgeTooltip>
|
|
||||||
) : (
|
) : (
|
||||||
// The main purpose of the NP badge is alignment: if there are
|
// The main purpose of the NP badge is alignment: if there are
|
||||||
// zone badges, we want them to start at the same rough position,
|
// zone badges, we want them to start at the same rough position,
|
||||||
|
@ -201,9 +205,7 @@ function ItemBadges({ item }) {
|
||||||
// generally avoids zone badges, we'd rather have the NC badge be
|
// generally avoids zone badges, we'd rather have the NC badge be
|
||||||
// a little extra that might pop up and hide the NP case, rather
|
// a little extra that might pop up and hide the NP case, rather
|
||||||
// than try to line things up like a table.
|
// than try to line things up like a table.
|
||||||
<ItemBadgeTooltip label="Neopoints">
|
<NpBadge />
|
||||||
<Badge>NP</Badge>
|
|
||||||
</ItemBadgeTooltip>
|
|
||||||
)}
|
)}
|
||||||
{occupiedZoneLabels.map((zoneLabel) => (
|
{occupiedZoneLabels.map((zoneLabel) => (
|
||||||
<ZoneBadge key={zoneLabel} variant="occupies" zoneLabel={zoneLabel} />
|
<ZoneBadge key={zoneLabel} variant="occupies" zoneLabel={zoneLabel} />
|
||||||
|
@ -211,7 +213,7 @@ function ItemBadges({ item }) {
|
||||||
{restrictedZoneLabels.map((zoneLabel) => (
|
{restrictedZoneLabels.map((zoneLabel) => (
|
||||||
<ZoneBadge key={zoneLabel} variant="restricts" zoneLabel={zoneLabel} />
|
<ZoneBadge key={zoneLabel} variant="restricts" zoneLabel={zoneLabel} />
|
||||||
))}
|
))}
|
||||||
</ItemSummaryBadgeList>
|
</ItemBadgeList>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,18 +339,6 @@ function ZoneBadge({ variant, zoneLabel }) {
|
||||||
return <Badge>{shorthand}</Badge>;
|
return <Badge>{shorthand}</Badge>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ItemBadgeTooltip({ label, children }) {
|
|
||||||
return (
|
|
||||||
<Tooltip
|
|
||||||
label={<Box textAlign="center">{label}</Box>}
|
|
||||||
placement="top"
|
|
||||||
openDelay={400}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* containerHasFocus is a common CSS selector, for the case where our parent
|
* containerHasFocus is a common CSS selector, for the case where our parent
|
||||||
* .item-container is hovered or the adjacent hidden radio/checkbox is
|
* .item-container is hovered or the adjacent hidden radio/checkbox is
|
||||||
|
|
|
@ -1,10 +1,43 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { css } from "emotion";
|
import { css } from "emotion";
|
||||||
import { Box, Image, Wrap, useColorModeValue, useTheme } from "@chakra-ui/core";
|
import {
|
||||||
|
Badge,
|
||||||
|
Box,
|
||||||
|
Image,
|
||||||
|
Tooltip,
|
||||||
|
Wrap,
|
||||||
|
useColorModeValue,
|
||||||
|
useTheme,
|
||||||
|
} from "@chakra-ui/core";
|
||||||
|
|
||||||
import { safeImageUrl } from "../util";
|
import { safeImageUrl } from "../util";
|
||||||
|
|
||||||
function ItemSummary({
|
function ItemCard({ item, badges, ...props }) {
|
||||||
|
const borderColor = useColorModeValue("gray.100", "green.500");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
as="a"
|
||||||
|
href={`https://impress.openneo.net/items/${item.id}`}
|
||||||
|
p="2"
|
||||||
|
boxShadow="lg"
|
||||||
|
borderRadius="lg"
|
||||||
|
width="400px"
|
||||||
|
border="1px"
|
||||||
|
borderColor={borderColor}
|
||||||
|
className="item-card"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ItemCardContent
|
||||||
|
item={item}
|
||||||
|
badges={badges}
|
||||||
|
focusSelector=".item-card:hover &, .item-card:focus &"
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ItemCardContent({
|
||||||
item,
|
item,
|
||||||
badges,
|
badges,
|
||||||
isWorn,
|
isWorn,
|
||||||
|
@ -140,7 +173,7 @@ function ItemName({ children, isDisabled, focusSelector, ...props }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ItemSummaryBadgeList({ children }) {
|
export function ItemBadgeList({ children }) {
|
||||||
return (
|
return (
|
||||||
<Wrap spacing="2" marginTop="1" opacity="0.7">
|
<Wrap spacing="2" marginTop="1" opacity="0.7">
|
||||||
{children}
|
{children}
|
||||||
|
@ -148,4 +181,32 @@ export function ItemSummaryBadgeList({ children }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ItemSummary;
|
export function ItemBadgeTooltip({ label, children }) {
|
||||||
|
return (
|
||||||
|
<Tooltip
|
||||||
|
label={<Box textAlign="center">{label}</Box>}
|
||||||
|
placement="top"
|
||||||
|
openDelay={400}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NcBadge() {
|
||||||
|
return (
|
||||||
|
<ItemBadgeTooltip label="Neocash">
|
||||||
|
<Badge colorScheme="purple">NC</Badge>
|
||||||
|
</ItemBadgeTooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NpBadge() {
|
||||||
|
return (
|
||||||
|
<ItemBadgeTooltip label="Neopoints">
|
||||||
|
<Badge>NP</Badge>
|
||||||
|
</ItemBadgeTooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ItemCard;
|
Loading…
Reference in a new issue