parent
e3e6603d65
commit
cd71834fdf
@ -0,0 +1,41 @@ |
||||
# Generated by Django 5.1 on 2025-05-06 10:21 |
||||
|
||||
import django.db.models.deletion |
||||
from django.db import migrations, models |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('shop', '0026_alter_order_user'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.CreateModel( |
||||
name='ShippingAddress', |
||||
fields=[ |
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||
('street_address', models.CharField(max_length=255)), |
||||
('apartment', models.CharField(blank=True, max_length=50, null=True)), |
||||
('city', models.CharField(max_length=100)), |
||||
('state', models.CharField(blank=True, max_length=100, null=True)), |
||||
('postal_code', models.CharField(max_length=20)), |
||||
('country', models.CharField(max_length=100)), |
||||
], |
||||
), |
||||
migrations.AlterField( |
||||
model_name='order', |
||||
name='payment_status', |
||||
field=models.CharField(choices=[('UNPAID', 'Unpaid'), ('PAID', 'Paid'), ('FAILED', 'Failed'), ('REFUNDED', 'Refunded')], default='UNPAID', max_length=20), |
||||
), |
||||
migrations.AlterField( |
||||
model_name='order', |
||||
name='status', |
||||
field=models.CharField(choices=[('PENDING', 'Pending'), ('PAID', 'Paid'), ('SHIPPED', 'Shipped'), ('DELIVERED', 'Delivered'), ('CANCELED', 'Canceled'), ('REFUNDED', 'Refunded'), ('PREPARED', 'Prepared')], default='PENDING', max_length=20), |
||||
), |
||||
migrations.AddField( |
||||
model_name='order', |
||||
name='shipping_address', |
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='shop.shippingaddress'), |
||||
), |
||||
] |
||||
@ -0,0 +1,81 @@ |
||||
{% extends 'tournaments/base.html' %} |
||||
|
||||
{% block head_title %}Mes Commandes{% endblock %} |
||||
{% block first_title %}Padel Club{% endblock %} |
||||
{% block second_title %}Mes Commandes{% endblock %} |
||||
|
||||
{% block content %} |
||||
{% include 'shop/partials/navigation_base.html' %} |
||||
|
||||
<div class="grid-x"> |
||||
<div class="cell medium-12 large-6 padding10"> |
||||
<h1 class="club padding10">Mes Commandes</h1> |
||||
<div class="bubble"> |
||||
{% if orders %} |
||||
<table class="order-table"> |
||||
<tbody> |
||||
{% for order in orders %} |
||||
<tr class="{% cycle 'odd-row' 'even-row' %}"> |
||||
<td class="text-left">Commande #{{ order.id }}</td> |
||||
<td> |
||||
<a href="{% url 'shop:order_detail' order.id %}" class="view-btn">Détails</a> |
||||
</td> |
||||
<td class="text-left">{{ order.date_ordered|date:"d/m/Y H:i" }}</td> |
||||
<td class="text-left"> |
||||
{% if order.status == 'PENDING' %} |
||||
<span class="status-badge pending">En attente</span> |
||||
{% elif order.status == 'PAID' %} |
||||
<span class="status-badge paid">Payée</span> |
||||
{% elif order.status == 'PREPARED' %} |
||||
<span class="status-badge prepared">En cours de préparation</span> |
||||
{% elif order.status == 'SHIPPED' %} |
||||
<span class="status-badge shipped">Expédiée</span> |
||||
{% elif order.status == 'DELIVERED' %} |
||||
<span class="status-badge delivered">Livrée</span> |
||||
{% elif order.status == 'CANCELED' %} |
||||
<span class="status-badge canceled">Annulée</span> |
||||
{% elif order.status == 'REFUNDED' %} |
||||
<span class="status-badge refunded">Remboursée</span> |
||||
{% endif %} |
||||
</td> |
||||
<td class="price-column"> |
||||
{% if order.discount_amount > 0 %} |
||||
<span class="original-price">{{ order.total_price }}€</span> |
||||
<span class="discounted-price">{{ order.get_total_after_discount }}€</span> |
||||
{% else %} |
||||
{{ order.total_price }}€ |
||||
{% endif %} |
||||
</td> |
||||
<td class="actions"> |
||||
{% if order.status == 'PENDING' or order.status == 'PAID' %} |
||||
<form method="post" action="{% url 'shop:cancel_order' order.id %}" class="inline-form" onsubmit="return confirm('Êtes-vous sûr de vouloir annuler cette commande?');"> |
||||
{% csrf_token %} |
||||
<button type="submit" class="remove-btn">Annuler</button> |
||||
</form> |
||||
{% endif %} |
||||
</td> |
||||
</tr> |
||||
{% endfor %} |
||||
</tbody> |
||||
</table> |
||||
{% else %} |
||||
<div class="empty-orders"> |
||||
<p>Vous n'avez pas encore de commandes.</p> |
||||
<a href="{% url 'shop:product_list' %}" class="confirm-nav-button">Découvrir la boutique</a> |
||||
</div> |
||||
{% endif %} |
||||
</div> |
||||
|
||||
{% if messages %} |
||||
<div class="messages"> |
||||
{% for message in messages %} |
||||
<div class="alert {% if message.tags %}alert-{{ message.tags }}{% endif %}"> |
||||
{{ message }} |
||||
</div> |
||||
{% endfor %} |
||||
</div> |
||||
{% endif %} |
||||
</div> |
||||
</div> |
||||
|
||||
{% endblock %} |
||||
@ -0,0 +1,150 @@ |
||||
{% extends 'tournaments/base.html' %} |
||||
|
||||
{% block head_title %}Détail de commande{% endblock %} |
||||
{% block first_title %}Padel Club{% endblock %} |
||||
{% block second_title %}Détail de commande{% endblock %} |
||||
|
||||
{% block content %} |
||||
{% include 'shop/partials/navigation_base.html' %} |
||||
|
||||
<div class="grid-x"> |
||||
<div class="cell medium-8 large-8 padding10"> |
||||
<h1 class="club padding10">Commande #{{ order.id }}</h1> |
||||
<div class="bubble"> |
||||
<div class="order-meta"> |
||||
<div class="order-date"> |
||||
<strong>Date:</strong> {{ order.date_ordered|date:"d/m/Y H:i" }} |
||||
</div> |
||||
<div class="order-status"> |
||||
<strong>Statut:</strong> |
||||
{% if order.status == 'PENDING' %} |
||||
<span class="status-badge pending">En attente</span> |
||||
{% elif order.status == 'PREPARED' %} |
||||
<span class="status-badge prepared">En cours de préparation</span> |
||||
{% elif order.status == 'PAID' %} |
||||
<span class="status-badge paid">Payée</span> |
||||
{% elif order.status == 'SHIPPED' %} |
||||
<span class="status-badge shipped">Expédiée</span> |
||||
{% elif order.status == 'DELIVERED' %} |
||||
<span class="status-badge delivered">Livrée</span> |
||||
{% elif order.status == 'CANCELED' %} |
||||
<span class="status-badge canceled">Annulée</span> |
||||
{% elif order.status == 'REFUNDED' %} |
||||
<span class="status-badge refunded">Remboursée</span> |
||||
{% endif %} |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="order-items-section"> |
||||
<h3>Produits</h3> |
||||
{% with items=order_items total_quantity=total_quantity total_price=order.total_price %} |
||||
{% include 'shop/partials/order_items_display.html' with items=items total_quantity=total_quantity total_price=total_price edit_mode=False cancel_mode=order.is_cancellable %} |
||||
{% endwith %} |
||||
</div> |
||||
|
||||
<div class="coupon-section"> |
||||
<div>Adresse de livraison (dans la mesure du possible)</div> |
||||
{% if order.shipping_address %} |
||||
<div class="address-details" style="margin: 10px 0; padding: 10px; background: #f8f9fa; border-radius: 4px;"> |
||||
<p style="margin: 0;">{{ order.shipping_address.street_address }}</p> |
||||
{% if order.shipping_address.apartment %} |
||||
<p style="margin: 5px 0;">{{ order.shipping_address.apartment }}</p> |
||||
{% endif %} |
||||
<p style="margin: 0;">{{ order.shipping_address.postal_code }} {{ order.shipping_address.city }}, {{ order.shipping_address.country }}</p> |
||||
</div> |
||||
{% if order.shipping_address_can_be_edited %} |
||||
<button class="edit-address-btn confirm-nav-button" style="margin-top: 10px;" onclick="toggleAddressForm()">Modifier l'adresse</button> |
||||
|
||||
<div id="address-form-container" style="display: none; margin-top: 10px;"> |
||||
<form method="post" action="{% url 'shop:update_shipping_address' order.id %}" class="coupon-form"> |
||||
{% csrf_token %} |
||||
<input type="text" name="street_address" class="address-input" style="width: 100%;" placeholder="Adresse" value="{{ order.shipping_address.street_address }}"> |
||||
<div style="margin: 10px 0;"> |
||||
<input type="text" name="apartment" class="address-input" style="width: 100%;" placeholder="Appartement (optionnel)" value="{{ order.shipping_address.apartment|default:'' }}"> |
||||
</div> |
||||
<div style="display: flex; gap: 10px;"> |
||||
<input type="text" name="postal_code" class="address-input" style="width: 25%;" placeholder="Code postal" value="{{ order.shipping_address.postal_code }}"> |
||||
<input type="text" name="city" class="address-input" style="width: 25%;" placeholder="Ville" value="{{ order.shipping_address.city }}"> |
||||
<input type="text" name="country" class="address-input" style="width: 25%;" placeholder="Pays" value="{{ order.shipping_address.country }}"> |
||||
</div> |
||||
<button type="submit" class="save-btn confirm-nav-button">Enregistrer</button> |
||||
</form> |
||||
</div> |
||||
{% endif %} |
||||
{% else %} |
||||
<p>Aucune adresse de livraison renseignée</p> |
||||
{% if order.shipping_address_can_be_edited %} |
||||
<button class="add-address-btn confirm-nav-button" onclick="toggleAddressForm()">Ajouter une adresse</button> |
||||
<div id="address-form-container" style="display: none; margin-top: 10px;"> |
||||
<form method="post" action="{% url 'shop:update_shipping_address' order.id %}" class="coupon-form"> |
||||
{% csrf_token %} |
||||
<input type="text" name="street_address" class="address-input" style="width: 100%;" placeholder="Adresse"> |
||||
<div style="margin: 10px 0;"> |
||||
<input type="text" name="apartment" class="address-input" style="width: 100%;" placeholder="Appartement (optionnel)"> |
||||
</div> |
||||
<div style="display: flex; gap: 10px;"> |
||||
<input type="text" name="postal_code" class="address-input" style="width: 25%;" placeholder="Code postal"> |
||||
<input type="text" name="city" class="address-input" style="width: 25%;" placeholder="Ville"> |
||||
<input type="text" name="country" class="address-input" style="width: 25%;" placeholder="Pays"> |
||||
</div> |
||||
<button type="submit" class="save-btn confirm-nav-button">Enregistrer</button> |
||||
</form> |
||||
</div> |
||||
{% endif %} |
||||
{% endif %} |
||||
</div> |
||||
|
||||
{% if order.discount_amount > 0 %} |
||||
<div class="discount-section"> |
||||
<div class="discount-row"> |
||||
<span>Sous-total:</span> |
||||
<span class="price-value">{{ order.total_price }}€</span> |
||||
</div> |
||||
<div class="discount-row"> |
||||
<span>Réduction:</span> |
||||
<span class="price-value">-{{ order.discount_amount }}€</span> |
||||
</div> |
||||
<div class="discount-row total-row"> |
||||
<span>Total final:</span> |
||||
<span class="price-value">{{ order.get_total_after_discount }}€</span> |
||||
</div> |
||||
|
||||
{% if order.coupon %} |
||||
<div class="coupon-info"> |
||||
Coupon appliqué: {{ order.coupon.code }} |
||||
</div> |
||||
{% endif %} |
||||
</div> |
||||
{% endif %} |
||||
|
||||
<div class="order-actions"> |
||||
{% if order.status == 'PENDING' or order.status == 'PAID' %} |
||||
<form method="post" action="{% url 'shop:cancel_order' order.id %}" class="inline-form" onsubmit="return confirm('Êtes-vous sûr de vouloir annuler cette commande? Cette action est irréversible.');"> |
||||
{% csrf_token %} |
||||
<button type="submit" class="remove-btn">Annuler la commande</button> |
||||
</form> |
||||
{% endif %} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
{% if messages %} |
||||
<div class="messages"> |
||||
{% for message in messages %} |
||||
<div class="alert {% if message.tags %}alert-{{ message.tags }}{% endif %}"> |
||||
{{ message }} |
||||
</div> |
||||
{% endfor %} |
||||
</div> |
||||
{% endif %} |
||||
</div> |
||||
|
||||
<script> |
||||
function toggleAddressForm() { |
||||
const formContainer = document.getElementById('address-form-container'); |
||||
const isHidden = formContainer.style.display === 'none'; |
||||
formContainer.style.display = isHidden ? 'block' : 'none'; |
||||
} |
||||
</script> |
||||
|
||||
{% endblock %} |
||||
@ -0,0 +1,9 @@ |
||||
<nav class="margin10"> |
||||
<a href="{% url 'shop:product_list' %}">La Boutique</a> |
||||
<a href="{% url 'shop:my_orders' %}">Mes Commandes</a> |
||||
{% if user.is_authenticated %} |
||||
<a href="{% url 'profile' %}">Mon compte</a> |
||||
{% else %} |
||||
<a href="{% url 'login' %}">Se connecter</a> |
||||
{% endif %} |
||||
</nav> |
||||
@ -1,60 +1,68 @@ |
||||
<table class="cart-table"> |
||||
<tbody> |
||||
{% for item in items %} |
||||
<tr class="{% cycle 'odd-row' 'even-row' %}"> |
||||
<td class="text-left product-name" data-label="Produit">{{ item.product_title }}</td> |
||||
{% if item.product_description %} |
||||
<td class="text-left product-description" data-label="Description">{{ item.product_description }}</td> |
||||
{% endif %} |
||||
<td class="product-color" data-label="Couleur"> |
||||
<div class="color-display"> |
||||
<div class="color-sample-cart" |
||||
{% if item.secondary_color_hex %} |
||||
style="background-image: linear-gradient(to right, {{ item.color_hex }} 50%, {{ item.secondary_color_hex }} 50%);" |
||||
{% else %} |
||||
style="background-color: {{ item.color_hex }};" |
||||
{% endif %} |
||||
></div> |
||||
{{ item.color_name }} | {{ item.size_name }} |
||||
</div> |
||||
</td> |
||||
<td class="product-quantity" data-label="Quantité"> |
||||
{% if edit_mode %} |
||||
<div class="quantity-controls"> |
||||
<form method="post" action="{% url 'shop:update_cart_item' %}" class="quantity-form"> |
||||
{% csrf_token %} |
||||
<input type="hidden" name="item_id" value="{{ item.id }}"> |
||||
<button type="submit" name="action" value="decrease" class="quantity-btn" {% if item.quantity <= 1 %}disabled{% endif %}>-</button> |
||||
<span class="quantity-value">{{ item.quantity }}</span> |
||||
<button type="submit" name="action" value="increase" class="quantity-btn">+</button> |
||||
</form> |
||||
</div> |
||||
{% else %} |
||||
<span>x {{ item.quantity }}</span> |
||||
{% endif %} |
||||
</td> |
||||
<td class="price-column product-price" data-label="Prix">{{ item.total_price }} €</td> |
||||
{% if edit_mode %} |
||||
<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 }}"> |
||||
<button type="submit" class="remove-btn">retirer</button> |
||||
</form> |
||||
</td> |
||||
{% endif %} |
||||
</tr> |
||||
{% endfor %} |
||||
</tbody> |
||||
<tfoot> |
||||
<tr> |
||||
<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_price }} €</td> |
||||
{% if edit_mode %} |
||||
<td class="total-label text-left"></td> |
||||
{% endif %} |
||||
</tr> |
||||
</tfoot> |
||||
<tbody> |
||||
{% for item in items %} |
||||
<tr class="{% cycle 'odd-row' 'even-row' %}"> |
||||
<td class="text-left product-name" data-label="Produit">{{ item.product_title }}</td> |
||||
{% if item.product_description %} |
||||
<td class="text-left product-description" data-label="Description">{{ item.product_description }}</td> |
||||
{% endif %} |
||||
<td class="product-color" data-label="Couleur"> |
||||
<div class="color-display"> |
||||
<div class="color-sample-cart" |
||||
{% if item.secondary_color_hex %} |
||||
style="background-image: linear-gradient(to right, {{ item.color_hex }} 50%, {{ item.secondary_color_hex }} 50%);" |
||||
{% else %} |
||||
style="background-color: {{ item.color_hex }};" |
||||
{% endif %} |
||||
></div> |
||||
{{ item.color_name }} | {{ item.size_name }} |
||||
</div> |
||||
</td> |
||||
<td class="product-quantity" data-label="Quantité"> |
||||
{% if edit_mode %} |
||||
<div class="quantity-controls"> |
||||
<form method="post" action="{% url 'shop:update_cart_item' %}" class="quantity-form"> |
||||
{% csrf_token %} |
||||
<input type="hidden" name="item_id" value="{{ item.id }}"> |
||||
<button type="submit" name="action" value="decrease" class="quantity-btn" {% if item.quantity <= 1 %}disabled{% endif %}>-</button> |
||||
<span class="quantity-value">{{ item.quantity }}</span> |
||||
<button type="submit" name="action" value="increase" class="quantity-btn">+</button> |
||||
</form> |
||||
</div> |
||||
{% else %} |
||||
<span>x {{ item.quantity }}</span> |
||||
{% endif %} |
||||
</td> |
||||
<td class="price-column product-price" data-label="Prix">{{ item.total_price }} €</td> |
||||
{% if edit_mode %} |
||||
<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 }}"> |
||||
<button type="submit" class="remove-btn">retirer</button> |
||||
</form> |
||||
</td> |
||||
{% elif cancel_mode and items.count > 1 %} |
||||
<td class="product-actions"> |
||||
<form method="post" action="{% url 'shop:cancel_order_item' order.id item.id %}" class="remove-form" |
||||
onsubmit="return confirm('Êtes-vous sûr de vouloir annuler cet article ? {% if order.status == 'PAID' %}Un remboursement sera effectué.{% endif %}');"> |
||||
{% csrf_token %} |
||||
<button type="submit" class="remove-btn">annuler</button> |
||||
</form> |
||||
</td> |
||||
{% endif %} |
||||
</tr> |
||||
{% endfor %} |
||||
</tbody> |
||||
<tfoot> |
||||
<tr> |
||||
<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_price }} €</td> |
||||
{% if edit_mode or cancel_mode %} |
||||
<td class="total-label text-left"></td> |
||||
{% endif %} |
||||
</tr> |
||||
</tfoot> |
||||
</table> |
||||
|
||||
@ -0,0 +1,18 @@ |
||||
# Generated by Django 5.1 on 2025-05-06 07:56 |
||||
|
||||
from django.db import migrations, models |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('tournaments', '0118_tournament_animation_type'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AlterField( |
||||
model_name='tournament', |
||||
name='animation_type', |
||||
field=models.IntegerField(choices=[(0, 'Tournoi'), (1, 'Mêlée'), (2, 'Classement'), (3, 'Consolation')], default=0), |
||||
), |
||||
] |
||||
Loading…
Reference in new issue