feat: wishlist view
This commit is contained in:
@@ -135,6 +135,8 @@ STATIC_ROOT = BASE_DIR / "static"
|
||||
MEDIA_URL = "/media/"
|
||||
MEDIA_ROOT = BASE_DIR / "media"
|
||||
|
||||
LOGIN_REDIRECT_URL = "/login/"
|
||||
|
||||
STORAGES = {
|
||||
"default": {
|
||||
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<input type="hidden" name="product" value="{{ product.pk }}">
|
||||
{% csrf_token %}
|
||||
<button class="flex items-center justify-center py-2.5 px-5 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700">
|
||||
{% include 'components/icons/like.svg' %}
|
||||
{% include 'components/icons/x.svg' %}
|
||||
{% translate 'Quitar de la lista de deseados' %}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" title=""
|
||||
<a href="{% url 'web:wishlist' %}" title=""
|
||||
class="inline-flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm hover:bg-gray-100 dark:hover:bg-gray-600">
|
||||
{% translate 'Lista de deseados' %}
|
||||
</a>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
{% extends 'theme/base.html' %}
|
||||
{% load static i18n %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'components/generic/navbar.html' %}
|
||||
<div>
|
||||
<section
|
||||
class="p-8"
|
||||
hx-get="{% url 'web:list_wishlisted_products' %}"
|
||||
hx-trigger="load, updated-wishlist"
|
||||
hx-target="#products"
|
||||
hx-swap="innerHTML"
|
||||
>
|
||||
<h1
|
||||
class="text-xl font-semibold text-gray-900 dark:text-white sm:text-2xl my-4"
|
||||
>
|
||||
{% translate 'Lista de deseados' %}
|
||||
</h1>
|
||||
|
||||
<div>
|
||||
<section id="products">
|
||||
|
||||
</section>
|
||||
|
||||
<div class="w-full text-center">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -38,10 +38,12 @@ class TestWishlist(TestCase, CreateProductsMixin):
|
||||
reverse("web:add_to_wishlist"),
|
||||
{
|
||||
"product": self.product.pk,
|
||||
}
|
||||
},
|
||||
)
|
||||
assert response.status_code == 201
|
||||
assert WishlistedProduct.objects.filter(user=self.user, product=self.product).exists()
|
||||
assert WishlistedProduct.objects.filter(
|
||||
user=self.user, product=self.product
|
||||
).exists()
|
||||
|
||||
def test_logged_user_delete_wishlisted_product(self):
|
||||
wishlisted = WishlistedProduct.objects.create(
|
||||
@@ -53,4 +55,27 @@ class TestWishlist(TestCase, CreateProductsMixin):
|
||||
reverse("web:delete_from_wishlist", kwargs={"pk": wishlisted.pk})
|
||||
)
|
||||
assert response.status_code == 204
|
||||
assert not WishlistedProduct.objects.filter(user=self.user, product=self.product).exists()
|
||||
assert not WishlistedProduct.objects.filter(
|
||||
user=self.user, product=self.product
|
||||
).exists()
|
||||
|
||||
def test_logged_user_wishlist(self):
|
||||
WishlistedProduct.objects.create(
|
||||
user=self.user,
|
||||
product=self.product,
|
||||
)
|
||||
self.client.force_login(self.user)
|
||||
response = self.client.get(
|
||||
reverse("web:wishlist")
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_not_logged_user_wishlist(self):
|
||||
WishlistedProduct.objects.create(
|
||||
user=self.user,
|
||||
product=self.product,
|
||||
)
|
||||
response = self.client.get(
|
||||
reverse("web:wishlist")
|
||||
)
|
||||
assert response.status_code == 302
|
||||
|
||||
+15
-2
@@ -1,6 +1,12 @@
|
||||
from django.urls import path
|
||||
|
||||
from web.views.components import cart, cart_dropdown, list_products, wishlist_button
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from web.views.components import (
|
||||
cart,
|
||||
cart_dropdown,
|
||||
list_products,
|
||||
wishlist_button,
|
||||
list_wishlisted_products,
|
||||
)
|
||||
from web.views.users import login, logout, my_account, register, reset_password
|
||||
from web.views.web import (
|
||||
add_cart_item,
|
||||
@@ -12,12 +18,14 @@ from web.views.web import (
|
||||
index,
|
||||
manifest,
|
||||
product_detail,
|
||||
wishlist,
|
||||
)
|
||||
|
||||
app_name = "web"
|
||||
|
||||
urlpatterns = [
|
||||
path("", index, name="index"),
|
||||
path("wishlist", login_required(wishlist, login_url="/login/"), name="wishlist"),
|
||||
path("categories/<str:slug>/", category_view, name="category_view"),
|
||||
path("products/<int:pk>/<str:slug>/", product_detail, name="product_detail"),
|
||||
path("cart/", cart_detail, name="cart_detail"),
|
||||
@@ -29,6 +37,11 @@ urlpatterns = [
|
||||
path("my-account/", my_account, name="my_account"),
|
||||
# components
|
||||
path("web/components/products/", list_products, name="list_products"),
|
||||
path(
|
||||
"web/components/wishlist/",
|
||||
list_wishlisted_products,
|
||||
name="list_wishlisted_products",
|
||||
),
|
||||
path("web/components/cart-dropdown/", cart_dropdown, name="cart_dropdown"),
|
||||
path("web/components/cart/", cart, name="cart"),
|
||||
path(
|
||||
|
||||
@@ -28,6 +28,32 @@ class ListProducts(TemplateView, FilteredQuerysetMixin, PaginatedQuerysetMixin):
|
||||
}
|
||||
|
||||
|
||||
class ListWishlistedProducts(
|
||||
TemplateView, FilteredQuerysetMixin, PaginatedQuerysetMixin
|
||||
):
|
||||
template_name = "web/list_products.html"
|
||||
queryset = Product.objects.filter(hidden=False).prefetch_related(
|
||||
"images",
|
||||
)
|
||||
filter_class = ProductFilter
|
||||
|
||||
def get_queryset(self):
|
||||
product_ids = WishlistedProduct.objects.filter(
|
||||
user=self.request.user
|
||||
).values_list("product", flat=True)
|
||||
return super().get_queryset().filter(pk__in=product_ids).distinct()
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
qs = self.get_queryset()
|
||||
page = self.get_paginated_queryset(qs)
|
||||
|
||||
return {
|
||||
"page": page,
|
||||
"has_next_page": page.has_next(),
|
||||
"has_previous_page": page.has_previous(),
|
||||
}
|
||||
|
||||
|
||||
def cart_dropdown(request, *args, **kwargs):
|
||||
cart, created = get_or_create_cart(request)
|
||||
|
||||
@@ -91,4 +117,5 @@ class WishlistButton(TemplateView):
|
||||
|
||||
|
||||
list_products = ListProducts.as_view()
|
||||
list_wishlisted_products = ListWishlistedProducts.as_view()
|
||||
wishlist_button = WishlistButton.as_view()
|
||||
|
||||
@@ -71,6 +71,18 @@ class CartDetail(TemplateView):
|
||||
}
|
||||
|
||||
|
||||
class WishlistView(TemplateView):
|
||||
template_name = "web/wishlist.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
settings = WebSettings.load()
|
||||
return {
|
||||
"title": settings.web_title,
|
||||
"web_title": settings.web_title,
|
||||
"description": settings.web_description,
|
||||
}
|
||||
|
||||
|
||||
@require_http_methods(
|
||||
[
|
||||
"POST",
|
||||
@@ -188,3 +200,4 @@ index = IndexView.as_view()
|
||||
category_view = CategoryView.as_view()
|
||||
product_detail = ProductDetail.as_view()
|
||||
cart_detail = CartDetail.as_view()
|
||||
wishlist = WishlistView.as_view()
|
||||
|
||||
Reference in New Issue
Block a user