From c23243fcb796725908c6476b7bf6367e9b2564aa Mon Sep 17 00:00:00 2001 From: Matchu Date: Tue, 24 Nov 2020 14:43:43 -0800 Subject: [PATCH] add real timestamp to trades page --- src/app/ItemTradesPage.js | 22 ++++++++++++++++------ src/server/loaders.js | 39 +++++++++++++++++++++++++++++++++++++++ src/server/types/User.js | 9 +++++++++ 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/app/ItemTradesPage.js b/src/app/ItemTradesPage.js index 06ac2d3..a076080 100644 --- a/src/app/ItemTradesPage.js +++ b/src/app/ItemTradesPage.js @@ -29,7 +29,7 @@ export function ItemTradesOfferingPage() { user { id username - # lastUpdatedAnyTrade + lastTradeActivity } closetList { id @@ -58,7 +58,7 @@ export function ItemTradesSeekingPage() { user { id username - # lastUpdatedAnyTrade + lastTradeActivity } closetList { id @@ -155,7 +155,7 @@ function ItemTradesTable({ {/* A small wording tweak to fit better on the xsmall screens! */} Last active - Updated + Active at Compare @@ -181,6 +181,7 @@ function ItemTradesTable({ href={`/user/${trade.user.id}/items#list-${trade.closetList.id}`} username={trade.user.username} listName={trade.closetList.name} + lastTradeActivity={trade.user.lastTradeActivity} /> ))} {!loading && data.item.trades.length === 0 && ( @@ -199,7 +200,13 @@ function ItemTradesTable({ ); } -function ItemTradesTableRow({ compareListHeading, href, username, listName }) { +function ItemTradesTableRow({ + compareListHeading, + href, + username, + listName, + lastTradeActivity, +}) { const history = useHistory(); const onClick = React.useCallback(() => history.push(href), [history, href]); const focusBackground = useColorModeValue("gray.100", "gray.600"); @@ -232,8 +239,10 @@ function ItemTradesTableRow({ compareListHeading, href, username, listName }) { {username} - <1 week - This week + {new Intl.DateTimeFormat("en", { + month: "short", + year: "numeric", + }).format(new Date(lastTradeActivity))} + (WIP: This is placeholder data!) } > diff --git a/src/server/loaders.js b/src/server/loaders.js index e2108af..57df5dc 100644 --- a/src/server/loaders.js +++ b/src/server/loaders.js @@ -919,6 +919,44 @@ const buildUserClosetListsLoader = (db, loaders) => ); }); +const buildUserLastTradeActivityLoader = (db) => + new DataLoader(async (userIds) => { + const qs = userIds.map((_) => "?").join(","); + const [rows, _] = await db.execute( + ` + SELECT + closet_hangers.user_id AS user_id, + MAX(closet_hangers.updated_at) AS last_trade_activity + FROM closet_hangers + INNER JOIN users ON users.id = closet_hangers.user_id + LEFT JOIN closet_lists ON closet_lists.id = closet_hangers.list_id + WHERE ( + closet_hangers.user_id IN (${qs}) + AND ( + (closet_hangers.list_id IS NOT NULL AND closet_lists.visibility >= 2) + OR ( + closet_hangers.list_id IS NULL AND closet_hangers.owned = 1 + AND users.owned_closet_hangers_visibility >= 2 + ) + OR ( + closet_hangers.list_id IS NULL AND closet_hangers.owned = 0 + AND users.wanted_closet_hangers_visibility >= 2 + ) + ) + ) + GROUP BY closet_hangers.user_id + `, + userIds + ); + + const entities = rows.map(normalizeRow); + + return userIds.map((userId) => { + const entity = entities.find((e) => e.userId === String(userId)); + return entity ? entity.lastTradeActivity : null; + }); + }); + const buildZoneLoader = (db) => { const zoneLoader = new DataLoader(async (ids) => { const qs = ids.map((_) => "?").join(","); @@ -1022,6 +1060,7 @@ function buildLoaders(db) { loaders.userByEmailLoader = buildUserByEmailLoader(db); loaders.userClosetHangersLoader = buildUserClosetHangersLoader(db); loaders.userClosetListsLoader = buildUserClosetListsLoader(db, loaders); + loaders.userLastTradeActivityLoader = buildUserLastTradeActivityLoader(db); loaders.zoneLoader = buildZoneLoader(db); loaders.zoneTranslationLoader = buildZoneTranslationLoader(db); diff --git a/src/server/types/User.js b/src/server/types/User.js index 14af26c..5c521a3 100644 --- a/src/server/types/User.js +++ b/src/server/types/User.js @@ -10,6 +10,10 @@ const typeDefs = gql` itemsTheyOwn: [Item!]! itemsTheyWant: [Item!]! + + # When this user last updated any of their trade lists, as an ISO 8601 + # timestamp. + lastTradeActivity: String! } extend type Query { @@ -166,6 +170,11 @@ const resolvers = { return closetListNodes; }, + + lastTradeActivity: async ({ id }, _, { userLastTradeActivityLoader }) => { + const lastTradeActivity = await userLastTradeActivityLoader.load(id); + return lastTradeActivity.toISOString(); + }, }, Query: {