Skip to content

Commit 2ab26f5

Browse files
Merge pull request #370 from reactioncommerce/369-feat-machikoyasuda-cartitem-subtotal
feat(#369): CartItem - Display Subtotal
2 parents 59f1a57 + e398e88 commit 2ab26f5

File tree

6 files changed

+400
-46
lines changed

6 files changed

+400
-46
lines changed

package/src/components/CartItem/v1/CartItem.js

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { withComponents } from "@reactioncommerce/components-context";
55
import { addTypographyStyles, applyTheme, CustomPropTypes } from "../../../utils";
66

77
const Item = styled.div`
8+
position: relative;
89
align-items: flex-start;
910
border-bottom-color: ${applyTheme("CartItem.borderBottomColor")};
1011
border-bottom-style: solid;
@@ -79,17 +80,39 @@ const ItemContentQuantityInput = styled.div`
7980
`;
8081

8182
const ItemContentPrice = styled.div`
82-
bottom: 0;
83-
flex: 0 1 auto;
84-
position: absolute;
83+
position: ${(props) => (props.isMiniCart ? "absolute" : "initial")};
84+
bottom: ${applyTheme("CartItem.paddingBottom")};
8585
right: 0;
86-
86+
text-align: right;
87+
@media (max-width: 768px) {
88+
position: absolute;
89+
}
8790
@media (min-width: 768px) {
8891
margin-left: 1.5rem;
89-
position: ${({ isMiniCart }) => (isMiniCart ? "absolute" : "relative")};
9092
}
9193
`;
9294

95+
const ItemContentSubtotal = styled.div`
96+
position: ${(props) => (props.isMiniCart ? "initial" : "absolute")};
97+
margin-top: ${(props) => (props.isMiniCart ? applyTheme("CartItem.subtotalDisplaySpacingAbove")(props) : "0")};
98+
bottom: ${applyTheme("CartItem.paddingBottom")};
99+
right: 0;
100+
text-align: right;
101+
@media (max-width: 768px) {
102+
position: initial;
103+
margin-top: ${applyTheme("CartItem.subtotalDisplaySpacingAbove")};
104+
}
105+
`;
106+
107+
const ItemContentSubtotalTitle = styled.div`
108+
${addTypographyStyles("ItemContentSubtotalTitle", "labelText")};
109+
white-space: pre;
110+
`;
111+
112+
const ItemContentSubtotalDisplay = styled.div`
113+
${addTypographyStyles("ItemContentSubtotalDisplay", "bodyTextSemiBold")};
114+
`;
115+
93116
const ItemRemoveButton = styled.button`
94117
${addTypographyStyles("CartItemRemoveButton", "labelText")}
95118
align-self: flex-start;
@@ -219,6 +242,12 @@ class CartItem extends Component {
219242
/**
220243
* Chosen items title
221244
*/
245+
subtotal: PropTypes.shape({
246+
/**
247+
* The display subtotal
248+
*/
249+
displayAmount: PropTypes.string
250+
}),
222251
title: PropTypes.string,
223252
/**
224253
* Quantity of chosen item in cart
@@ -293,10 +322,12 @@ class CartItem extends Component {
293322
title,
294323
quantity,
295324
isLowQuantity,
296-
price: { displayAmount: displayPrice }
325+
price: { displayAmount: displayPrice },
326+
subtotal
297327
}
298328
} = this.props;
299329

330+
const { displayAmount: displaySubtotal } = subtotal || {};
300331
const { displayAmount: displayCompareAtPrice } = compareAtPrice || {};
301332

302333
const {
@@ -339,15 +370,22 @@ class CartItem extends Component {
339370

340371
{!isReadOnly && <ItemRemoveButton onClick={this.handleRemoveItemFromCart}>Remove</ItemRemoveButton>}
341372
</ItemContentDetail>
342-
343-
<ItemContentPrice isMiniCart={isMiniCart}>
344-
<Price
345-
displayPrice={displayPrice}
346-
displayCompareAtPrice={displayCompareAtPrice}
347-
hasPriceBottom={isMiniCart}
348-
/>
349-
</ItemContentPrice>
350373
</ItemContent>
374+
<ItemContentPrice isMiniCart={isMiniCart}>
375+
<Price
376+
displayPrice={displayPrice}
377+
displayCompareAtPrice={displayCompareAtPrice}
378+
hasPriceBottom={isMiniCart}
379+
/>
380+
{ quantity !== 1 ?
381+
<ItemContentSubtotal isMiniCart={isMiniCart}>
382+
<ItemContentSubtotalTitle>Total ({quantity}):</ItemContentSubtotalTitle>
383+
<ItemContentSubtotalDisplay>{displaySubtotal}</ItemContentSubtotalDisplay>
384+
</ItemContentSubtotal>
385+
:
386+
null
387+
}
388+
</ItemContentPrice>
351389
</Item>
352390
);
353391
}

package/src/components/CartItem/v1/CartItem.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ const item = {
2626
},
2727
productSlug: "product-slug",
2828
productVendor: "Patagonia",
29+
subtotal: {
30+
displayAmount: "$40.00",
31+
},
2932
title: "A Great Product",
3033
quantity: 2
3134
};
@@ -37,6 +40,41 @@ const item = {
3740
/>
3841
```
3942

43+
#### Default: isMiniCart
44+
45+
```jsx
46+
const item = {
47+
_id: "123",
48+
attributes: [{ label: "Color", value: "Red" }, { label: "Size", value: "Medium" }],
49+
compareAtPrice: {
50+
displayAmount: "$45.00"
51+
},
52+
currentQuantity: 3,
53+
imageURLs: {
54+
small: "//placehold.it/150",
55+
thumbnail: "//placehold.it/100"
56+
},
57+
isLowQuantity: true,
58+
price: {
59+
displayAmount: "$20.00"
60+
},
61+
productSlug: "product-slug",
62+
productVendor: "Patagonia",
63+
subtotal: {
64+
displayAmount: "$40.00",
65+
},
66+
title: "A Great Product",
67+
quantity: 2
68+
};
69+
70+
<CartItem
71+
isMiniCart
72+
item={item}
73+
onChangeCartItemQuantity={(value, _id) => console.log("cart item quantity changed to", value, "for item", _id)}
74+
onRemoveItemFromCart={() => console.log("Item removed from cart")}
75+
/>
76+
```
77+
4078
#### Without Compare At Price
4179
```jsx
4280
const item = {

package/src/components/CartItem/v1/CartItem.test.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ const mockItem = {
2121
},
2222
productSlug: "product-slug",
2323
productVendor: "Patagonia",
24+
subtotal: {
25+
displayAmount: "$40.00"
26+
},
2427
title: "A Great Product",
2528
quantity: 2
2629
};

0 commit comments

Comments
 (0)