Skip to content

Commit 0980a43

Browse files
Matthew FreireMatthew Freire
authored andcommitted
Updating and removing items in cart
1 parent e1cd3a9 commit 0980a43

File tree

6 files changed

+136
-6
lines changed

6 files changed

+136
-6
lines changed

core/api/urls.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
ItemDetailView,
66
AddToCartView,
77
OrderDetailView,
8+
OrderQuantityUpdateView,
89
PaymentView,
910
AddCouponView,
1011
CountryListView,
1112
AddressListView,
1213
AddressCreateView,
1314
AddressUpdateView,
14-
AddressDeleteView
15+
AddressDeleteView,
16+
OrderItemDeleteView
1517
)
1618

1719
urlpatterns = [
@@ -29,4 +31,8 @@
2931
path('order-summary/', OrderDetailView.as_view(), name='order-summary'),
3032
path('checkout/', PaymentView.as_view(), name='checkout'),
3133
path('add-coupon/', AddCouponView.as_view(), name='add-coupon'),
34+
path('order-items/<pk>/delete/',
35+
OrderItemDeleteView.as_view(), name='order-item-delete'),
36+
path('order-item/update-quantity/',
37+
OrderQuantityUpdateView.as_view(), name='order-item-update-quantity'),
3238
]

core/api/views.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,42 @@ class ItemDetailView(RetrieveAPIView):
4040
queryset = Item.objects.all()
4141

4242

43+
class OrderQuantityUpdateView(APIView):
44+
def post(self, request, *args, **kwargs):
45+
slug = request.data.get('slug', None)
46+
if slug is None:
47+
return Response({"message": "Invalid data"}, status=HTTP_400_BAD_REQUEST)
48+
item = get_object_or_404(Item, slug=slug)
49+
order_qs = Order.objects.filter(
50+
user=request.user,
51+
ordered=False
52+
)
53+
if order_qs.exists():
54+
order = order_qs[0]
55+
# check if the order item is in the order
56+
if order.items.filter(item__slug=item.slug).exists():
57+
order_item = OrderItem.objects.filter(
58+
item=item,
59+
user=request.user,
60+
ordered=False
61+
)[0]
62+
if order_item.quantity > 1:
63+
order_item.quantity -= 1
64+
order_item.save()
65+
else:
66+
order.items.remove(order_item)
67+
return Response(status=HTTP_200_OK)
68+
else:
69+
return Response({"message": "This item was not in your cart"}, status=HTTP_400_BAD_REQUEST)
70+
else:
71+
return Response({"message": "You do not have an active order"}, status=HTTP_400_BAD_REQUEST)
72+
73+
74+
class OrderItemDeleteView(DestroyAPIView):
75+
permission_classes = (IsAuthenticated, )
76+
queryset = OrderItem.objects.all()
77+
78+
4379
class AddToCartView(APIView):
4480
def post(self, request, *args, **kwargs):
4581
slug = request.data.get('slug', None)

db.sqlite3

0 Bytes
Binary file not shown.

src/constants.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ export const addressListURL = addressType =>
1717
export const addressCreateURL = `${endpoint}/addresses/create/`;
1818
export const addressUpdateURL = id => `${endpoint}/addresses/${id}/update/`;
1919
export const addressDeleteURL = id => `${endpoint}/addresses/${id}/delete/`;
20+
export const orderItemDeleteURL = id => `${endpoint}/order-items/${id}/delete/`;
21+
export const orderItemUpdateQuantityURL = `${endpoint}/order-item/update-quantity/`;

