add created at date to item page

this will help me notice which items are new! lol
This commit is contained in:
Emi Matchu 2020-09-15 04:15:15 -07:00
parent 57c0981472
commit ffeb494f45
4 changed files with 72 additions and 0 deletions

View file

@ -7,6 +7,7 @@ import {
Box, Box,
Skeleton, Skeleton,
SkeletonText, SkeletonText,
Tooltip,
VisuallyHidden, VisuallyHidden,
VStack, VStack,
useBreakpointValue, useBreakpointValue,
@ -63,6 +64,7 @@ function ItemPageHeader({ itemId, isEmbedded }) {
isNc isNc
thumbnailUrl thumbnailUrl
description description
createdAt
} }
} }
`, `,
@ -130,6 +132,20 @@ function ItemPageBadges({ item, isEmbedded }) {
<Skeleton isLoaded={item?.isNc != null}> <Skeleton isLoaded={item?.isNc != null}>
{item?.isNc ? <NcBadge /> : <NpBadge />} {item?.isNc ? <NcBadge /> : <NpBadge />}
</Skeleton> </Skeleton>
{
// If the createdAt date is null (loaded and empty), hide the badge.
item.createdAt !== null && (
<Skeleton
// Distinguish between undefined (still loading) and null (loaded and
// empty).
isLoaded={item.createdAt !== undefined}
>
<Badge display="block">
<ShortTimestamp when={item.createdAt || "1970-01-01"} />
</Badge>
</Skeleton>
)
}
<Skeleton isLoaded={searchBadgesAreLoaded}> <Skeleton isLoaded={searchBadgesAreLoaded}>
<LinkBadge <LinkBadge
href={`https://impress.openneo.net/items/${item.id}`} href={`https://impress.openneo.net/items/${item.id}`}
@ -228,6 +244,47 @@ function LinkBadge({ children, href, 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 (
<Tooltip
label={`First seen on ${fullDateFormatter.format(date)}`}
placement="top"
openDelay={400}
>
{dateIsOlderThanLastMonth
? monthYearFormatter.format(date)
: monthDayYearFormatter.format(date)}
</Tooltip>
);
}
function ItemPageOwnWantButtons({ itemId }) { function ItemPageOwnWantButtons({ itemId }) {
const theme = useTheme(); const theme = useTheme();
const toast = useToast(); const toast = useToast();

View file

@ -13,6 +13,7 @@ describe("Item", () => {
thumbnailUrl thumbnailUrl
rarityIndex rarityIndex
isNc isNc
createdAt
manualSpecialColor { manualSpecialColor {
id id
name name

View file

@ -11926,6 +11926,7 @@ exports[`Item loads metadata 1`] = `
Object { Object {
"items": Array [ "items": Array [
Object { Object {
"createdAt": null,
"description": "Dont leave any trace that you were there with these gloves.", "description": "Dont leave any trace that you were there with these gloves.",
"explicitlyBodySpecific": false, "explicitlyBodySpecific": false,
"id": "38913", "id": "38913",
@ -11936,6 +11937,7 @@ Object {
"thumbnailUrl": "http://images.neopets.com/items/clo_zafara_agent_gloves.gif", "thumbnailUrl": "http://images.neopets.com/items/clo_zafara_agent_gloves.gif",
}, },
Object { Object {
"createdAt": null,
"description": "Hide your face and hair so no one can recognise you.", "description": "Hide your face and hair so no one can recognise you.",
"explicitlyBodySpecific": false, "explicitlyBodySpecific": false,
"id": "38911", "id": "38911",
@ -11946,6 +11948,7 @@ Object {
"thumbnailUrl": "http://images.neopets.com/items/clo_zafara_agent_hood.gif", "thumbnailUrl": "http://images.neopets.com/items/clo_zafara_agent_hood.gif",
}, },
Object { Object {
"createdAt": null,
"description": "This robe is great for being stealthy.", "description": "This robe is great for being stealthy.",
"explicitlyBodySpecific": false, "explicitlyBodySpecific": false,
"id": "38912", "id": "38912",
@ -11956,6 +11959,7 @@ Object {
"thumbnailUrl": "http://images.neopets.com/items/clo_zafara_agent_robe.gif", "thumbnailUrl": "http://images.neopets.com/items/clo_zafara_agent_robe.gif",
}, },
Object { Object {
"createdAt": "2011-03-31T07:15:51.000Z",
"description": "Maybe youll be discovered by some Neopets from the future and thawed out!", "description": "Maybe youll be discovered by some Neopets from the future and thawed out!",
"explicitlyBodySpecific": true, "explicitlyBodySpecific": true,
"id": "55788", "id": "55788",
@ -11966,6 +11970,7 @@ Object {
"thumbnailUrl": "http://images.neopets.com/items/mall_petinice.gif", "thumbnailUrl": "http://images.neopets.com/items/mall_petinice.gif",
}, },
Object { Object {
"createdAt": "2018-04-13T01:23:08.000Z",
"description": "Made with the finest jewels of the sea!", "description": "Made with the finest jewels of the sea!",
"explicitlyBodySpecific": false, "explicitlyBodySpecific": false,
"id": "77530", "id": "77530",
@ -11979,6 +11984,7 @@ Object {
"thumbnailUrl": "http://images.neopets.com/items/mall_clo_marabluegown.gif", "thumbnailUrl": "http://images.neopets.com/items/mall_clo_marabluegown.gif",
}, },
Object { Object {
"createdAt": "2018-06-23T04:50:35.000Z",
"description": "You truly are the number one fan of Altador Cup, and your room reflects this!", "description": "You truly are the number one fan of Altador Cup, and your room reflects this!",
"explicitlyBodySpecific": false, "explicitlyBodySpecific": false,
"id": "78104", "id": "78104",

View file

@ -10,6 +10,10 @@ const typeDefs = gql`
rarityIndex: Int! rarityIndex: Int!
isNc: Boolean! isNc: Boolean!
# When this item was first added to DTI. ISO 8601 string, or null if the
# item was added so long ago that we don't have this field!
createdAt: String
currentUserOwnsThis: Boolean! currentUserOwnsThis: Boolean!
currentUserWantsThis: Boolean! currentUserWantsThis: Boolean!
@ -102,6 +106,10 @@ const resolvers = {
const item = await itemLoader.load(id); const item = await itemLoader.load(id);
return item.rarityIndex === 500 || item.rarityIndex === 0; return item.rarityIndex === 500 || item.rarityIndex === 0;
}, },
createdAt: async ({ id }, _, { itemLoader }) => {
const item = await itemLoader.load(id);
return item.createdAt && item.createdAt.toISOString();
},
currentUserOwnsThis: async ( currentUserOwnsThis: async (
{ id }, { id },