From a67181ab4240f7523b0d9d982896c99d4afd0df1 Mon Sep 17 00:00:00 2001 From: GitHub Copilot Date: Sun, 16 Aug 2026 12:50:32 +0200 Subject: [PATCH] [IMP] website_sale_aplicoop: skip the product-card tags row when unused The tags row was reserved (empty, aria-hidden) on every product card so prices stay aligned across a grid row regardless of which cards have tags. But when no product in the current batch has a published tag, that row was still a fixed, permanent gap on every card for a feature nobody was using. any_product_has_tags is now computed once per batch (controller-side, per CLAUDE.md's no-logic-in-QWeb rule) from the already-filtered published_tags, and the template skips the row entirely when it's False across all three render paths (initial page, load-more, infinite-scroll AJAX). Co-Authored-By: Claude Sonnet 5 --- .../controllers/website_sale.py | 17 +++++++++ .../views/website_templates.xml | 38 +++++++++++-------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/website_sale_aplicoop/controllers/website_sale.py b/website_sale_aplicoop/controllers/website_sale.py index 058472f..ce2fde2 100644 --- a/website_sale_aplicoop/controllers/website_sale.py +++ b/website_sale_aplicoop/controllers/website_sale.py @@ -847,6 +847,12 @@ class AplicoopWebsiteSale(WebsiteSale): product_display_info, filtered_products_dict, ) = self._prepare_products_maps(products, pricelist) + # Whether the tags row needs to be reserved on every card: if nothing in + # this batch has a published tag, the row is skipped entirely instead of + # leaving an empty aria-hidden gap on every product (see product-card.css). + any_product_has_tags = any( + v["published_tags"] for v in filtered_products_dict.values() + ) # Inject draft sale demand context so ribbons/is_out_of_stock use forecasted net qty products, product_max_qty = self._prepare_draft_stock_data(products) @@ -876,6 +882,7 @@ class AplicoopWebsiteSale(WebsiteSale): "group_order": group_order, "products": products, "filtered_product_tags": filtered_products_dict, + "any_product_has_tags": any_product_has_tags, "cart": cart, "available_categories": available_categories, "category_hierarchy": category_hierarchy, @@ -986,6 +993,10 @@ class AplicoopWebsiteSale(WebsiteSale): "product": product, "published_tags": published_tags, } + # See eskaera_shop for why this decides whether to reserve the tags row. + any_product_has_tags = any( + v["published_tags"] for v in filtered_products_dict.values() + ) product_display_info = {} for product in products_page: @@ -1004,6 +1015,7 @@ class AplicoopWebsiteSale(WebsiteSale): "group_order": group_order, "products": products_page, "filtered_product_tags": filtered_products_dict, + "any_product_has_tags": any_product_has_tags, "product_supplier_info": product_supplier_info, "product_price_info": product_price_info, "product_display_info": product_display_info, @@ -1112,6 +1124,10 @@ class AplicoopWebsiteSale(WebsiteSale): } for product in products_page } + # See eskaera_shop for why this decides whether to reserve the tags row. + any_product_has_tags = any( + v["published_tags"] for v in filtered_products_dict.values() + ) # Inject draft demand context for ribbons/stock flags products_page, product_max_qty = self._prepare_draft_stock_data(products_page) @@ -1126,6 +1142,7 @@ class AplicoopWebsiteSale(WebsiteSale): "group_order": group_order, "products": products_page, "filtered_product_tags": filtered_products_dict, + "any_product_has_tags": any_product_has_tags, "product_supplier_info": product_supplier_info, "product_price_info": product_price_info, "product_display_info": product_display_info, diff --git a/website_sale_aplicoop/views/website_templates.xml b/website_sale_aplicoop/views/website_templates.xml index a4f4e39..08cc8e0 100644 --- a/website_sale_aplicoop/views/website_templates.xml +++ b/website_sale_aplicoop/views/website_templates.xml @@ -661,23 +661,29 @@ - -
- - - - + regardless of which optional fields a given product has. The + tags row itself is only reserved when at least one product in + this batch actually has a tag (any_product_has_tags, computed + controller-side) — otherwise it would add a permanent empty + gap to every card for a feature nobody in the list uses. --> + + +
+ + + + + + + + - - - - -
-
- - + + +