Repository: artsy/metaphysics
Pull request #6694: feat: add Your Bids quick link for users with active bids
Author: login: anandaroop
Created: 2025-05-01T03:25:44Z | Merged: 2025-05-02T14:15:00Z

https://artsyproduct.atlassian.net/browse/ONYX-1691

For Quick Links v2, this Implements the conditional **Your Bids** link that is shown only to users with active bids:

```js
{
  title: "Your Bids",
  href: "/inbox",
  ownerType: OwnerType.inbox,
  icon: undefined,
}
```

Tapping on the pill takes you to `/inbox`, which in turn defaults to the **Bids** view if there are active bids.


| Pill | Destination |
|--------|--------|
| <img src="https://github.com/user-attachments/assets/429e6a63-a23b-4473-8ded-ba765a90295a" height=400 /> | <img src="https://github.com/user-attachments/assets/fcf37d0f-babd-4fd3-b989-4d68962bfb6d" height=400 /> | 





Diff:
diff --git a/src/schema/v2/homeView/sections/QuickLinks.ts b/src/schema/v2/homeView/sections/QuickLinks.ts
index 56c60b541d..98940e4497 100644
--- a/src/schema/v2/homeView/sections/QuickLinks.ts
+++ b/src/schema/v2/homeView/sections/QuickLinks.ts
@@ -12,8 +12,10 @@ export const QuickLinks: HomeViewSection = {
   ownerType: OwnerType.quickLinks,
   type: HomeViewSectionTypeNames.HomeViewSectionNavigationPills,
   requiresAuthentication: true,
-  resolver: (_parent, _args, context, _info) => {
-    return getDisplayableQuickLinks(context)
+  resolver: async (_parent, _args, context, _info) => {
+    let links = getDisplayableQuickLinks(context)
+    links = await maybeInsertYourBidsLink(links, context)
+    return links
   },
 }
 
@@ -51,6 +53,9 @@ export const QUICK_LINKS_V2: Array<NavigationPill> = [
     ownerType: OwnerType.auctions,
     icon: "GavelIcon",
   },
+  /*
+   * see below for optional Your Bids link inserted here
+   */
   {
     title: "New This Week",
     href: "/collection/new-this-week",
@@ -146,3 +151,31 @@ export const QUICK_LINKS: Array<NavigationPill> = [
     icon: "FairIcon",
   },
 ]
+
+/**
+ * If the user has currently active bids then we insert
+ * the **Your Bids** link immediately after the **Auctions** link.
+ * We return the (maybe) updated full list of quick links.
+ */
+async function maybeInsertYourBidsLink(
+  links: NavigationPill[],
+  context: ResolverContext
+): Promise<NavigationPill[]> {
+  if (isFeatureFlagEnabled("onyx_enable-quick-links-v2")) {
+    const { MyBids } = require("schema/v2/me/myBids")
+    const bids = await MyBids.resolve?.({}, {}, context, {} as any)
+    const hasBids = bids?.active?.length > 0
+    const auctionsIndex = links.findIndex((link) => link.href === "/auctions")
+
+    if (hasBids && auctionsIndex >= 0) {
+      const yourBids: NavigationPill = {
+        title: "Your Bids",
+        href: "/inbox",
+        ownerType: OwnerType.inbox,
+        icon: undefined,
+      }
+      links.splice(auctionsIndex + 1, 0, yourBids)
+    }
+  }
+  return links
+}
diff --git a/src/schema/v2/homeView/sections/__tests__/QuickLinks.test.ts b/src/schema/v2/homeView/sections/__tests__/QuickLinks.test.ts
index a740b58681..73bbbfb1a1 100644
--- a/src/schema/v2/homeView/sections/__tests__/QuickLinks.test.ts
+++ b/src/schema/v2/homeView/sections/__tests__/QuickLinks.test.ts
@@ -105,6 +105,69 @@ describe("QuickLinks", () => {
         }
       `)
     })
+
+    describe("when user has active bids", () => {
+      beforeEach(() => {
+        jest.mock("schema/v2/me/myBids", () => {
+          const originalModule = jest.requireActual("schema/v2/me/myBids")
+
+          return {
+            MyBidType: originalModule.MyBidType,
+            MyBids: {
+              ...originalModule.MyBids,
+              resolve: jest.fn().mockReturnValueOnce({
+                active: [
+                  {
+                    // some bid
+                  },
+                ],
+              }),
+            },
+          }
+        })
+      })
+      afterEach(() => {
+        jest.clearAllMocks()
+      })
+
+      it("returns the Your Bids quick link", async () => {
+        const { homeView } = await runQuery(query, context)
+
+        expect(homeView.section.navigationPills).toContainEqual(
+          expect.objectContaining({
+            title: "Your Bids",
+          })
+        )
+      })
+    })
+
+    describe("when user has no active bids", () => {
+      beforeEach(() => {
+        jest.mock("schema/v2/me/myBids", () => {
+          const originalModule = jest.requireActual("schema/v2/me/myBids")
+
+          return {
+            MyBidType: originalModule.MyBidType,
+            MyBids: {
+              ...originalModule.MyBids,
+              resolve: jest.fn().mockReturnValueOnce({}),
+            },
+          }
+        })
+      })
+      afterEach(() => {
+        jest.clearAllMocks()
+      })
+
+      it("does NOT return the Your Bids quick link", async () => {
+        const { homeView } = await runQuery(query, context)
+        expect(homeView.section.navigationPills).not.toContainEqual(
+          expect.objectContaining({
+            title: "Your Bids",
+          })
+        )
+      })
+    })
   })
 
   describe("when v2 is not enabled", () => {


Reviews:
user: login: anandaroop
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-01T13:50:55Z
user: login: dariakoko
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T10:29:12Z
user: login: olerichter00
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T10:37:34Z
user: login: anandaroop
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-02T14:11:05Z
user: login: anandaroop
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-02T14:12:52Z

Review comments:
diff_hunk: @@ -146,3 +151,26 @@ export const QUICK_LINKS: Array<NavigationPill> = [
     icon: "FairIcon",
   },
 ]
+
+async function maybeInsertYourBidsLink(
+  links: NavigationPill[],
+  context: ResolverContext
+) {
+  if (isFeatureFlagEnabled("onyx_enable-quick-links-v2")) {
+    const { MyBids } = require("schema/v2/me/myBids")
+    const bids = await MyBids.resolve?.({}, {}, context, {} as any)
+    const hasBids = bids?.active?.length > 0
+    const auctionsIndex = links.findIndex((link) => link.href === "/auctions")
path: src/schema/v2/homeView/sections/QuickLinks.ts
user: login: anandaroop
body: Noting that once this is enabled, this `MyBids.resolve(…)` check will be performed on every home view request. We should keep an eye on performance.
created_at: 2025-05-01T13:50:55Z
author_association: MEMBER
diff_hunk: @@ -146,3 +151,26 @@ export const QUICK_LINKS: Array<NavigationPill> = [
     icon: "FairIcon",
   },
 ]
+
+async function maybeInsertYourBidsLink(
path: src/schema/v2/homeView/sections/QuickLinks.ts
user: login: dariakoko
body: **minor:** maybe `shouldInsertYourBidsLink` could be a better name for this function?
created_at: 2025-05-02T10:28:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -146,3 +151,26 @@ export const QUICK_LINKS: Array<NavigationPill> = [
     icon: "FairIcon",
   },
 ]
+
+async function maybeInsertYourBidsLink(
+  links: NavigationPill[],
+  context: ResolverContext
+) {
+  if (isFeatureFlagEnabled("onyx_enable-quick-links-v2")) {
+    const { MyBids } = require("schema/v2/me/myBids")
+    const bids = await MyBids.resolve?.({}, {}, context, {} as any)
+    const hasBids = bids?.active?.length > 0
+    const auctionsIndex = links.findIndex((link) => link.href === "/auctions")
+
+    if (hasBids && auctionsIndex >= 0) {
+      const yourBids: NavigationPill = {
+        title: "Your Bids",
+        href: "/inbox",
+        ownerType: OwnerType.inbox,
+        icon: undefined,
+      }
+      links.splice(auctionsIndex + 1, 0, yourBids)
+    }
path: src/schema/v2/homeView/sections/QuickLinks.ts
user: login: olerichter00
body: A comment would be helpful to explain where and under what conditions the navigation pill is inserted.
created_at: 2025-05-02T10:37:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -146,3 +151,26 @@ export const QUICK_LINKS: Array<NavigationPill> = [
     icon: "FairIcon",
   },
 ]
+
+async function maybeInsertYourBidsLink(
+  links: NavigationPill[],
+  context: ResolverContext
+) {
+  if (isFeatureFlagEnabled("onyx_enable-quick-links-v2")) {
+    const { MyBids } = require("schema/v2/me/myBids")
+    const bids = await MyBids.resolve?.({}, {}, context, {} as any)
+    const hasBids = bids?.active?.length > 0
+    const auctionsIndex = links.findIndex((link) => link.href === "/auctions")
+
+    if (hasBids && auctionsIndex >= 0) {
+      const yourBids: NavigationPill = {
+        title: "Your Bids",
+        href: "/inbox",
+        ownerType: OwnerType.inbox,
+        icon: undefined,
+      }
+      links.splice(auctionsIndex + 1, 0, yourBids)
+    }
path: src/schema/v2/homeView/sections/QuickLinks.ts
user: login: anandaroop
body: Added in 31b02eeec 👍🏽 
created_at: 2025-05-02T14:11:05Z
author_association: MEMBER
diff_hunk: @@ -146,3 +151,26 @@ export const QUICK_LINKS: Array<NavigationPill> = [
     icon: "FairIcon",
   },
 ]
+
+async function maybeInsertYourBidsLink(
path: src/schema/v2/homeView/sections/QuickLinks.ts
user: login: anandaroop
body: If this were a predicate function I would agree, but since this actually mutates the list, this naming convention is pretty standard (we [use it a lot](https://github.com/search?q=org%3Aartsy+%2Fmaybe%5Cw%7B5%2C%7D%2F&type=code), in fact)
created_at: 2025-05-02T14:12:52Z
author_association: MEMBER

PR comments: