Add custom filter and remove individual grinds functionality

This commit is contained in:
Nathan Chapman 2022-05-08 14:46:55 -06:00
parent 0f7a36a569
commit 2521beea74
16 changed files with 65 additions and 30 deletions

View File

@ -19,7 +19,7 @@ ORDER_REFUND_TEMPLATE = 'storefront/order_refund'
def send_order_confirmation_email(order):
send_templated_mail(
template_name=CONFIRM_ORDER_TEMPLATE,
from_email=settings.DEFAULT_FROM_EMAIL,
from_email=settings.ORDER_FROM_EMAIL,
recipient_list=[order['email']],
context=order
)
@ -30,7 +30,7 @@ def send_order_confirmation_email(order):
def send_order_shipped_email(data):
send_templated_mail(
template_name=SHIP_ORDER_TEMPLATE,
from_email=settings.DEFAULT_FROM_EMAIL,
from_email=settings.ORDER_FROM_EMAIL,
recipient_list=[data['email']],
context=data
)

View File

@ -32,6 +32,7 @@ ANYMAIL_CONFIG = {
SERVER_EMAIL = os.environ.get('SERVER_EMAIL', '')
DEFAULT_FROM_EMAIL = os.environ.get('DEFAULT_FROM_EMAIL', '')
DEFAULT_CONTACT_EMAIL = os.environ.get('DEFAULT_CONTACT_EMAIL', '')
ORDER_FROM_EMAIL = os.environ.get('ORDER_FROM_EMAIL', '')
STATIC_ROOT_PATH = os.environ.get('STATIC_ROOT_PATH', '/var/www/ptcoffee-dev/static/')
SECURE_HSTS_SECONDS = os.environ.get('SECURE_HSTS_SECONDS', 3600)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 MiB

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

@ -218,13 +218,26 @@ input[type=submit]:hover,
/* Contact form
========================================================================== */
.contact-form {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0 2rem;
}
.contact-form p:nth-child(6) {
grid-column: span 2;
}
.contact-form p:last-child {
grid-column: 2;
}
.contact-form label {
display: block;
}
:is(.contact-form) input, select, textarea {
width: 100%;
max-width: 600px;
}
@ -476,12 +489,15 @@ section:not(:last-child) {
background-image: url("/static/images/site_banner.jpg");
}
.site__banner--fairtrade {
padding: 6rem 1rem;
background-image: url("/static/images/fairtrade_banner.jpg");
}
.site__banner--reviews {
padding: 6rem 1rem;
background-image: url("/static/images/reviews_banner.jpg");
}
.site__banner--about {
padding: 6rem 1rem;
background-image: url("/static/images/coffee_banner.jpg");
}
@ -791,6 +807,15 @@ article + article {
grid-column: 2;
grid-row: 1;
}
.item__form {
flex-direction: column;
}
.item__form *:not(:last-child) {
margin-bottom: 1rem;
width: 100%;
}
}

View File

@ -62,10 +62,12 @@ class Cart:
self.session.modified = True
logger.info(f'\nCart:\n{self.cart}\n')
def remove(self, product):
def remove(self, product, grind):
product_id = str(product.id)
if product_id in self.cart:
del self.cart[product_id]
del self.cart[product_id]['variations'][grind]
if not self.cart[product_id]['variations']:
del self.cart[product_id]
self.save()
def __iter__(self):

View File

