Skip to content

Commit 49b1097

Browse files
authored
feat(core): filter out child cart line items (#2827)
1 parent b5f460c commit 49b1097

4 files changed

Lines changed: 91 additions & 3 deletions

File tree

.changeset/bright-rules-chew.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
---
2+
"@bigcommerce/catalyst-core": patch
3+
---
4+
5+
Filter out child cart items (items with `parentEntityId`) from cart and cart analytics to prevent duplicate line items when products have parent-child relationships, such as product bundles.
6+
7+
## Migration steps
8+
9+
### Step 1: GraphQL Fragment Updates
10+
11+
The `parentEntityId` field has been added to both physical and digital cart item fragments to identify child items.
12+
13+
Update `core/app/[locale]/(default)/cart/page-data.ts`:
14+
15+
```diff
16+
export const PhysicalItemFragment = graphql(`
17+
fragment PhysicalItemFragment on CartPhysicalItem {
18+
entityId
19+
quantity
20+
productEntityId
21+
variantEntityId
22+
+ parentEntityId
23+
listPrice {
24+
currencyCode
25+
value
26+
}
27+
}
28+
`);
29+
30+
export const DigitalItemFragment = graphql(`
31+
fragment DigitalItemFragment on CartDigitalItem {
32+
entityId
33+
quantity
34+
productEntityId
35+
variantEntityId
36+
+ parentEntityId
37+
listPrice {
38+
currencyCode
39+
value
40+
}
41+
}
42+
`);
43+
```
44+
45+
### Step 2: Cart Display Filtering
46+
47+
Cart line items are now filtered to exclude child items when displaying the cart.
48+
49+
Update `core/app/[locale]/(default)/cart/page.tsx`:
50+
51+
```diff
52+
const lineItems = [
53+
...cart.lineItems.giftCertificates,
54+
...cart.lineItems.physicalItems,
55+
...cart.lineItems.digitalItems,
56+
- ];
57+
+ ].filter((item) => !('parentEntityId' in item) || !item.parentEntityId);
58+
```
59+
60+
### Step 3: Analytics Data Filtering
61+
62+
Analytics data collection now only includes top-level items to prevent duplicate tracking.
63+
64+
Update `core/app/[locale]/(default)/cart/page.tsx` in the `getAnalyticsData` function:
65+
66+
```diff
67+
- const lineItems = [...cart.lineItems.physicalItems, ...cart.lineItems.digitalItems];
68+
+ const lineItems = [...cart.lineItems.physicalItems, ...cart.lineItems.digitalItems].filter(
69+
+ (item) => !item.parentEntityId, // Only include top-level items
70+
+ );
71+
```
72+
73+
### Step 4: Styling Update
74+
75+
Cart subtitle text color has been updated for improved contrast.
76+
77+
Update `core/vibes/soul/sections/cart/client.tsx`:
78+
79+
```diff
80+
- <span className="text-[var(--cart-subtext-text,hsl(var(--contrast-300)))] contrast-more:text-[var(--cart-subtitle-text,hsl(var(--contrast-500)))]">
81+
+ <span className="text-[var(--cart-subtext-text,hsl(var(--contrast-400)))] contrast-more:text-[var(--cart-subtitle-text,hsl(var(--contrast-500)))]">
82+
{lineItem.subtitle}
83+
</span>
84+
```

core/app/[locale]/(default)/cart/page-data.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export const PhysicalItemFragment = graphql(`
1919
quantity
2020
productEntityId
2121
variantEntityId
22+
parentEntityId
2223
listPrice {
2324
currencyCode
2425
value
@@ -71,6 +72,7 @@ export const DigitalItemFragment = graphql(`
7172
quantity
7273
productEntityId
7374
variantEntityId
75+
parentEntityId
7476
listPrice {
7577
currencyCode
7678
value

core/app/[locale]/(default)/cart/page.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ const getAnalyticsData = async (cartId: string) => {
4141
return [];
4242
}
4343

44-
const lineItems = [...cart.lineItems.physicalItems, ...cart.lineItems.digitalItems];
44+
const lineItems = [...cart.lineItems.physicalItems, ...cart.lineItems.digitalItems].filter(
45+
(item) => !item.parentEntityId, // Only include top-level items
46+
);
4547

4648
return lineItems.map((item) => {
4749
return {
@@ -98,7 +100,7 @@ export default async function Cart({ params }: Props) {
98100
...cart.lineItems.giftCertificates,
99101
...cart.lineItems.physicalItems,
100102
...cart.lineItems.digitalItems,
101-
];
103+
].filter((item) => !('parentEntityId' in item) || !item.parentEntityId);
102104

103105
const formattedLineItems = lineItems.map((item) => {
104106
if (item.__typename === 'CartGiftCertificate') {

core/vibes/soul/sections/cart/client.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ export function CartClient<LineItem extends CartLineItem>({
451451
<div className="flex grow flex-col flex-wrap justify-between gap-y-2 @xl:flex-row">
452452
<div className="flex w-full flex-1 flex-col @xl:w-1/2 @xl:pr-4">
453453
<span className="font-medium">{lineItem.title}</span>
454-
<span className="text-[var(--cart-subtext-text,hsl(var(--contrast-300)))] contrast-more:text-[var(--cart-subtitle-text,hsl(var(--contrast-500)))]">
454+
<span className="text-[var(--cart-subtext-text,hsl(var(--contrast-400)))] contrast-more:text-[var(--cart-subtitle-text,hsl(var(--contrast-500)))]">
455455
{lineItem.subtitle}
456456
</span>
457457
</div>

0 commit comments

Comments
 (0)