From 27a0f94c4eae2844d7e0745122a396e12ad5621b Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Mon, 1 Aug 2022 18:53:44 -0600 Subject: [PATCH] Add dynamic subscription calculation --- src/static/scripts/subscriptions.js | 128 ++++++++++++++++++ src/static/styles/main.css | 6 +- src/storefront/forms.py | 10 +- .../templates/storefront/subscriptions.html | 26 +++- 4 files changed, 156 insertions(+), 14 deletions(-) create mode 100644 src/static/scripts/subscriptions.js diff --git a/src/static/scripts/subscriptions.js b/src/static/scripts/subscriptions.js new file mode 100644 index 0000000..61e94f4 --- /dev/null +++ b/src/static/scripts/subscriptions.js @@ -0,0 +1,128 @@ +class Subscription { + static TWELVE_OZ + static SIXTEEN_OZ + static FIVE_LBS + + static TWELVE_SHIPPING + static SIXTEEN_SHIPPING + static FIVE_SHIPPING + + constructor(element, output) { + this.TWELVE_OZ = '12' + this.SIXTEEN_OZ = '16' + this.FIVE_LBS = '75' + this.TWELVE_SHIPPING = 7 + this.SIXTEEN_SHIPPING = 5 + this.FIVE_SHIPPING = 1 + + this.element = element + this.output = this.element.querySelector('.output') + this.shippingDiscount = 10 + this.price = this.element.querySelector('select[name=size]') + this.products = this.element.querySelectorAll('input[name^=product]') + this.element.addEventListener('change', this.render.bind(this)) + this.render() + } + + get total_qty() { + return Array.from(this.products).reduce((total, current) => { + return total + Number(current.value) + }, 0) + } + + get hasFreeShipping() { + switch(this.price.value) { + case this.TWELVE_OZ: + if (parseInt(this.total_qty) >= this.TWELVE_SHIPPING) { + return true + } else { + return false + } + break + case this.SIXTEEN_OZ: + if (parseInt(this.total_qty) >= this.SIXTEEN_SHIPPING) { + return true + } else { + return false + } + break + case this.FIVE_LBS: + if (parseInt(this.total_qty) >= this.FIVE_SHIPPING) { + return true + } else { + return false + } + break + default: + throw 'Something is wrong with the price' + } + } + + get countToFreeShipping() { + switch(this.price.value) { + case this.TWELVE_OZ: + return this.TWELVE_SHIPPING - this.total_qty + break + case this.SIXTEEN_OZ: + return this.SIXTEEN_SHIPPING - this.total_qty + break + case this.FIVE_LBS: + return this.FIVE_SHIPPING + break + default: + throw 'Something is wrong with the price' + break + } + } + + get shippingStatus() { + let items = 0 + + if (this.hasFreeShipping) { + return 'You have free shipping!' + } else { + return `Add ${this.countToFreeShipping} more item(s) for free shipping!` + } + + } + + get totalRetailPrice() { + let totalPrice = Array.from(this.products).reduce((total, current) => { + return total + (Number(this.price.value) * current.value); + }, 0); + + return new Intl.NumberFormat('en-US', { + currency: 'USD', + style: 'currency', + }).format(totalPrice) + } + + get totalPrice() { + let totalPrice = Array.from(this.products).reduce((total, current) => { + return total + (Number(this.price.value) * current.value); + }, 0); + + let percentage = (this.shippingDiscount / 100) * totalPrice + + + return new Intl.NumberFormat('en-US', { + currency: 'USD', + style: 'currency', + }).format(totalPrice - percentage) + } + + render() { + this.output.querySelector('.retail-price').innerText = this.totalRetailPrice + this.output.querySelector('.price').innerText = this.totalPrice + this.output.querySelector('.shipping').innerText = this.shippingStatus + } + + add_item(item) { + this.items.push(item) + return this.items + } +} + + +const subCreateFromEl = document.querySelector('.subscription-create-form') +const sub = new Subscription(subCreateFromEl) diff --git a/src/static/styles/main.css b/src/static/styles/main.css index e526e2d..7b4d259 100644 --- a/src/static/styles/main.css +++ b/src/static/styles/main.css @@ -639,7 +639,7 @@ article + article { } -.create-subscription-form { +.subscription-create-form { display: grid; grid-template-columns: 2fr 1fr; gap: 2rem; @@ -649,11 +649,11 @@ article + article { display: grid; grid-template-columns: repeat(2, 1fr); justify-items: center; - gap: 8rem; + gap: 6rem; overflow-y: scroll; max-height: 50rem; border-bottom: var(--default-border); - padding: 0 4rem 4rem; + padding: 0 2rem 2rem; } .product__subscription-list div { diff --git a/src/storefront/forms.py b/src/storefront/forms.py index 55c4cba..75deefa 100644 --- a/src/storefront/forms.py +++ b/src/storefront/forms.py @@ -178,13 +178,13 @@ class SubscriptionCreateForm(forms.Form): TWELVE_OZ = 12 SIXTEEN_OZ = 16 - FIVE_LBS = 5 + FIVE_LBS = 75 SIZE_CHOICES = [ - (TWELVE_OZ, '12oz'), - (SIXTEEN_OZ, '16oz'), - (FIVE_LBS, '5lbs'), + (TWELVE_OZ, '12 oz ($10.80)'), + (SIXTEEN_OZ, '16 oz ($14.40)'), + (FIVE_LBS, '5 lbs ($67.50)'), ] - size = forms.ChoiceField(choices=SIZE_CHOICES) grind = forms.ChoiceField(choices=CoffeeGrind.GRIND_CHOICES) schedule = forms.ChoiceField(choices=SCHEDULE_CHOICES) + size = forms.ChoiceField(choices=SIZE_CHOICES) diff --git a/src/storefront/templates/storefront/subscriptions.html b/src/storefront/templates/storefront/subscriptions.html index 6d497e3..a1d034e 100644 --- a/src/storefront/templates/storefront/subscriptions.html +++ b/src/storefront/templates/storefront/subscriptions.html @@ -2,10 +2,7 @@ {% load static %} {% block head %} - - - - + {% endblock %} {% block content %} @@ -15,7 +12,7 @@
-
+ {% csrf_token %}

Pick your coffee

@@ -33,9 +30,26 @@ {% endfor %}
-
+

Pick your options

{{ form.as_p }} +
+ + + + + + + + + + + + + +
Retail total
Save10%
Subscription total
+
+