project2463/templates/cart_new.html

731 lines
23 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends "base.html" %}
{% block title %}Моя корзина{% endblock %}
{% block content %}
<div class="container">
<!-- Хлебные крошки -->
<nav aria-label="breadcrumb" class="mb-3">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ url_for('catalog') }}">Каталог материалов</a></li>
<li class="breadcrumb-item active">Корзина</li>
</ol>
</nav>
<div class="d-flex justify-content-between align-items-center mb-4">
<h2 class="page-title">
<i class="fas fa-shopping-cart"></i> Моя корзина
</h2>
<a href="{{ url_for('catalog') }}" class="btn btn-outline">
<i class="fas fa-arrow-left"></i> Продолжить покупки
</a>
</div>
{% if cart_items %}
<!-- Информация о транспортных расходах -->
<div class="info-card mb-3">
<div class="info-card-header">
<i class="fas fa-truck"></i> Транспортные расходы
</div>
<div class="info-card-body">
<p><i class="fas fa-info-circle"></i> Транспортные расходы составляют 10% от стоимости материалов</p>
</div>
</div>
<!-- Таблица материалов в корзине -->
<div class="cart-table-container">
<table class="cart-table">
<thead>
<tr>
<th>Материал</th>
<th>Поставщик</th>
<th>Артикул</th>
<th>Категория</th>
<th>Цена</th>
<th style="text-align: center;">Количество</th>
<th>Сумма</th>
<th style="text-align: center;">Действия</th>
</tr>
</thead>
<tbody id="cartBody">
{% for item in cart_items %}
<tr id="item-{{ item.key }}" data-price="{{ item.price }}" data-max="{{ item.in_stock }}" data-key="{{ item.key }}" data-supplier-id="{{ item.supplier_id }}" data-supplier-name="{{ item.supplier_name }}">
<td data-label="Материал" class="product-name">{{ item.product_name }}</td>
<td data-label="Поставщик">{{ item.supplier_name }}</td>
<td data-label="Артикул">{{ item.article }}</td>
<td data-label="Категория">{{ item.category_name }}</td>
<td data-label="Цена" class="item-price">{{ item.price|int }} ₽</td>
<td data-label="Количество" style="text-align: center;">
<div class="quantity-control">
<input type="number" class="quantity-input"
value="{{ item.quantity }}" min="1" max="{{ item.in_stock }}"
data-item-key="{{ item.key }}"
id="quantity-{{ item.key }}"
placeholder="Кол-во">
</div>
</td>
<td data-label="Сумма" class="item-total amount-value">{{ (item.price * item.quantity)|int }} ₽</td>
<td data-label="Действия" style="text-align: center;">
<button class="btn-remove remove-item"
data-item-key="{{ item.key }}"
data-item-name="{{ item.product_name }}"
title="Удалить материал">
<i class="fas fa-trash"></i>
</button>
</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr class="cart-summary">
<td colspan="5" class="text-end"><strong>Базовая сумма:</strong></td>
<td colspan="2" class="total-amount" id="base-total">{{ total_amount|int }} ₽</td>
<td></td>
</tr>
<tr class="cart-summary">
<td colspan="5" class="text-end"><strong>Транспортные расходы (10%):</strong></td>
<td colspan="2" class="total-amount" id="transport-cost">{{ (total_amount * 0.1)|int }} ₽</td>
<td></td>
</tr>
<tr class="cart-total">
<td colspan="5" class="text-end"><strong>ИТОГО к оплате:</strong></td>
<td colspan="2" class="total-amount" id="cart-total">{{ (total_amount * 1.1)|int }} ₽</td>
<td></td>
</tr>
</tfoot>
</table>
</div>
<!-- Информация о заказе по поставщикам -->
{% if cart_items|groupby('supplier_id') %}
<div class="supplier-orders mt-4">
<h4 class="section-title">Заказы по поставщикам</h4>
<div id="supplier-orders-container">
{% for supplier_id, items in cart_items|groupby('supplier_id') %}
{% set supplier_total = 0 %}
{% for item in items %}
{% set supplier_total = supplier_total + (item.price * item.quantity) %}
{% endfor %}
{% set supplier_total_with_transport = supplier_total * 1.1 %}
<div class="supplier-order-card mb-3" id="supplier-{{ supplier_id }}">
<div class="supplier-order-header">
<span><i class="fas fa-truck"></i> Поставщик: {{ items[0].supplier_name }}</span>
<span class="supplier-order-total" id="supplier-total-{{ supplier_id }}">{{ supplier_total_with_transport|int }} ₽ (с транспортными расходами)</span>
</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
<!-- Кнопка оформления заказа -->
<div class="cart-actions">
<form method="POST" action="{{ url_for('checkout') }}" id="checkoutForm">
<button type="submit" class="btn btn-primary btn-lg"
onclick="return confirm('Оформить заказ? Все материалы будут перемещены в заказы.')">
<i class="fas fa-check"></i> Оформить заказ
</button>
</form>
</div>
{% else %}
<!-- Пустая корзина -->
<div class="empty-cart">
<div class="empty-icon">
<i class="fas fa-shopping-cart"></i>
</div>
<h4 class="empty-title">Корзина пуста</h4>
<p class="empty-text">Добавьте материалы в корзину, чтобы оформить заказ</p>
<a href="{{ url_for('catalog') }}" class="btn btn-primary btn-lg">
<i class="fas fa-arrow-left"></i> Перейти в каталог
</a>
</div>
{% endif %}
</div>
<style>
/* ===== ОСНОВНЫЕ ПЕРЕМЕННЫЕ ===== */
:root {
--antique-white: #FAEBD7;
--light-brown: #DEB887;
--brown: #A0522D;
--dark-brown: #8B4513;
}
/* ===== ХЛЕБНЫЕ КРОШКИ ===== */
.breadcrumb {
background: none;
padding: 0;
}
.breadcrumb-item a {
color: var(--brown);
text-decoration: none;
font-family: 'Verdana', sans-serif;
font-weight: 500;
}
.breadcrumb-item a:hover {
text-decoration: underline;
}
.breadcrumb-item.active {
color: #6c757d;
font-family: 'Verdana', sans-serif;
}
.breadcrumb-item + .breadcrumb-item::before {
color: var(--light-brown);
}
/* ===== ЗАГОЛОВОК ===== */
.page-title {
color: var(--brown);
font-size: 1.8rem;
font-weight: 600;
font-family: 'Verdana', sans-serif;
margin: 0;
display: flex;
align-items: center;
gap: 10px;
}
.page-title i {
color: var(--brown);
}
/* ===== КНОПКИ ===== */
.btn {
padding: 10px 20px;
border-radius: 8px;
font-size: 0.95rem;
font-weight: 500;
font-family: 'Verdana', sans-serif;
border: none;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 8px;
text-decoration: none;
}
.btn-primary {
background: var(--brown);
color: white;
}
.btn-primary:hover {
background: var(--dark-brown);
}
.btn-outline {
background: white;
border: 2px solid var(--brown);
color: var(--brown);
}
.btn-outline:hover {
background: var(--antique-white);
}
.btn-lg {
padding: 12px 30px;
font-size: 1.1rem;
}
/* ===== ИНФОРМАЦИОННАЯ КАРТОЧКА ===== */
.info-card {
background: white;
border: 1px solid var(--light-brown);
border-radius: 12px;
overflow: hidden;
}
.info-card-header {
background: linear-gradient(135deg, var(--brown) 0%, var(--dark-brown) 100%);
color: white;
padding: 12px 20px;
font-weight: 600;
font-family: 'Verdana', sans-serif;
}
.info-card-header i {
color: white;
margin-right: 8px;
}
.info-card-body {
padding: 15px 20px;
background: var(--antique-white);
}
.info-card-body p {
margin: 8px 0;
font-family: 'Verdana', sans-serif;
}
.info-card-body i {
color: var(--brown);
width: 20px;
}
/* ===== ТАБЛИЦА КОРЗИНЫ ===== */
.cart-table-container {
background: white;
border: 2px solid var(--brown);
border-radius: 12px;
overflow: hidden;
}
.cart-table {
width: 100%;
border-collapse: collapse;
}
.cart-table thead th {
background: var(--brown);
color: white;
font-weight: 600;
padding: 15px;
font-size: 1rem;
font-family: 'Verdana', sans-serif;
border-bottom: 2px solid var(--light-brown);
white-space: nowrap;
}
.cart-table tbody td {
padding: 15px;
font-family: 'Verdana', sans-serif;
color: #2c3e50;
border-bottom: 2px solid var(--light-brown);
vertical-align: middle;
background-color: white;
}
.cart-table tbody tr:last-child td {
border-bottom: none;
}
.cart-table tbody tr:hover td {
background-color: var(--antique-white);
}
.cart-table tfoot tr {
background: var(--antique-white);
border-top: 2px solid var(--brown);
}
.cart-table tfoot td {
padding: 12px 15px !important;
font-family: 'Verdana', sans-serif;
}
.cart-summary td {
color: #2c3e50;
}
.cart-total td {
background: var(--light-brown);
color: var(--dark-brown);
font-weight: 700;
}
.total-amount {
font-weight: 700;
color: var(--dark-brown);
font-size: 1.1rem;
}
.product-name {
font-weight: 600;
color: var(--brown);
}
.section-title {
color: var(--brown);
font-size: 1.2rem;
font-weight: 600;
margin-bottom: 15px;
padding-bottom: 8px;
border-bottom: 2px solid var(--light-brown);
font-family: 'Verdana', sans-serif;
}
/* ===== УПРАВЛЕНИЕ КОЛИЧЕСТВОМ ===== */
.quantity-control {
display: flex;
align-items: center;
justify-content: center;
}
.quantity-input {
width: 80px;
height: 40px;
border: 2px solid var(--light-brown);
border-radius: 8px;
text-align: center;
font-size: 1rem;
font-family: 'Verdana', sans-serif;
padding: 0 8px;
margin: 0;
background-color: white;
color: #2c3e50;
font-weight: 500;
}
/* Убираем стрелки в поле ввода */
.quantity-input::-webkit-inner-spin-button,
.quantity-input::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
.quantity-input {
-moz-appearance: textfield;
appearance: textfield;
}
.quantity-input:focus {
border-color: var(--brown);
outline: none;
}
/* ===== КНОПКА УДАЛЕНИЯ ===== */
.btn-remove {
background: white;
border: 2px solid #dc3545;
color: #dc3545;
width: 36px;
height: 36px;
border-radius: 8px;
cursor: pointer;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 1rem;
padding: 0;
}
.btn-remove:hover {
background: #dc3545;
color: white;
}
.btn-remove i {
color: inherit;
}
.amount-value {
font-weight: 700;
color: var(--brown);
font-size: 1.1rem;
}
/* ===== КАРТОЧКИ ЗАКАЗОВ ПО ПОСТАВЩИКАМ ===== */
.supplier-order-card {
border: 1px solid var(--light-brown);
border-radius: 10px;
overflow: hidden;
}
.supplier-order-header {
background: linear-gradient(135deg, var(--brown) 0%, var(--dark-brown) 100%);
color: white;
padding: 12px 20px;
display: flex;
justify-content: space-between;
align-items: center;
font-family: 'Verdana', sans-serif;
}
.supplier-order-header i {
color: white;
margin-right: 8px;
}
.supplier-order-total {
font-weight: 600;
}
/* ===== КНОПКА ОФОРМЛЕНИЯ ===== */
.cart-actions {
text-align: right;
margin-top: 25px;
padding-top: 20px;
border-top: 2px solid var(--light-brown);
}
/* ===== ПУСТАЯ КОРЗИНА ===== */
.empty-cart {
text-align: center;
padding: 60px 20px;
background: white;
border: 2px solid var(--brown);
border-radius: 12px;
}
.empty-icon {
font-size: 5rem;
color: var(--light-brown);
margin-bottom: 20px;
}
.empty-icon i {
color: var(--light-brown);
}
.empty-title {
color: var(--brown);
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 10px;
font-family: 'Verdana', sans-serif;
}
.empty-text {
color: #6c757d;
margin-bottom: 30px;
font-family: 'Verdana', sans-serif;
}
/* ===== АДАПТИВНОСТЬ ===== */
@media (max-width: 992px) {
.cart-table {
display: block;
}
.cart-table thead {
display: none;
}
.cart-table tbody tr {
display: block;
margin-bottom: 15px;
border: 2px solid var(--brown);
border-radius: 8px;
overflow: hidden;
}
.cart-table tbody td {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px;
border-bottom: 2px solid var(--light-brown);
background-color: white;
}
.cart-table tbody td:before {
content: attr(data-label);
font-weight: 600;
color: var(--brown);
margin-right: 10px;
min-width: 100px;
}
.cart-table tbody tr:last-child td:last-child {
border-bottom: none;
}
.cart-table tfoot {
display: block;
}
.cart-total td,
.cart-summary td {
display: block;
text-align: left !important;
padding: 10px !important;
}
.quantity-control {
justify-content: flex-end;
}
.quantity-input {
width: 70px;
}
.cart-actions {
text-align: center;
}
.btn-lg {
width: 100%;
justify-content: center;
}
.d-flex.justify-content-between {
flex-direction: column;
gap: 15px;
align-items: flex-start !important;
}
.btn-outline {
width: 100%;
justify-content: center;
}
.supplier-order-header {
flex-direction: column;
gap: 8px;
text-align: center;
}
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
const quantityInputs = document.querySelectorAll('.quantity-input');
const removeButtons = document.querySelectorAll('.remove-item');
const updateTimers = {};
function updateQuantity(itemKey, newQuantity) {
const row = document.getElementById(`item-${itemKey}`);
const price = parseFloat(row.dataset.price);
const maxStock = parseInt(row.dataset.max);
if (newQuantity > maxStock) {
alert(`Максимально доступное количество: ${maxStock} ед.`);
return false;
}
if (newQuantity < 1) newQuantity = 1;
const totalCell = row.querySelector('.item-total');
totalCell.textContent = (price * newQuantity).toFixed(0) + ' ₽';
updateCartTotal();
updateSupplierTotals();
return true;
}
function updateCartOnServer(itemKey, quantity) {
if (updateTimers[itemKey]) clearTimeout(updateTimers[itemKey]);
updateTimers[itemKey] = setTimeout(() => {
const form = document.createElement('form');
form.method = 'POST';
form.action = "{{ url_for('update_cart', item_key=0) }}".replace('0', itemKey);
form.style.display = 'none';
const input = document.createElement('input');
input.type = 'hidden';
input.name = 'quantity';
input.value = quantity;
form.appendChild(input);
document.body.appendChild(form);
form.submit();
}, 800);
}
function updateCartTotal() {
let totalBase = 0;
document.querySelectorAll('.item-total').forEach(cell => {
const value = parseFloat(cell.textContent) || 0;
totalBase += value;
});
const transport = totalBase * 0.1;
const totalWithTransport = totalBase + transport;
document.getElementById('base-total').textContent = totalBase.toFixed(0) + ' ₽';
document.getElementById('transport-cost').textContent = transport.toFixed(0) + ' ₽';
document.getElementById('cart-total').textContent = totalWithTransport.toFixed(0) + ' ₽';
}
function updateSupplierTotals() {
const supplierTotals = {};
document.querySelectorAll('#cartBody tr').forEach(row => {
const supplierId = row.dataset.supplierId;
const supplierName = row.dataset.supplierName;
const totalCell = row.querySelector('.item-total');
const value = parseFloat(totalCell.textContent) || 0;
if (!supplierTotals[supplierId]) {
supplierTotals[supplierId] = {
name: supplierName,
total: 0
};
}
supplierTotals[supplierId].total += value;
});
// Обновляем отображение для каждого поставщика
for (const [supplierId, data] of Object.entries(supplierTotals)) {
const supplierTotalElement = document.getElementById(`supplier-total-${supplierId}`);
if (supplierTotalElement) {
const totalWithTransport = data.total * 1.1;
supplierTotalElement.textContent = totalWithTransport.toFixed(0) + ' ₽ (с транспортными расходами)';
}
}
}
quantityInputs.forEach(input => {
// Запрещаем изменение стрелками на клавиатуре
input.addEventListener('keydown', function(e) {
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
e.preventDefault();
}
});
input.addEventListener('input', function() {
const itemKey = this.dataset.itemKey;
const row = document.getElementById(`item-${itemKey}`);
const maxStock = parseInt(row.dataset.max);
let newQuantity = parseInt(this.value);
if (isNaN(newQuantity)) return;
if (newQuantity > maxStock) {
this.value = maxStock;
newQuantity = maxStock;
alert(`Максимально доступное количество: ${maxStock} ед.`);
}
if (newQuantity < 1) {
this.value = 1;
newQuantity = 1;
}
if (updateQuantity(itemKey, newQuantity)) {
updateCartOnServer(itemKey, newQuantity);
}
});
input.addEventListener('blur', function() {
const itemKey = this.dataset.itemKey;
let value = parseInt(this.value);
if (isNaN(value) || value < 1) {
this.value = 1;
value = 1;
updateQuantity(itemKey, 1);
updateCartOnServer(itemKey, 1);
}
});
});
removeButtons.forEach(button => {
button.addEventListener('click', function(e) {
e.preventDefault();
const itemKey = this.dataset.itemKey;
const itemName = this.dataset.itemName;
if (confirm(`Удалить материал "${itemName}" из корзины?`)) {
const form = document.createElement('form');
form.method = 'POST';
form.action = "{{ url_for('remove_from_cart', item_key=0) }}".replace('0', itemKey);
form.style.display = 'none';
document.body.appendChild(form);
form.submit();
}
});
});
// Инициализация
updateCartTotal();
updateSupplierTotals();
});
</script>
{% endblock %}