diff --git a/src/app/UserItemsPage.js b/src/app/UserItemsPage.js
index e67a288..0e02447 100644
--- a/src/app/UserItemsPage.js
+++ b/src/app/UserItemsPage.js
@@ -1,12 +1,12 @@
import React from "react";
-import { Badge, Box, Center, Wrap } from "@chakra-ui/core";
+import { Badge, Box, Center, Wrap, VStack } from "@chakra-ui/core";
import { CheckIcon, EmailIcon, StarIcon } from "@chakra-ui/icons";
import gql from "graphql-tag";
import { useParams } from "react-router-dom";
import { useQuery } from "@apollo/client";
import HangerSpinner from "./components/HangerSpinner";
-import { Heading1, Heading2 } from "./util";
+import { Heading1, Heading2, Heading3 } from "./util";
import ItemCard, {
ItemBadgeList,
ItemCardList,
@@ -32,27 +32,22 @@ function UserItemsPage() {
username
contactNeopetsUsername
- itemsTheyOwn {
+ closetLists {
id
- isNc
name
- thumbnailUrl
- currentUserWantsThis
- allOccupiedZones {
+ ownsOrWantsItems
+ isDefaultList
+ items {
id
- label @client
- }
- }
-
- itemsTheyWant {
- id
- isNc
- name
- thumbnailUrl
- currentUserOwnsThis
- allOccupiedZones {
- id
- label @client
+ isNc
+ name
+ thumbnailUrl
+ currentUserOwnsThis
+ currentUserWantsThis
+ allOccupiedZones {
+ id
+ label @client
+ }
}
}
}
@@ -73,36 +68,48 @@ function UserItemsPage() {
return {error.message};
}
- // This helps you compare your owns/wants to other users! If they own
- // something, and you want it, we say "You want this!". And if they want
- // something, and you own it, we say "You own this!".
- const showYouOwnThisBadge = (item) =>
- !isCurrentUser && item.currentUserOwnsThis;
- const showYouWantThisBadge = (item) =>
- !isCurrentUser && item.currentUserWantsThis;
+ if (data.user == null) {
+ return User not found;
+ }
- const numYouOwnThisBadges = data.user.itemsTheyWant.filter(
- showYouOwnThisBadge
- ).length;
- const numYouWantThisBadges = data.user.itemsTheyOwn.filter(
- showYouWantThisBadge
- ).length;
+ const listsOfOwnedItems = data.user.closetLists.filter(
+ (l) => l.ownsOrWantsItems === "OWNS"
+ );
+ const listsOfWantedItems = data.user.closetLists.filter(
+ (l) => l.ownsOrWantsItems === "WANTS"
+ );
- const sortedItemsTheyOwn = [...data.user.itemsTheyOwn].sort((a, b) => {
- // This is a cute sort hack. We sort first by, bringing "You want this!" to
- // the top, and then sorting by name _within_ those two groups.
- const aName = `${showYouWantThisBadge(a) ? "000" : "999"} ${a.name}`;
- const bName = `${showYouWantThisBadge(b) ? "000" : "999"} ${b.name}`;
+ // Sort default list to the end, then sort alphabetically. We use a similar
+ // sort hack that we use for sorting items in ClosetList!
+ listsOfOwnedItems.sort((a, b) => {
+ const aName = `${a.isDefaultList ? "ZZZ" : "AAA"} ${a.name}`;
+ const bName = `${b.isDefaultList ? "ZZZ" : "AAA"} ${b.name}`;
+ return aName.localeCompare(bName);
+ });
+ listsOfWantedItems.sort((a, b) => {
+ const aName = `${a.isDefaultList ? "ZZZ" : "AAA"} ${a.name}`;
+ const bName = `${b.isDefaultList ? "ZZZ" : "AAA"} ${b.name}`;
return aName.localeCompare(bName);
});
- const sortedItemsTheyWant = [...data.user.itemsTheyWant].sort((a, b) => {
- // This is a cute sort hack. We sort first by, bringing "You own this!" to
- // the top, and then sorting by name _within_ those two groups.
- const aName = `${showYouOwnThisBadge(a) ? "000" : "999"} ${a.name}`;
- const bName = `${showYouOwnThisBadge(b) ? "000" : "999"} ${b.name}`;
- return aName.localeCompare(bName);
- });
+ const allItemsTheyOwn = listsOfOwnedItems.map((l) => l.items).flat();
+ const allItemsTheyWant = listsOfWantedItems.map((l) => l.items).flat();
+
+ const itemsTheyOwnThatYouWant = allItemsTheyOwn.filter(
+ (i) => i.currentUserWantsThis
+ );
+ const itemsTheyWantThatYouOwn = allItemsTheyWant.filter(
+ (i) => i.currentUserOwnsThis
+ );
+
+ // It's important to de-duplicate these! Otherwise, if the same item appears
+ // in multiple lists, we'll double-count it.
+ const numItemsTheyOwnThatYouWant = new Set(
+ itemsTheyOwnThatYouWant.map((i) => i.id)
+ ).size;
+ const numItemsTheyWantThatYouOwn = new Set(
+ itemsTheyWantThatYouOwn.map((i) => i.id)
+ ).size;
return (
@@ -140,7 +147,7 @@ function UserItemsPage() {
* _this user_ owns, so they come first. I think it's also probably a
* more natural train of thought: you come to someone's list _wanting_
* something, and _then_ thinking about what you can offer. */}
- {numYouWantThisBadges > 0 && (
+ {!isCurrentUser && numItemsTheyOwnThatYouWant > 0 && (
- {numYouWantThisBadges > 1
- ? `${numYouWantThisBadges} items you want`
+ {numItemsTheyOwnThatYouWant > 1
+ ? `${numItemsTheyOwnThatYouWant} items you want`
: "1 item you want"}
)}
- {numYouOwnThisBadges > 0 && (
+ {!isCurrentUser && numItemsTheyWantThatYouOwn > 0 && (
- {numYouOwnThisBadges > 1
- ? `${numYouOwnThisBadges} items you own`
+ {numItemsTheyWantThatYouOwn > 1
+ ? `${numItemsTheyWantThatYouOwn} items you own`
: "1 item you own"}
)}
-
+
{isCurrentUser ? "Items you own" : `Items ${data.user.username} owns`}
-
- {sortedItemsTheyOwn.map((item) => {
- return (
+
+ {listsOfOwnedItems.map((closetList) => (
+ 1}
+ />
+ ))}
+
+
+
+ {isCurrentUser ? "Items you want" : `Items ${data.user.username} wants`}
+
+
+ {listsOfWantedItems.map((closetList) => (
+ 1}
+ />
+ ))}
+
+
+ );
+}
+
+function ClosetList({ closetList, isCurrentUser, showHeading }) {
+ const hasYouWantThisBadge = (item) =>
+ !isCurrentUser &&
+ closetList.ownsOrWantsItems === "OWNS" &&
+ item.currentUserWantsThis;
+ const hasYouOwnThisBadge = (item) =>
+ !isCurrentUser &&
+ closetList.ownsOrWantsItems === "WANTS" &&
+ item.currentUserOwnsThis;
+ const hasAnyTradeBadge = (item) =>
+ hasYouOwnThisBadge(item) || hasYouWantThisBadge(item);
+
+ const sortedItems = [...closetList.items].sort((a, b) => {
+ // This is a cute sort hack. We sort first by, bringing "You own/want
+ // this!" to the top, and then sorting by name _within_ those two groups.
+ const aName = `${hasAnyTradeBadge(a) ? "000" : "999"} ${a.name}`;
+ const bName = `${hasAnyTradeBadge(b) ? "000" : "999"} ${b.name}`;
+ return aName.localeCompare(bName);
+ });
+
+ return (
+
+ {showHeading && (
+
+ {closetList.name}
+
+ )}
+ {sortedItems.length > 0 ? (
+
+ {sortedItems.map((item) => (
{item.isNc ? : }
- {showYouWantThisBadge(item) && }
+ {hasYouOwnThisBadge(item) && }
+ {hasYouWantThisBadge(item) && }
}
/>
- );
- })}
-
-
-
- {isCurrentUser ? "Items you want" : `Items ${data.user.username} wants`}
-
-
- {sortedItemsTheyWant.map((item) => (
-
- {item.isNc ? : }
- {showYouOwnThisBadge(item) && }
-
-
- }
- />
- ))}
-
+ ))}
+
+ ) : (
+ This list is empty!
+ )}
);
}
diff --git a/src/app/util.js b/src/app/util.js
index 8bd4122..8376aac 100644
--- a/src/app/util.js
+++ b/src/app/util.js
@@ -34,6 +34,7 @@ export function Delay({ children, ms = 300 }) {
export function Heading1({ children, ...props }) {
return (
+ {children}
+
+ );
+}
+
/**
* safeImageUrl returns an HTTPS-safe image URL for Neopets assets!
*/
diff --git a/src/server/types/User.js b/src/server/types/User.js
index bf5822e..bdcfbd6 100644
--- a/src/server/types/User.js
+++ b/src/server/types/User.js
@@ -168,7 +168,7 @@ const resolvers = {
if (isCurrentUser || user.ownedClosetHangersVisibility >= 1) {
closetListNodes.push({
id: `user-${id}-default-list-OWNS`,
- name: "(Not in a list)",
+ name: "Not in a list",
ownsOrWantsItems: "OWNS",
isDefaultList: true,
items: allClosetHangers
@@ -180,7 +180,7 @@ const resolvers = {
if (isCurrentUser || user.wantedClosetHangersVisibility >= 1) {
closetListNodes.push({
id: `user-${id}-default-list-WANTS`,
- name: "(Not in a list)",
+ name: "Not in a list",
ownsOrWantsItems: "WANTS",
isDefaultList: true,
items: allClosetHangers