@ -133,8 +133,7 @@ class ContactForm(forms.Form):
(OTHER, 'Other (please describe below)'),
]
first_name = forms.CharField()
last_name = forms.CharField()
full_name = forms.CharField()
email_address = forms.EmailField()
referal = forms.ChoiceField(
label='How did you find our website?',

View File

@ -1,4 +1,5 @@
{% extends "base.html" %}
{% load grind_filter %}
{% block head_title %}Cart | {% endblock %}
@ -15,20 +16,18 @@
<img class="item__image" src="{{product.get_first_img.image.url}}" alt="{{product.get_first_img.image}}">
</figure>
<div class="item__info">
<h4>{{product.name}}</h4>
<p><strong>Grind</strong>:</p>
{% for key, value in item.variations.items %}
<p><strong>{{key}}</strong><br>
<form class="item__form" action="{% url 'storefront:cart-update' product.pk key %}" method="POST">
{% csrf_token %}
{{ value.update_quantity_form }}
<input type="submit" value="Update">
</form>
</p>
{% endfor %}
<p>
<a href="{% url 'storefront:cart-remove' product.pk %}">Remove from cart</a>
<h3>{{product.name}}</h3>
<h5>Grind:</h5>
{% for key, value in item.variations.items %}
<p><strong>{{ key|get_grind_display }}</strong><br>
<form class="item__form" action="{% url 'storefront:cart-update' product.pk key %}" method="POST">
{% csrf_token %}
{{ value.update_quantity_form }}
<input type="submit" value="Update">
<a href="{% url 'storefront:cart-remove' product.pk key %}">Remove item</a>
</form>
</p>
{% endfor %}
</div>
<div class="item__price">
<p><strong>${{item.price}}</strong></p>

View File

@ -13,9 +13,9 @@
Please contact us, were happy to help you over the phone<br>
<a href="tel:+13603855856">(360) 385-5856</a> Mon-Fri between 9:00 am and 5:00 pm Pacific Time.
</p>
<p>Or send us a message using the form below and we'll email you back as soon as we can.</p>
</header>
<section>
<p>Or send us a message using the form below and we'll email you back as soon as we can.</p>
<form action="{% url 'storefront:contact' %}" method="post" class="contact-form">
{% csrf_token %}
{{form.as_p}}

View File

@ -1,5 +1,6 @@
{% extends "base.html" %}
{% load static %}
{% load grind_filter %}
{% block head_title %}Checkout | {% endblock %}
@ -38,7 +39,7 @@
<div>
<h4>{{product.name}}</h4>
{% for key, value in item.variations.items %}
<p>Grind: <strong>{{key}}</strong>, Qty: <strong>{{value.quantity}}</strong></p>
<p>Grind: <strong>{{ key|get_grind_display }}</strong>, Qty: <strong>{{value.quantity}}</strong></p>
{% endfor %}
</div>
<div class="item__price">

View File

View File

@ -0,0 +1,8 @@
from django import template
from core import CoffeeGrind
def get_grind_display(value):
return next((v[1] for i, v in enumerate(CoffeeGrind.GRIND_CHOICES) if v[0] == value), None)
register = template.Library()
register.filter('get_grind_display', get_grind_display)

View File

@ -154,7 +154,7 @@ class CartTest(TestCase):
update_quantity=False
)
self.assertEqual(len(cart), 3)
cart.remove(self.product)
cart.remove(self.product, CoffeeGrind.WHOLE)
self.assertEqual(len(cart), 0)
def test_cart_get_total_weight(self):

View File

@ -15,7 +15,7 @@ urlpatterns = [
path('cart/', views.CartView.as_view(), name='cart-detail'),
path('cart/<int:pk>/add/', views.CartAddProductView.as_view(), name='cart-add'),
path('cart/<int:pk>/update/<slug:grind>/', views.CartUpdateProductView.as_view(), name='cart-update'),
path('cart/<int:pk>/remove/', views.cart_remove_product_view, name='cart-remove'),
path('cart/<int:pk>/remove/<slug:grind>/', views.cart_remove_product_view, name='cart-remove'),
path('coupon/apply/', views.CouponApplyView.as_view(), name='coupon-apply'),

View File

@ -104,10 +104,10 @@ class CartUpdateProductView(SingleObjectMixin, FormView):
return super().form_valid(form)
def cart_remove_product_view(request, pk):
def cart_remove_product_view(request, pk, grind):
cart = Cart(request)
product = get_object_or_404(Product, id=pk)
cart.remove(product)
cart.remove(product, grind)
return redirect('storefront:cart-detail')

View File

@ -2,7 +2,7 @@
{% block plain %}
Referred from: {{referal}}
From: {{first_name}} {{last_name}} {{email_address}}
From: {{full_name}} {{email_address}}
Message: {{message}}
{% endblock %}
@ -10,7 +10,7 @@
{% block html %}
<p><strong>Referred from</strong>:<br>{{referal}}</p>
<p><strong>From</strong>:<br>{{first_name}} {{last_name}} {{email_address|urlize}}</p>
<p><strong>From</strong>:<br>{{full_name}} {{email_address|urlize}}</p>
<p><strong>Message</strong>:<br>{{message|linebreaks}}</p>
{% endblock %}

View File

@ -4,7 +4,7 @@
Hi {{full_name}}, we're getting your order ready to be shipped. We will notify you when it has been sent.
If you have any questions, reply to this email or contact us at support@ptcoffee.com
If you have any questions, send us an email at support@ptcoffee.com.
Thanks,
Port Townsend Roasting Co.
@ -15,7 +15,7 @@
<p>Hi {{full_name}}, we're getting your order ready to be shipped. We will notify you when it has been sent.</p>
<p>If you have any questions, reply to this email or contact us at <a href="mailto:support@ptcoffee.com">support@ptcoffee.com</a></p>
<p>If you have any questions, send us an email at <a href="mailto:support@ptcoffee.com">support@ptcoffee.com</a>.</p>
<p>Thanks,<br>
Port Townsend Roasting Co.</p>