import React from "react"; import { css } from "emotion"; import { AspectRatio, Badge, Button, Box, Skeleton, SkeletonText, Tooltip, VisuallyHidden, VStack, useBreakpointValue, useColorModeValue, useTheme, useToast, } from "@chakra-ui/core"; import { CheckIcon, ExternalLinkIcon, ChevronRightIcon, StarIcon, } from "@chakra-ui/icons"; import gql from "graphql-tag"; import { useQuery } from "@apollo/client"; import { useParams } from "react-router-dom"; import { ItemBadgeList, ItemThumbnail, NcBadge, NpBadge, } from "./components/ItemCard"; import { Delay, Heading1, usePageTitle } from "./util"; import OutfitPreview from "./components/OutfitPreview"; function ItemPage() { const { itemId } = useParams(); return ; } /** * 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 ( ); } function ItemPageHeader({ itemId, isEmbedded }) { const { error, data } = useQuery( gql` query ItemPage($itemId: ID!) { item(id: $itemId) { id name isNc thumbnailUrl description createdAt } } `, { variables: { itemId }, returnPartialData: true } ); usePageTitle(data?.item?.name, { skip: isEmbedded }); // Show 2 lines of description text placeholder on small screens, or when // embedded in the wardrobe page's narrow drawer. In larger contexts, show // just 1 line. const viewportNumDescriptionLines = useBreakpointValue({ base: 2, md: 1 }); const numDescriptionLines = isEmbedded ? 2 : viewportNumDescriptionLines; if (error) { return {error.message}; } const item = data?.item; return ( <> {item?.name || "Item name here"} {item?.description || ( )} ); } function ItemPageBadges({ item, isEmbedded }) { const searchBadgesAreLoaded = item?.name != null && item?.isNc != null; return ( {item?.isNc ? : } { // If the createdAt date is null (loaded and empty), hide the badge. item.createdAt !== null && ( {item.createdAt && } ) } Old DTI Jellyneo {!item?.isNc && ( Shop Wiz )} {!item?.isNc && ( Trade Post )} {!item?.isNc && ( Auctions )} ); } function LinkBadge({ children, href, isEmbedded }) { return ( {children} { // We also change the icon to signal whether this will launch in a new // window or not! isEmbedded ? : } ); } const fullDateFormatter = new Intl.DateTimeFormat("en-US", { dateStyle: "long", }); const monthYearFormatter = new Intl.DateTimeFormat("en-US", { month: "short", year: "numeric", }); const monthDayYearFormatter = new Intl.DateTimeFormat("en-US", { month: "short", day: "numeric", year: "numeric", }); function ShortTimestamp({ when }) { const date = new Date(when); // To find the start of last month, take today, then set its date to the 1st // and its time to midnight (the start of this month), and subtract one // month. (JS handles negative months and rolls them over correctly.) const startOfLastMonth = new Date(); startOfLastMonth.setDate(1); startOfLastMonth.setHours(0); startOfLastMonth.setMinutes(0); startOfLastMonth.setSeconds(0); startOfLastMonth.setMilliseconds(0); startOfLastMonth.setMonth(startOfLastMonth.getMonth() - 1); const dateIsOlderThanLastMonth = date < startOfLastMonth; return ( {dateIsOlderThanLastMonth ? monthYearFormatter.format(date) : monthDayYearFormatter.format(date)} ); } function ItemPageOwnWantButtons({ itemId }) { const theme = useTheme(); const toast = useToast(); const [currentUserOwnsThis, setCurrentUserOwnsThis] = React.useState(false); const [currentUserWantsThis, setCurrentUserWantsThis] = React.useState(false); const { loading, error } = useQuery( gql` query ItemPageOwnWantButtons($itemId: ID!) { item(id: $itemId) { id currentUserOwnsThis currentUserWantsThis } } `, { variables: { itemId }, onCompleted: (data) => { setCurrentUserOwnsThis(data?.item?.currentUserOwnsThis || false); setCurrentUserWantsThis(data?.item?.currentUserWantsThis || false); }, } ); if (error) { return {error.message}; } return ( { setCurrentUserOwnsThis(e.target.checked); toast({ title: "Todo: This doesn't actually work yet!", status: "info", duration: 1500, }); }} /> { setCurrentUserWantsThis(e.target.checked); toast({ title: "Todo: This doesn't actually work yet!", status: "info", duration: 1500, }); }} /> ); } function IconCheckbox({ icon, isChecked, ...props }) { return ( {icon} ); } function ItemPageOutfitPreview({ itemId }) { const borderColor = useColorModeValue("green.700", "green.400"); return ( ); } export default ItemPage;