add created at date to item page
this will help me notice which items are new! lol
This commit is contained in:
parent
57c0981472
commit
ffeb494f45
4 changed files with 72 additions and 0 deletions
|
@ -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();
|
||||||
|
|
|
@ -13,6 +13,7 @@ describe("Item", () => {
|
||||||
thumbnailUrl
|
thumbnailUrl
|
||||||
rarityIndex
|
rarityIndex
|
||||||
isNc
|
isNc
|
||||||
|
createdAt
|
||||||
manualSpecialColor {
|
manualSpecialColor {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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 },
|
||||||
|
|
Loading…
Reference in a new issue