[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 <noreply@anthropic.com>
This commit is contained in:
GitHub Copilot 2026-08-16 12:50:32 +02:00
parent f3e39550c2
commit a67181ab42
2 changed files with 39 additions and 16 deletions

View file

@ -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,