offer/seek trade pages, with placeholder data

This commit is contained in:
Emi Matchu 2020-11-23 11:25:23 -08:00
parent 9481ce05a6
commit 8068a1d260
3 changed files with 243 additions and 1 deletions

View file

@ -18,6 +18,12 @@ import WardrobePageLayout from "./WardrobePage/WardrobePageLayout";
const HomePage = loadable(() => import("./HomePage"));
const ItemPage = loadable(() => import("./ItemPage"));
const ItemTradesOfferingPage = loadable(() =>
import("./ItemTradesPage").then((m) => m.ItemTradesOfferingPage)
);
const ItemTradesSeekingPage = loadable(() =>
import("./ItemTradesPage").then((m) => m.ItemTradesSeekingPage)
);
const ModelingPage = loadable(() => import("./ModelingPage"));
const UserItemsPage = loadable(() => import("./UserItemsPage"));
const WardrobePage = loadable(() => import("./WardrobePage"), {
@ -70,6 +76,16 @@ function App() {
<ChakraProvider theme={theme}>
<CSSReset />
<Switch>
<Route path="/items/:itemId/trades/offering">
<PageLayout>
<ItemTradesOfferingPage />
</PageLayout>
</Route>
<Route path="/items/:itemId/trades/seeking">
<PageLayout>
<ItemTradesSeekingPage />
</PageLayout>
</Route>
<Route path="/items/:itemId">
<PageLayout>
<ItemPage />

226
src/app/ItemTradesPage.js Normal file
View file

@ -0,0 +1,226 @@
import React from "react";
import { css } from "emotion";
import { Box, Tooltip, useColorModeValue, useToken } from "@chakra-ui/core";
import gql from "graphql-tag";
import { useQuery } from "@apollo/client";
import { useHistory, useParams } from "react-router-dom";
import { Heading2, usePageTitle } from "./util";
import ItemPageLayout from "./ItemPageLayout";
export function ItemTradesOfferingPage() {
return (
<ItemTradesPage
title="Trades: Offering"
userHeading="Owner"
compareListHeading="They're seeking"
/>
);
}
export function ItemTradesSeekingPage() {
return (
<ItemTradesPage
title="Trades: Seeking"
userHeading="Seeker"
compareListHeading="They're offering"
/>
);
}
function ItemTradesPage({ title, userHeading, compareListHeading }) {
const { itemId } = useParams();
const { loading, error, data } = useQuery(
gql`
query ItemTradesPage($itemId: ID!) {
item(id: $itemId) {
id
name
isNc
isPb
thumbnailUrl
description
createdAt
}
}
`,
{ variables: { itemId }, returnPartialData: true }
);
usePageTitle(`${data?.item?.name} | ${title}`, { skip: loading });
if (error) {
return <Box color="red.400">{error.message}</Box>;
}
return (
<ItemPageLayout item={data?.item}>
<Heading2 marginTop="6" marginBottom="4">
{title}
</Heading2>
<ItemTradesTable
itemId={itemId}
userHeading={userHeading}
compareListHeading={compareListHeading}
/>
</ItemPageLayout>
);
}
function ItemTradesTable({ itemId, userHeading, compareListHeading }) {
return (
<Box
as="table"
width="100%"
boxShadow="md"
className={css`
/* Chakra doesn't have props for these! */
border-collapse: separate;
border-spacing: 0;
`}
>
<Box as="thead">
<Box as="tr">
<ItemTradesTableCell as="th">{userHeading}</ItemTradesTableCell>
<ItemTradesTableCell as="th">List</ItemTradesTableCell>
<ItemTradesTableCell as="th">
{/* A small wording tweak to fit better on the xsmall screens! */}
<Box display={{ base: "none", sm: "block" }}>Last updated</Box>
<Box display={{ base: "block", sm: "none" }}>Updated</Box>
</ItemTradesTableCell>
<ItemTradesTableCell as="th">Compare</ItemTradesTableCell>
</Box>
</Box>
<Box as="tbody">
<ItemTradesTableRow compareListHeading={compareListHeading} />
<ItemTradesTableRow compareListHeading={compareListHeading} />
<ItemTradesTableRow compareListHeading={compareListHeading} />
<ItemTradesTableRow compareListHeading={compareListHeading} />
<ItemTradesTableRow compareListHeading={compareListHeading} />
</Box>
</Box>
);
}
function ItemTradesTableRow({ compareListHeading }) {
const href = "/user/6/items#list-1";
const history = useHistory();
const onClick = React.useCallback(() => history.push(href), [history, href]);
const focusBackground = useColorModeValue("gray.100", "gray.600");
return (
<Box
as="tr"
cursor={"pointer"}
_hover={{ background: focusBackground }}
_focusWithin={{ background: focusBackground }}
onClick={onClick}
>
<ItemTradesTableCell>Matchu</ItemTradesTableCell>
<ItemTradesTableCell>
<Box
as="a"
href="/user/6/items#list-1"
className={css`
&:hover,
&:focus,
tr:hover &,
tr:focus-within & {
text-decoration: underline;
}
`}
>
Top priorities and such so yeah
</Box>
</ItemTradesTableCell>
<ItemTradesTableCell>&lt;1 week</ItemTradesTableCell>
<ItemTradesTableCell height="100%">
<Tooltip
placement="bottom"
label={
<Box>
{compareListHeading}:
<Box as="ul" listStyle="disc">
<Box as="li" marginLeft="1em">
Adorable Freckles
</Box>
<Box as="li" marginLeft="1em">
Constellation Dress
</Box>
</Box>
</Box>
}
>
<Box
tabIndex="0"
width="100%"
className={css`
&:hover,
&:focus,
tr:hover &,
tr:focus-within & {
text-decoration: underline dashed;
}
`}
>
<Box display={{ base: "block", md: "none" }}>2 match</Box>
<Box display={{ base: "none", md: "block" }}>2 matches</Box>
</Box>
</Tooltip>
</ItemTradesTableCell>
</Box>
);
}
function ItemTradesTableCell({ children, as = "td", ...props }) {
const borderColor = useColorModeValue("gray.300", "gray.400");
const borderColorCss = useToken("colors", borderColor);
const borderRadiusCss = useToken("radii", "md");
return (
<Box
as={as}
paddingX="4"
paddingY="2"
textAlign="left"
fontSize={{ base: "xs", sm: "sm" }}
className={css`
/* Lol sigh, getting this right is way more involved than I wish it
* were. What I really want is border-collapse and a simple 1px border,
* but that disables border-radius. So, we homebrew it by giving all
* cells bottom and right borders, but only the cells on the edges a
* top or left border; and then target the exact 4 corner cells to
* round them. Pretty old-school tbh 🙃 */
border-bottom: 1px solid ${borderColorCss};
border-right: 1px solid ${borderColorCss};
thead tr:first-of-type & {
border-top: 1px solid ${borderColorCss};
}
&:first-of-type {
border-left: 1px solid ${borderColorCss};
}
thead tr:first-of-type &:first-of-type {
border-top-left-radius: ${borderRadiusCss};
}
thead tr:first-of-type &:last-of-type {
border-top-right-radius: ${borderRadiusCss};
}
tbody tr:last-of-type &:first-of-type {
border-bottom-left-radius: ${borderRadiusCss};
}
tbody tr:last-of-type &:last-of-type {
border-bottom-right-radius: ${borderRadiusCss};
}
`}
{...props}
>
{children}
</Box>
);
}

View file

@ -412,7 +412,7 @@ function ClosetList({ closetList, isCurrentUser, showHeading }) {
});
return (
<Box>
<Box id={`list-${closetList.id}`}>
{showHeading && (
<Heading3
marginBottom="2"