diff --git a/artel/artel/settings/base.py b/artel/artel/settings/base.py index fad24bd..15ea9df 100644 --- a/artel/artel/settings/base.py +++ b/artel/artel/settings/base.py @@ -173,3 +173,6 @@ WAGTAILADMIN_BASE_URL = "http://example.com" # STORE SETTINGS PRODUCTS_PER_PAGE = 6 + +# CART settings +CART_SESSION_ID = 'cart' diff --git a/artel/store/cart.py b/artel/store/cart.py new file mode 100644 index 0000000..9020277 --- /dev/null +++ b/artel/store/cart.py @@ -0,0 +1,78 @@ +from abc import ( + ABC, + abstractmethod +) +from typing import List +from dataclasses import dataclass +from django.http.request import HttpRequest +from django.conf import settings + +from store.models import Product + + +@dataclass +class CartItem: + product: Product + quantity: int + + +class BaseCart(ABC): + + def validate_item_id(self, item_id): + return Product.objects.get(id=item_id) + + @abstractmethod + def add_item(self, item_id, quantity): + ... + + @abstractmethod + def remove_item(self, item_id): + ... + + @abstractmethod + def update_item_quantity(self, item_id, change): + ... + + @abstractmethod + def get_items(self): + ... + + +class SessionCart(BaseCart): + + def __init__(self, request: HttpRequest) -> None: + super().__init__() + self.session = request.session + if not self.session.get(settings.CART_SESSION_ID): + self.session[settings.CART_SESSION_ID] = {} + + def add_item(self, item_id, quantity): + # TODO - add logging + self.validate_item_id(item_id) + + if not self.session[settings.CART_SESSION_ID].get(item_id): + self.session[settings.CART_SESSION_ID][item_id] = quantity + else: + self.update_item_quantity(item_id, quantity) + + def remove_item(self, item_id): + self.validate_item_id(item_id) + try: + self.session[settings.CART_SESSION_ID].pop(item_id) + except KeyError: + # TODO - add logging + ... + + def update_item_quantity(self, item_id, change): + self.validate_item_id(item_id) + try: + self.session[settings.CART_SESSION_ID][item_id] += change + except KeyError: + # TODO - add logging + self.add_item(item_id, change) + + def get_items(self) -> List[CartItem]: + _items = [] + for item_id, quantity in self.session[settings.CART_SESSION_ID].items(): + _items.append(CartItem(quantity=quantity, product=Product.objects.get(id=item_id))) + return _items \ No newline at end of file diff --git a/artel/store/static/js/cart.js b/artel/store/static/js/cart.js new file mode 100644 index 0000000..5d49051 --- /dev/null +++ b/artel/store/static/js/cart.js @@ -0,0 +1,34 @@ +// Add item to cart on form submission +$('#add-to-cart-form').on('submit', function(event) { + event.preventDefault(); + const form = $(this); + const formData = new FormData(form[0]); // Serialize the form data correctly + $.ajax({ + type: form.attr('method'), + url: form.attr('action'), + data: formData, // Use the serialized form data + dataType: 'json', + processData: false, // Prevent jQuery from processing the data + contentType: false, // Let the browser set the content type + success: function(data) { + alert(data.message); + fetchCartItems(); + } + }); +}); + +// Fetch cart items and update the display +function fetchCartItems() { + fetch('/cart/') + .then(response => response.json()) + .then(data => { + const cartItems = data.cart_items; + const cartItemsList = $('#cart-items'); + cartItemsList.empty(); + cartItems.forEach(item => { + const li = $('