responsive cart

shop
Raz 8 months ago
parent 34197e7c1a
commit 039a3448f6
  1. 1
      padelclub_backend/settings.py
  2. 14
      shop/cart.py
  3. 26
      shop/static/shop/css/shop.css
  4. 172
      shop/templates/shop/cart.html
  5. 18
      shop/templates/shop/product_item.html
  6. 2
      shop/templates/shop/product_list.html
  7. 2
      shop/views.py

@ -155,6 +155,7 @@ AUTHENTICATION_BACKENDS = [
]
CSRF_COOKIE_SECURE = True # if using HTTPS
SESSION_COOKIE_SECURE = True # Si vous utilisez HTTPS
# Stripe Settings
STRIPE_PUBLISHABLE_KEY = 'pk_test_51R4LrTPEZkECCx484C2KbmRpcO2ZkZb0NoNi8QJB4X3E5JFu3bvLk4JZQmz9grKbk6O40z3xI8DawHrGyUY0fOT600VEKC9ran' # Replace with your actual key

@ -16,15 +16,21 @@ def add_to_cart(request, product_id, quantity=1, color_id=None, size_id=None):
product = Product.objects.get(id=product_id)
cart_id = get_or_create_cart_id(request)
color = Color.objects.get(id=color_id) if color_id else None
size = Size.objects.get(id=size_id) if size_id else None
try:
# Try to get existing cart item
cart_item = CartItem.objects.get(product=product, session_id=cart_id)
# Try to get existing cart item with the same product, color, and size
cart_item = CartItem.objects.get(
product=product,
session_id=cart_id,
color=color,
size=size
)
cart_item.quantity += quantity
cart_item.save()
except CartItem.DoesNotExist:
# Create new cart item
color = Color.objects.get(id=color_id) if color_id else None
size = Size.objects.get(id=size_id) if size_id else None
cart_item = CartItem.objects.create(
product=product,
quantity=quantity,

@ -131,7 +131,6 @@
/* Cart Table */
.cart-table {
width: 100%;
border-collapse: collapse;
}
.cart-table th,
@ -329,3 +328,28 @@
.color-sample:hover {
transform: scale(1.1);
}
.color-display {
display: flex;
align-items: center;
gap: 8px;
}
.color-sample-cart {
width: 28px;
height: 28px;
border-radius: 50%;
border: 1px solid #ddd;
display: inline-block;
}
/* Fix for white + sign */
.quantity-btn {
color: #333; /* Darker text color to ensure visibility */
}
.quantity-btn:hover:not([disabled]) {
background-color: #f39200;
color: white;
border-color: #f39200;
}

@ -5,6 +5,123 @@
{% block second_title %}Plein de goodies !{% endblock %}
{% block content %}
<style>
.cart-table {
display: block;
width: 100%;
}
.cart-table thead {
display: none; /* Hide header on small screens */
}
.cart-table tbody, .cart-table tr, .cart-table tfoot {
display: block;
width: 100%;
}
.cart-table tbody tr {
/* margin-bottom: 15px;
padding: 10px;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1); */
}
.cart-table td {
display: flex;
/* padding: 8px 5px;
text-align: right;
justify-content: space-between;
align-items: center; */
}
.cart-table .price-column,
.cart-table .text-left {
/* text-align: right !important; */
}
.cart-table td.product-name {
grid-column: 1 / span 2;
grid-row: 1;
font-weight: bold;
font-size: 1.1em;
}
.cart-table td.product-color {
grid-column: 1 / span 2;
grid-row: 2;
}
/* .cart-table td.product-size {
grid-column: 2;
grid-row: 2;
} */
.cart-table td.product-quantity {
grid-column: 1;
grid-row: 3;
}
.cart-table td.product-price {
grid-column: 3;
grid-row: 3;
justify-content: right;
}
.cart-table td.product-actions {
grid-column: 3;
grid-row: 1;
justify-content: right;
}
/* Make each product a grid container */
.cart-table tbody tr {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
/* Cart summary buttons */
.cart-summary {
flex-direction: column;
gap: 10px;
}
.checkout-button {
width: 100%;
text-align: center;
height: 44px; /* Fixed height */
line-height: 24px; /* Vertically center text */
display: flex;
align-items: center;
justify-content: center;
}
.cart-table tfoot tr {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.cart-table tfoot td {
display: block;
width: 100%;
}
.cart-table tfoot td.total-quantity {
grid-column: 1;
grid-row: 1;
text-align: left;
}
.cart-table tfoot td.total-price {
grid-column: 3;
grid-row: 1;
text-align: right;
}
.cart-table tfoot td:empty {
display: none;
}
</style>
<nav class="margin10">
<a href="{% url 'shop:product_list' %}">La Boutique</a>
@ -18,12 +135,12 @@
{% endif %}
</nav>
<div class="grid-x">
<div class="cell medium-9 large-8 my-block">
<div class="small-12 medium-9 large-6 my-block">
<h1 class="club my-block topmargin20">Votre panier</h1>
<div class="bubble">
{% if cart_items %}
<table class="cart-table">
<thead>
<!-- <thead>
<tr>
<th class="text-left">Produit</th>
<th>Couleur</th>
@ -32,14 +149,18 @@
<th class="price-column">Prix</th>
<th></th>
</tr>
</thead>
</thead> -->
<tbody>
{% for item in cart_items %}
<tr class="{% cycle 'odd' 'even' %}">
<td class="text-left">{{ item.product.title }}</td>
<td>{{ item.color.name }}</td>
<td>{{ item.size.name }}</td>
<td>
<td class="text-left product-name" data-label="Produit">{{ item.product.title }}</td>
<td class="product-color" data-label="Couleur">
<div class="color-display">
<div class="color-sample-cart" style="background-color: {{ item.color.colorHex }}"></div>
{{ item.color.name }} | {{ item.size.name }}
</div>
</td>
<td class="product-quantity" data-label="Quantité">
<div class="quantity-controls">
<form method="post" action="{% url 'shop:update_cart_item' %}" class="quantity-form">
{% csrf_token %}
@ -50,8 +171,8 @@
</form>
</div>
</td>
<td class="price-column">{{ item.get_total_price }} €</td>
<td>
<td class="price-column product-price" data-label="Prix">{{ item.get_total_price }} €</td>
<td class="product-actions">
<form method="post" action="{% url 'shop:remove_from_cart' %}" class="remove-form">
{% csrf_token %}
<input type="hidden" name="item_id" value="{{ item.id }}">
@ -63,30 +184,33 @@
</tbody>
<tfoot>
<tr>
<td colspan="3" class="total-label text-left">Total:</td>
<td class="total-quantity">{{ total_quantity }}</td>
<td class="price-column total-price">{{ total }} €</td>
<td></td>
<td class="total-quantity" data-label="total-quantity">{{ total_quantity }} produit(s)</td>
<td class="total-label text-left"></td>
<td class="total-label text-left"></td>
<td class="price-column total-price" data-label="total-price">{{ total }} €</td>
<td class="total-label text-left"></td>
</tr>
</tfoot>
</table>
<div class="cart-summary">
{% if cart_items %}
<a class="cancel-nav-button checkout-button" href="{% url 'shop:clear_cart' %}">Vider le panier</a>
{% endif %}
{% if user.is_authenticated %}
<!-- For authenticated users: Direct Stripe payment button -->
<button id="checkout-button" class="confirm-nav-button checkout-button">Procéder au paiement</button>
<!-- For authenticated users: Direct Stripe payment button -->
<button id="checkout-button" class="confirm-nav-button checkout-button">Procéder au paiement</button>
{% else %}
<!-- For guest users: Regular checkout path -->
<a class="confirm-nav-button checkout-button" href="{% url 'shop:checkout' %}">Passer la commande</a>
<div class="guest-checkout-notice">
<p>Connectez-vous pour un paiement plus rapide.</p>
<a class="styled-link" href="{% url 'login' %}?next={% url 'shop:view_cart' %}">Se connecter</a>
</div>
<!-- For guest users: Regular checkout path -->
<a class="confirm-nav-button checkout-button" href="{% url 'shop:checkout' %}">Passer la commande</a>
<div class="guest-checkout-notice">
<p>Connectez-vous pour un paiement plus rapide.</p>
<a class="styled-link" href="{% url 'login' %}?next={% url 'shop:view_cart' %}">Se connecter</a>
</div>
{% endif %}
<hr>
{% if cart_items %}
<a class="cancel-nav-button checkout-button" href="{% url 'shop:clear_cart' %}" onclick="return confirm('Êtes-vous sûr de vouloir supprimer votre panier ?');">Vider le panier</a>
{% endif %}
</div>
{% else %}
<p>Votre panier est vide.</p>

@ -1,4 +1,4 @@
<div class="small-12 medium-4 large-3 my-block">
<div class="small-12 medium-6 large-3 my-block">
<div class="bubble">
{% if product.image %}
<img src="{{ product.image.url }}" alt="{{ product.title }}" class="product-image">
@ -32,12 +32,16 @@
<div class="option-element form-group">
{% if product.sizes.exists %}
<select name="size" id="size-{{ product.id }}" class="form-control" required>
<option value="" disabled selected>Taille</option>
{% for size in product.sizes.all %}
<option value="{{ size.id }}" {% if forloop.first %}selected{% endif %}>{{ size.name }}</option>
{% endfor %}
</select>
{% if product.sizes.all|length == 1 %}
<input type="hidden" name="size" value="{{ product.sizes.all.0.id }}">
{% else %}
<select name="size" id="size-{{ product.id }}" class="form-control" required>
<option value="" disabled selected>Taille</option>
{% for size in product.sizes.all %}
<option value="{{ size.id }}" {% if forloop.first %}selected{% endif %}>{{ size.name }}</option>
{% endfor %}
</select>
{% endif %}
{% endif %}
</div>
<div class="option-element form-group quantity-group">

@ -21,7 +21,7 @@
<nav class="margin10">
<a class="confirm-nav-button" href="{% url 'shop:view_cart' %}">Voir mon panier ({{ total }} €)</a>
{% if cart_items %}
<a class="cancel-nav-button" href="{% url 'shop:clear_cart' %}">Vider le panier</a>
<a class="cancel-nav-button" href="{% url 'shop:clear_cart' %}" onclick="return confirm('Êtes-vous sûr de vouloir supprimer votre panier ?');">Vider le panier</a>
{% endif %}
</nav>

@ -11,6 +11,7 @@ from django.conf import settings
from django.urls import reverse
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from django.views.decorators.csrf import ensure_csrf_cookie
from . import cart
@ -109,6 +110,7 @@ def view_cart(request):
return render(request, 'shop/cart.html', context)
@ensure_csrf_cookie
def add_to_cart_view(request, product_id):
"""Add a product to the cart"""
product = get_object_or_404(Product, id=product_id)

Loading…
Cancel
Save