src/containers/Layout.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ class CustomLayout extends React.Component {
2222

2323
render() {
2424
const { authenticated, cart, loading } = this.props;
25-
console.log(cart);
2625
return (
2726
<div>
2827
<Menu inverted>

src/containers/OrderSummary.js

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
Container,
44
Dimmer,
55
Header,
6+
Icon,
67
Image,
78
Label,
89
Loader,
@@ -11,9 +12,15 @@ import {
1112
Message,
1213
Segment
1314
} from "semantic-ui-react";
14-
import { Link } from "react-router-dom";
15+
import { connect } from "react-redux";
16+
import { Link, Redirect } from "react-router-dom";
1517
import { authAxios } from "../utils";
16-
import { orderSummaryURL } from "../constants";
18+
import {
19+
addToCartURL,
20+
orderSummaryURL,
21+
orderItemDeleteURL,
22+
orderItemUpdateQuantityURL
23+
} from "../constants";
1724

1825
class OrderSummary extends React.Component {
1926
state = {
@@ -53,8 +60,57 @@ class OrderSummary extends React.Component {
5360
return text;
5461
};
5562

63+
handleFormatData = itemVariations => {
64+
// convert [{id: 1},{id: 2}] to [1,2] - they're all variations
65+
return Object.keys(itemVariations).map(key => {
66+
return itemVariations[key].id;
67+
});
68+
};
69+
70+
handleAddToCart = (slug, itemVariations) => {
71+
this.setState({ loading: true });
72+
const variations = this.handleFormatData(itemVariations);
73+
authAxios
74+
.post(addToCartURL, { slug, variations })
75+
.then(res => {
76+
this.handleFetchOrder();
77+
this.setState({ loading: false });
78+
})
79+
.catch(err => {
80+
this.setState({ error: err, loading: false });
81+
});
82+
};
83+
84+
handleRemoveQuantityFromCart = slug => {
85+
authAxios
86+
.post(orderItemUpdateQuantityURL, { slug })
87+
.then(res => {
88+
this.handleFetchOrder();
89+
})
90+
.catch(err => {
91+
this.setState({ error: err });
92+
});
93+
};
94+
95+
handleRemoveItem = itemID => {
96+
authAxios
97+
.delete(orderItemDeleteURL(itemID))
98+
.then(res => {
99+
this.handleFetchOrder();
100+
})
101+
.catch(err => {
102+
this.setState({ error: err });
103+
});
104+
};
105+
56106
render() {
57107
const { data, error, loading } = this.state;
108+
const { isAuthenticated } = this.props;
109+
if (!isAuthenticated) {
110+
return <Redirect to="/login" />;
111+
}
112+
console.log(data);
113+
58114
return (
59115
<Container>
60116
<Header>Order Summary</Header>
@@ -96,14 +152,39 @@ class OrderSummary extends React.Component {
96152
{this.renderVariations(orderItem)}
97153
</Table.Cell>
98154
<Table.Cell>${orderItem.item.price}</Table.Cell>
99-
<Table.Cell>{orderItem.quantity}</Table.Cell>
155+
<Table.Cell textAlign="center">
156+
<Icon
157+
name="minus"
158+
style={{ float: "left", cursor: "pointer" }}
159+
onClick={() =>
160+
this.handleRemoveQuantityFromCart(orderItem.item.slug)
161+
}
162+
/>
163+
{orderItem.quantity}
164+
<Icon
165+
name="plus"
166+
style={{ float: "right", cursor: "pointer" }}
167+
onClick={() =>
168+
this.handleAddToCart(
169+
orderItem.item.slug,
170+
orderItem.item_variations
171+
)
172+
}
173+
/>
174+
</Table.Cell>
100175
<Table.Cell>
101176
{orderItem.item.discount_price && (
102177
<Label color="green" ribbon>
103178
ON DISCOUNT
104179
</Label>
105180
)}
106181
${orderItem.final_price}
182+
<Icon
183+
name="trash"
184+
color="red"
185+
style={{ float: "right", cursor: "pointer" }}
186+
onClick={() => this.handleRemoveItem(orderItem.id)}
187+
/>
107188
</Table.Cell>
108189
</Table.Row>
109190
);
@@ -136,4 +217,10 @@ class OrderSummary extends React.Component {
136217
}
137218
}
138219

139-
export default OrderSummary;
220+
const mapStateToProps = state => {
221+
return {
222+
isAuthenticated: state.auth.token !== null
223+
};
224+
};
225+
226+
export default connect(mapStateToProps)(OrderSummary);

0 commit comments

Comments
 (0)