Add dynamic subscription calculation
This commit is contained in:
parent
41ddfd8952
commit
27a0f94c4e
128
src/static/scripts/subscriptions.js
Normal file
128
src/static/scripts/subscriptions.js
Normal file
@ -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)
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -2,10 +2,7 @@
|
||||
{% load static %}
|
||||
|
||||
{% block head %}
|
||||
<script defer src="{% static 'scripts/product_list.js' %}"></script>
|
||||
<link rel="stylesheet" href="{% static 'styles/checkout.css' %}" />
|
||||
<script src="https://js.stripe.com/v3/"></script>
|
||||
<script src="{% static 'scripts/checkout.js' %}" defer></script>
|
||||
<script src="{% static 'scripts/subscriptions.js' %}" defer></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@ -15,7 +12,7 @@
|
||||
</div>
|
||||
<article>
|
||||
<section class="">
|
||||
<form action="" class="create-subscription-form">
|
||||
<form action="" class="subscription-create-form">
|
||||
{% csrf_token %}
|
||||
<div>
|
||||
<h4>Pick your coffee</h4>
|
||||
@ -33,9 +30,26 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="output">
|
||||
<h4>Pick your options</h4>
|
||||
{{ form.as_p }}
|
||||
<div class="cart__table-wrapper">
|
||||
<table class="cart__totals">
|
||||
<tr>
|
||||
<td>Retail total</td>
|
||||
<td><del class="retail-price"></del></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Save</td>
|
||||
<td>10%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Subscription total</th>
|
||||
<td><strong class="price"></strong></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<p class="shipping"></p>
|
||||
<p>
|
||||
<input type="submit" value="Continue to payment">
|
||||
</p>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user