Remove promo, add featured on main page
All checks were successful
Build and Push Docker Image / build (push) Successful in 54s
All checks were successful
Build and Push Docker Image / build (push) Successful in 54s
This commit is contained in:
@@ -3,6 +3,8 @@ from django.core import mail
|
|||||||
from django.test import SimpleTestCase, TestCase, override_settings
|
from django.test import SimpleTestCase, TestCase, override_settings
|
||||||
from django.urls import reverse, resolve
|
from django.urls import reverse, resolve
|
||||||
|
|
||||||
|
from items.models import Category, Item
|
||||||
|
|
||||||
|
|
||||||
@override_settings(EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend", ADMINISTRATOR_EMAIL="admin@example.com")
|
@override_settings(EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend", ADMINISTRATOR_EMAIL="admin@example.com")
|
||||||
class FaqQuestionTests(TestCase):
|
class FaqQuestionTests(TestCase):
|
||||||
@@ -39,6 +41,50 @@ class FaqQuestionTests(TestCase):
|
|||||||
self.assertContains(response, "Необходимо согласие на обработку персональных данных.")
|
self.assertContains(response, "Необходимо согласие на обработку персональных данных.")
|
||||||
|
|
||||||
|
|
||||||
|
class HomePopularProductsTests(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.category = Category.objects.create(name="Plumbing", slug="plumbing")
|
||||||
|
|
||||||
|
def test_home_page_renders_available_products(self):
|
||||||
|
visible_item = Item.objects.create(
|
||||||
|
name="Visible sink",
|
||||||
|
slug="visible-sink",
|
||||||
|
category=self.category,
|
||||||
|
price="1600.00",
|
||||||
|
is_available=True,
|
||||||
|
)
|
||||||
|
Item.objects.create(
|
||||||
|
name="Hidden sink",
|
||||||
|
slug="hidden-sink",
|
||||||
|
category=self.category,
|
||||||
|
price="1800.00",
|
||||||
|
is_available=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self.client.get(reverse("home"))
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertContains(response, visible_item.name)
|
||||||
|
self.assertContains(response, reverse("detail", args=[self.category.slug, visible_item.slug]))
|
||||||
|
self.assertContains(response, "1600,00 руб.")
|
||||||
|
self.assertNotContains(response, "Hidden sink")
|
||||||
|
|
||||||
|
def test_home_page_limits_popular_products_to_six(self):
|
||||||
|
for index in range(7):
|
||||||
|
Item.objects.create(
|
||||||
|
name=f"Product {index}",
|
||||||
|
slug=f"product-{index}",
|
||||||
|
category=self.category,
|
||||||
|
price="1000.00",
|
||||||
|
is_available=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self.client.get(reverse("home"))
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(len(response.context["home_products"]), 6)
|
||||||
|
|
||||||
|
|
||||||
class FaviconTests(SimpleTestCase):
|
class FaviconTests(SimpleTestCase):
|
||||||
def test_favicon_route_returns_icon(self):
|
def test_favicon_route_returns_icon(self):
|
||||||
response = self.client.get(reverse("favicon"))
|
response = self.client.get(reverse("favicon"))
|
||||||
|
|||||||
@@ -2,11 +2,15 @@ import logging
|
|||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
|
from django.db.models import BooleanField, Case, Value, When
|
||||||
from django.shortcuts import redirect, render
|
from django.shortcuts import redirect, render
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
|
||||||
|
from favorites.services import get_user_favorite_item_ids
|
||||||
from home.forms import FaqQuestionForm
|
from home.forms import FaqQuestionForm
|
||||||
|
from items.models import Item
|
||||||
|
from orders.services import get_user_cart_item_ids
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -55,7 +59,26 @@ def index(request):
|
|||||||
messages.success(request, "Спасибо. Ваш вопрос отправлен, мы свяжемся с вами в ближайшее время.")
|
messages.success(request, "Спасибо. Ваш вопрос отправлен, мы свяжемся с вами в ближайшее время.")
|
||||||
return redirect(f"{reverse('home')}#faq-section")
|
return redirect(f"{reverse('home')}#faq-section")
|
||||||
|
|
||||||
return render(request=request, template_name='home/index.html', context={"faq_form": form})
|
home_products = (
|
||||||
|
Item.objects.filter(is_available=True)
|
||||||
|
.select_related("category", "subcategory")
|
||||||
|
.prefetch_related("images")
|
||||||
|
.annotate(
|
||||||
|
discount_sort=Case(
|
||||||
|
When(discount_price__isnull=False, then=Value(True)),
|
||||||
|
default=Value(False),
|
||||||
|
output_field=BooleanField(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.order_by("-is_new", "-discount_sort", "-created_at")[:6]
|
||||||
|
)
|
||||||
|
|
||||||
|
return render(request=request, template_name='home/index.html', context={
|
||||||
|
"faq_form": form,
|
||||||
|
"home_products": home_products,
|
||||||
|
"favorite_item_ids": get_user_favorite_item_ids(request.user),
|
||||||
|
"cart_item_ids": get_user_cart_item_ids(request.user),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def services(request):
|
def services(request):
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ class CartFlowTests(TestCase):
|
|||||||
self.assertContains(response, "3200,00 руб.")
|
self.assertContains(response, "3200,00 руб.")
|
||||||
self.assertContains(response, "3745,00 руб.")
|
self.assertContains(response, "3745,00 руб.")
|
||||||
self.assertContains(response, "/media/items/cart-item.jpg")
|
self.assertContains(response, "/media/items/cart-item.jpg")
|
||||||
|
self.assertNotContains(response, 'name="promo_code"', html=False)
|
||||||
|
|
||||||
def test_cart_page_redirects_guest_to_login(self):
|
def test_cart_page_redirects_guest_to_login(self):
|
||||||
response = self.client.get(reverse("orders:cart"))
|
response = self.client.get(reverse("orders:cart"))
|
||||||
|
|||||||
@@ -281,20 +281,6 @@
|
|||||||
color: var(--mid);
|
color: var(--mid);
|
||||||
}
|
}
|
||||||
|
|
||||||
.promo-row {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: minmax(0, 1fr) 178px;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.promo-row button {
|
|
||||||
border: 0;
|
|
||||||
background: var(--blue-gray);
|
|
||||||
color: var(--white);
|
|
||||||
font: inherit;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkout-summary {
|
.checkout-summary {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
@@ -440,15 +426,10 @@
|
|||||||
.checkout-options--three,
|
.checkout-options--three,
|
||||||
.checkout-grid,
|
.checkout-grid,
|
||||||
.checkout-grid--contacts,
|
.checkout-grid--contacts,
|
||||||
.promo-row,
|
|
||||||
.order-success__summary {
|
.order-success__summary {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.promo-row button {
|
|
||||||
height: 38px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkout-submit,
|
.checkout-submit,
|
||||||
.order-success__link,
|
.order-success__link,
|
||||||
.cart-empty a {
|
.cart-empty a {
|
||||||
|
|||||||
@@ -500,14 +500,172 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.product {
|
.product {
|
||||||
padding: 20px;
|
position: relative;
|
||||||
background: #d9d9d9;
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: #ffffff;
|
||||||
|
border: 1px solid rgba(54, 33, 62, 0.12);
|
||||||
|
transition: border-color 0.2s, box-shadow 0.2s, transform 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.product-actions .bi-heart {
|
.product:hover {
|
||||||
|
border-color: rgba(54, 33, 62, 0.28);
|
||||||
|
box-shadow: 0 18px 36px rgba(54, 33, 62, 0.1);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-media {
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
background: rgba(99, 118, 141, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-media img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-placeholder {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 130px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #63768d;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-actions {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
top: 18px;
|
||||||
|
left: 18px;
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-actions form {
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-actions button,
|
||||||
|
.product-actions a {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 2px;
|
border: 1px solid rgba(54, 33, 62, 0.18);
|
||||||
transform: translateY(2px);
|
background: rgba(255, 255, 255, 0.88);
|
||||||
|
color: #36213e;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s, border-color 0.2s, color 0.2s, transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-actions button:hover,
|
||||||
|
.product-actions a:hover,
|
||||||
|
.product-actions .is-active {
|
||||||
|
border-color: #63768d;
|
||||||
|
background: #63768d;
|
||||||
|
color: #ffffff;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-actions svg {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-info {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
padding: 18px;
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-category {
|
||||||
|
display: block;
|
||||||
|
color: #63768d;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.2;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-name {
|
||||||
|
min-height: 52px;
|
||||||
|
margin-top: 8px;
|
||||||
|
display: -webkit-box;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #36213e;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 22px;
|
||||||
|
line-height: 1.18;
|
||||||
|
text-decoration: none;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-name:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-meta {
|
||||||
|
margin-top: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-price-block {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-price {
|
||||||
|
color: #36213e;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 21px;
|
||||||
|
line-height: 1.15;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-price--discount {
|
||||||
|
color: #c54c5d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-price-original {
|
||||||
|
color: #8a8a9a;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.15;
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-availability {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
color: #4f7d4f;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.products-empty {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
color: #554971;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.product-1 {
|
.product-1 {
|
||||||
|
|||||||
@@ -2,193 +2,102 @@
|
|||||||
|
|
||||||
<section class="products-section container">
|
<section class="products-section container">
|
||||||
<h2 class="products-title">ПОПУЛЯРНЫЕ ТОВАРЫ</h2>
|
<h2 class="products-title">ПОПУЛЯРНЫЕ ТОВАРЫ</h2>
|
||||||
|
|
||||||
<div class="products-grid">
|
<div class="products-grid">
|
||||||
<article class="product product-1">
|
{% for item in home_products %}
|
||||||
<div class="product-actions">
|
{% url 'detail' item.category.slug item.slug as item_url %}
|
||||||
<button title="В избранное">
|
<article class="product product-{{ forloop.counter }}">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
<a class="product-media" href="{{ item_url }}" aria-label="Открыть товар {{ item.name }}">
|
||||||
class="bi bi-heart" viewBox="0 0 16 16">
|
{% with primary_image=item.primary_image %}
|
||||||
<path d="m8 2.748-.717-.737C5.6.281 2.514.878 1.4 3.053c-.523 1.023-.641 2.5.314 4.385.92 1.815 2.834 3.989 6.286 6.357 3.452-2.368 5.365-4.542 6.286-6.357.955-1.886.838-3.362.314-4.385C13.486.878 10.4.28 8.717 2.01zM8 15C-7.333 4.868 3.279-3.04 7.824 1.143q.09.083.176.171a3 3 0 0 1 .176-.17C12.72-3.042 23.333 4.867 8 15"></path>
|
{% if primary_image %}
|
||||||
</svg>
|
<img src="{{ primary_image.image.url }}" alt="{{ primary_image.alt|default:item.name }}">
|
||||||
</button>
|
{% else %}
|
||||||
<button title="В корзину">
|
<span class="product-placeholder">Нет фото</span>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
{% endif %}
|
||||||
class="bi bi-cart2" viewBox="0 0 16 16">
|
{% endwith %}
|
||||||
<path d="M0 2.5A.5.5 0 0 1 .5 2H2a.5.5 0 0 1 .485.379L2.89 4H14.5a.5.5 0 0 1 .485.621l-1.5 6A.5.5 0 0 1 13 11H4a.5.5 0 0 1-.485-.379L1.61 3H.5a.5.5 0 0 1-.5-.5M3.14 5l1.25 5h8.22l1.25-5zM5 13a1 1 0 1 0 0 2 1 1 0 0 0 0-2m-2 1a2 2 0 1 1 4 0 2 2 0 0 1-4 0m9-1a1 1 0 1 0 0 2 1 1 0 0 0 0-2m-2 1a2 2 0 1 1 4 0 2 2 0 0 1-4 0"></path>
|
</a>
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
|
|
||||||
<article class="product product-2">
|
<div class="product-actions" aria-label="Действия с товаром">
|
||||||
|
{% if request.user.is_authenticated %}
|
||||||
|
<form method="post" action="{% url 'favorites:toggle' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="item_id" value="{{ item.id }}">
|
||||||
|
<input type="hidden" name="next" value="{{ request.get_full_path }}">
|
||||||
|
<button
|
||||||
|
class="{% if item.id in favorite_item_ids %}is-active{% endif %}"
|
||||||
|
type="submit"
|
||||||
|
title="{% if item.id in favorite_item_ids %}Удалить из избранного{% else %}Добавить в избранное{% endif %}"
|
||||||
|
aria-label="{% if item.id in favorite_item_ids %}Удалить из избранного{% else %}Добавить в избранное{% endif %}"
|
||||||
|
>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true" focusable="false">
|
||||||
|
<path d="m8 2.748-.717-.737C5.6.281 2.514.878 1.4 3.053c-.523 1.023-.641 2.5.314 4.385.92 1.815 2.834 3.989 6.286 6.357 3.452-2.368 5.365-4.542 6.286-6.357.955-1.886.838-3.362.314-4.385C13.486.878 10.4.28 8.717 2.01z"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<a
|
||||||
|
href="{% url 'users:login' %}?next={{ request.get_full_path|urlencode }}"
|
||||||
|
title="Войдите, чтобы добавить в избранное"
|
||||||
|
aria-label="Войдите, чтобы добавить в избранное"
|
||||||
|
>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true" focusable="false">
|
||||||
|
<path d="m8 2.748-.717-.737C5.6.281 2.514.878 1.4 3.053c-.523 1.023-.641 2.5.314 4.385.92 1.815 2.834 3.989 6.286 6.357 3.452-2.368 5.365-4.542 6.286-6.357.955-1.886.838-3.362.314-4.385C13.486.878 10.4.28 8.717 2.01z"></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</article>
|
{% if request.user.is_authenticated %}
|
||||||
|
{% if item.id in cart_item_ids %}
|
||||||
|
<a href="{% url 'orders:cart' %}" title="Перейти в корзину" aria-label="Перейти в корзину">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true" focusable="false">
|
||||||
|
<path d="M0 2.5A.5.5 0 0 1 .5 2H2a.5.5 0 0 1 .485.379L2.89 4H14.5a.5.5 0 0 1 .485.621l-1.5 6A.5.5 0 0 1 13 11H4a.5.5 0 0 1-.485-.379L1.61 3H.5a.5.5 0 0 1-.5-.5M3.14 5l1.25 5h8.22l1.25-5zM5 13a1 1 0 1 0 0 2 1 1 0 0 0 0-2m-2 1a2 2 0 1 1 4 0 2 2 0 0 1-4 0m9-1a1 1 0 1 0 0-2m-2 1a2 2 0 1 1 4 0 2 2 0 0 1-4 0"></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
<form method="post" action="{% url 'orders:add' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="item_id" value="{{ item.id }}">
|
||||||
|
<input type="hidden" name="next" value="{{ request.get_full_path }}">
|
||||||
|
<button type="submit" title="В корзину" aria-label="В корзину">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true" focusable="false">
|
||||||
|
<path d="M0 2.5A.5.5 0 0 1 .5 2H2a.5.5 0 0 1 .485.379L2.89 4H14.5a.5.5 0 0 1 .485.621l-1.5 6A.5.5 0 0 1 13 11H4a.5.5 0 0 1-.485-.379L1.61 3H.5a.5.5 0 0 1-.5-.5M3.14 5l1.25 5h8.22l1.25-5zM5 13a1 1 0 1 0 0 2 1 1 0 0 0 0-2m-2 1a2 2 0 1 1 4 0 2 2 0 0 1-4 0m9-1a1 1 0 1 0 0-2m-2 1a2 2 0 1 1 4 0 2 2 0 0 1-4 0"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<a href="{% url 'users:login' %}?next={{ request.get_full_path|urlencode }}" title="Войдите, чтобы добавить в корзину" aria-label="Войдите, чтобы добавить в корзину">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true" focusable="false">
|
||||||
|
<path d="M0 2.5A.5.5 0 0 1 .5 2H2a.5.5 0 0 1 .485.379L2.89 4H14.5a.5.5 0 0 1 .485.621l-1.5 6A.5.5 0 0 1 13 11H4a.5.5 0 0 1-.485-.379L1.61 3H.5a.5.5 0 0 1-.5-.5M3.14 5l1.25 5h8.22l1.25-5zM5 13a1 1 0 1 0 0 2 1 1 0 0 0 0-2m-2 1a2 2 0 1 1 4 0 2 2 0 0 1-4 0m9-1a1 1 0 1 0 0-2m-2 1a2 2 0 1 1 4 0 2 2 0 0 1-4 0"></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
<article class="product product-3">
|
<div class="product-info">
|
||||||
|
<span class="product-category">
|
||||||
</article>
|
{{ item.category.name }}{% if item.subcategory %} / {{ item.subcategory.name }}{% endif %}
|
||||||
|
</span>
|
||||||
<article class="product product-4">
|
<a class="product-name" href="{{ item_url }}">{{ item.name }}</a>
|
||||||
|
<div class="product-meta">
|
||||||
</article>
|
<div class="product-price-block">
|
||||||
|
<span class="product-price{% if item.has_discount %} product-price--discount{% endif %}">
|
||||||
<article class="product product-5">
|
{{ item.display_price }} руб.
|
||||||
|
</span>
|
||||||
</article>
|
{% if item.has_discount %}
|
||||||
|
<span class="product-price-original">{{ item.price }} руб.</span>
|
||||||
<article class="product product-6">
|
{% endif %}
|
||||||
|
</div>
|
||||||
</article>
|
<span class="product-availability">В наличии</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
{% empty %}
|
||||||
|
<p class="products-empty">Товары скоро появятся.</p>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% comment %}
|
|
||||||
<!-- Card 1 — tall -->
|
|
||||||
<div class="product-card tall">
|
|
||||||
<img class="product-card-img" src="{% static 'img/kitchen-sink.jpg' %}" alt="Кухонная мойка">
|
|
||||||
|
|
||||||
<div class="product-info">
|
|
||||||
<div class="p-name">Кухонная мойка</div>
|
|
||||||
<div class="p-sub">Искусственный камень, врезная на столешницу</div>
|
|
||||||
<div class="p-price">1600 руб</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Card 2 -->
|
|
||||||
<div class="product-card">
|
|
||||||
<img class="product-card-img" src="{% static 'img/chopping-board.jpg' %}" alt="Разделочная доска"
|
|
||||||
style="aspect-ratio:4/3;">
|
|
||||||
<div class="product-actions">
|
|
||||||
<button title="В избранное">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
||||||
stroke-width="2">
|
|
||||||
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<button title="В корзину">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
||||||
stroke-width="2">
|
|
||||||
<path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"/>
|
|
||||||
<line x1="3" y1="6" x2="21" y2="6"/>
|
|
||||||
<path d="M16 10a4 4 0 0 1-8 0"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="product-info">
|
|
||||||
<div class="p-name">Разделочная доска</div>
|
|
||||||
<div class="p-sub">Нержавеющая сталь</div>
|
|
||||||
<div class="p-price">50 руб</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Card 3 — tall -->
|
|
||||||
<div class="product-card tall">
|
|
||||||
<img class="product-card-img" src="{% static 'img/terra-mirror.jpg' %}" alt="Зеркало Terra">
|
|
||||||
<div class="product-actions">
|
|
||||||
<button title="В избранное">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
||||||
stroke-width="2">
|
|
||||||
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<button title="В корзину">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
||||||
stroke-width="2">
|
|
||||||
<path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"/>
|
|
||||||
<line x1="3" y1="6" x2="21" y2="6"/>
|
|
||||||
<path d="M16 10a4 4 0 0 1-8 0"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="product-info">
|
|
||||||
<div class="p-name">Зеркало Terra</div>
|
|
||||||
<div class="p-sub">Холодная подсветка, фронтальная</div>
|
|
||||||
<div class="p-price">200 руб</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Card 4 -->
|
|
||||||
<div class="product-card">
|
|
||||||
<img class="product-card-img" src="{% static 'img/toilet.jpg' %}" alt="Унитаз"
|
|
||||||
style="aspect-ratio:4/3;">
|
|
||||||
<div class="product-actions">
|
|
||||||
<button title="В избранное">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
||||||
stroke-width="2">
|
|
||||||
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<button title="В корзину">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
||||||
stroke-width="2">
|
|
||||||
<path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"/>
|
|
||||||
<line x1="3" y1="6" x2="21" y2="6"/>
|
|
||||||
<path d="M16 10a4 4 0 0 1-8 0"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="product-info">
|
|
||||||
<div class="p-name">Унитаз</div>
|
|
||||||
<div class="p-sub">Напольный с бачком, безободковый</div>
|
|
||||||
<div class="p-price">1600 руб</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Card 5 (коврик) -->
|
|
||||||
<div class="product-card">
|
|
||||||
<img class="product-card-img" src="{% static 'img/rubber-mat.jpg' %}" alt="Коврик"
|
|
||||||
style="aspect-ratio:4/3;">
|
|
||||||
<div class="product-actions">
|
|
||||||
<button title="В избранное">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
||||||
stroke-width="2">
|
|
||||||
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<button title="В корзину">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
||||||
stroke-width="2">
|
|
||||||
<path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"/>
|
|
||||||
<line x1="3" y1="6" x2="21" y2="6"/>
|
|
||||||
<path d="M16 10a4 4 0 0 1-8 0"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="product-info">
|
|
||||||
<div class="p-name">Коврик для посуды</div>
|
|
||||||
<div class="p-sub">Мгновенно впитывает воду</div>
|
|
||||||
<div class="p-price">20 руб</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Card 6 (смеситель) -->
|
|
||||||
<div class="product-card">
|
|
||||||
<img class="product-card-img" src="{% static 'img/mixer.jpg' %}" alt="Смеситель"
|
|
||||||
style="aspect-ratio:4/3;">
|
|
||||||
<div class="product-actions">
|
|
||||||
<button title="В избранное">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
||||||
stroke-width="2">
|
|
||||||
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<button title="В корзину">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
||||||
stroke-width="2">
|
|
||||||
<path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"/>
|
|
||||||
<line x1="3" y1="6" x2="21" y2="6"/>
|
|
||||||
<path d="M16 10a4 4 0 0 1-8 0"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="product-info">
|
|
||||||
<div class="p-name">Смеситель</div>
|
|
||||||
<div class="p-sub">Однорычажный смеситель</div>
|
|
||||||
<div class="p-price">340 руб</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>{% endcomment %}
|
|
||||||
|
|
||||||
<div class="products-footer">
|
<div class="products-footer">
|
||||||
<a href="#" class="btn-primary">ПЕРЕЙТИ В КАТАЛОГ</a>
|
<a href="/catalog/" class="btn-primary">ПЕРЕЙТИ В КАТАЛОГ</a>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -180,14 +180,6 @@
|
|||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="promo-row">
|
|
||||||
<label class="checkout-input">
|
|
||||||
<span>Промокод</span>
|
|
||||||
<input type="text" name="promo_code" value="{{ checkout_form.promo_code.value|default:'' }}" placeholder="Промокод">
|
|
||||||
</label>
|
|
||||||
<button type="button">ПРИМЕНИТЬ</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="checkout-summary">
|
<div class="checkout-summary">
|
||||||
<p><strong>Товары, {{ total_quantity }} шт.</strong><span>{{ products_total }}</span></p>
|
<p><strong>Товары, {{ total_quantity }} шт.</strong><span>{{ products_total }}</span></p>
|
||||||
<p><strong>Скидка</strong><span>{{ discount_total }}</span></p>
|
<p><strong>Скидка</strong><span>{{ discount_total }}</span></p>
|
||||||
|
|||||||
Reference in New Issue
Block a user