feat(storefront): homepage, module gating, widget protocol, i18n fixes
Some checks failed
CI / ruff (push) Successful in 14s
CI / pytest (push) Failing after 2h32m45s
CI / validate (push) Successful in 30s
CI / dependency-scanning (push) Successful in 31s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped

Storefront homepage & module gating:
- CMS owns storefront GET / (slug="home" with 3-tier resolution)
- Catalog loses GET / (keeps /products only)
- Store root redirect (GET / → /store/dashboard or /store/login)
- Route gating: non-core modules return 404 when disabled for platform
- Seed store default homepages per platform

Widget protocol for customer dashboard:
- StorefrontDashboardCard contract in widgets.py
- Widget aggregator get_storefront_dashboard_cards()
- Orders and Loyalty module widget providers
- Dashboard template renders contributed cards (no module names)

Landing template module-agnostic:
- CTAs driven by storefront_nav (not hardcoded module names)
- Header actions check nav item IDs (not enabled_modules)
- Remove hardcoded "Add Product" sidebar button
- Remove all enabled_modules checks from storefront templates

i18n fixes:
- Title placeholder resolution ({{store_name}}) for store default pages
- Storefront nav label_keys prefixed with module code
- Add storefront.account.* keys to 6 modules (en/fr/de/lb)
- Header/footer CMS pages use get_translated_title(current_language)
- Footer labels use i18n keys instead of hardcoded English

Icon cleanup:
- Standardize on map-pin (remove location-marker alias)
- Replace all location-marker references across templates and docs

Docs:
- Storefront builder vision proposal (6 phases)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-13 22:53:17 +02:00
parent dd9dc04328
commit adc36246b8
58 changed files with 4691 additions and 3806 deletions

View File

@@ -106,16 +106,6 @@
</div>
</div>
{% if 'catalog' in enabled_modules %}
<!-- Quick Actions (static, outside dynamic menu) -->
<div class="px-6 my-6">
<button class="flex items-center justify-between w-full px-4 py-2 text-sm font-medium leading-5 text-white transition-colors duration-150 bg-purple-600 border border-transparent rounded-lg active:bg-purple-600 hover:bg-purple-700 focus:outline-none focus:shadow-outline-purple"
@click="$dispatch('open-add-product-modal')">
<span x-html="$icon('plus', 'w-4 h-4')"></span>
<span class="ml-2">Add Product</span>
</button>
</div>
{% endif %}
</div>
{% endmacro %}

View File

@@ -100,7 +100,7 @@
{# CMS pages (About, Contact) are already dynamic via header_pages #}
{% for page in header_pages|default([]) %}
<a href="{{ base_url }}{{ page.slug }}" class="text-gray-700 dark:text-gray-300 hover:text-primary">
{{ page.title }}
{{ page.get_translated_title(current_language) }}
</a>
{% endfor %}
</nav>
@@ -108,7 +108,10 @@
{# Right side actions #}
<div class="flex items-center space-x-4">
{% if 'catalog' in enabled_modules|default([]) %}
{# Action items from enabled modules (search, cart, etc.) #}
{% set action_ids = storefront_nav.get('actions', [])|map(attribute='id')|list %}
{% if 'search' in action_ids %}
{# Search #}
<button @click="openSearch()" class="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -118,7 +121,7 @@
</button>
{% endif %}
{% if 'cart' in enabled_modules|default([]) %}
{% if 'cart' in action_ids %}
{# Cart #}
<a href="{{ base_url }}cart" class="relative p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -131,7 +134,7 @@
style="background-color: var(--color-accent)">
</span>
</a>
{% endif %}
{% endif %}{# cart #}
{# Theme toggle #}
<button @click="toggleTheme()"
@@ -272,7 +275,7 @@
{% for page in header_pages|default([]) %}
<a href="{{ base_url }}{{ page.slug }}" @click="closeMobileMenu()"
class="block px-3 py-2 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
{{ page.title }}
{{ page.get_translated_title(current_language) }}
</a>
{% endfor %}
</nav>
@@ -332,13 +335,10 @@
{# Column 1 #}
<div>
<h4 class="font-semibold mb-4">Quick Links</h4>
<h4 class="font-semibold mb-4">{{ _('cms.storefront.quick_links') }}</h4>
<ul class="space-y-2">
{% if 'catalog' in enabled_modules|default([]) %}
<li><a href="{{ base_url }}products" class="text-gray-600 hover:text-primary dark:text-gray-400">Products</a></li>
{% endif %}
{% for page in col1_pages %}
<li><a href="{{ base_url }}{{ page.slug }}" class="text-gray-600 hover:text-primary dark:text-gray-400">{{ page.title }}</a></li>
<li><a href="{{ base_url }}{{ page.slug }}" class="text-gray-600 hover:text-primary dark:text-gray-400">{{ page.get_translated_title(current_language) }}</a></li>
{% endfor %}
</ul>
</div>
@@ -346,10 +346,10 @@
{# Column 2 #}
{% if col2_pages %}
<div>
<h4 class="font-semibold mb-4">Information</h4>
<h4 class="font-semibold mb-4">{{ _('cms.storefront.information') }}</h4>
<ul class="space-y-2">
{% for page in col2_pages %}
<li><a href="{{ base_url }}{{ page.slug }}" class="text-gray-600 hover:text-primary dark:text-gray-400">{{ page.title }}</a></li>
<li><a href="{{ base_url }}{{ page.slug }}" class="text-gray-600 hover:text-primary dark:text-gray-400">{{ page.get_translated_title(current_language) }}</a></li>
{% endfor %}
</ul>
</div>
@@ -357,22 +357,17 @@
{% else %}
{# Fallback: Static links if no CMS pages configured #}
<div>
<h4 class="font-semibold mb-4">Quick Links</h4>
<h4 class="font-semibold mb-4">{{ _('cms.storefront.quick_links') }}</h4>
<ul class="space-y-2">
{% if 'catalog' in enabled_modules|default([]) %}
<li><a href="{{ base_url }}products" class="text-gray-600 hover:text-primary dark:text-gray-400">Products</a></li>
{% endif %}
<li><a href="{{ base_url }}about" class="text-gray-600 hover:text-primary dark:text-gray-400">About Us</a></li>
<li><a href="{{ base_url }}contact" class="text-gray-600 hover:text-primary dark:text-gray-400">Contact</a></li>
<li><a href="{{ base_url }}about" class="text-gray-600 hover:text-primary dark:text-gray-400">{{ _('cms.storefront.about') }}</a></li>
<li><a href="{{ base_url }}contact" class="text-gray-600 hover:text-primary dark:text-gray-400">{{ _('cms.storefront.contact') }}</a></li>
</ul>
</div>
<div>
<h4 class="font-semibold mb-4">Information</h4>
<h4 class="font-semibold mb-4">{{ _('cms.storefront.information') }}</h4>
<ul class="space-y-2">
<li><a href="{{ base_url }}faq" class="text-gray-600 hover:text-primary dark:text-gray-400">FAQ</a></li>
<li><a href="{{ base_url }}shipping" class="text-gray-600 hover:text-primary dark:text-gray-400">Shipping</a></li>
<li><a href="{{ base_url }}returns" class="text-gray-600 hover:text-primary dark:text-gray-400">Returns</a></li>
<li><a href="{{ base_url }}faq" class="text-gray-600 hover:text-primary dark:text-gray-400">{{ _('cms.storefront.faq') }}</a></li>
</ul>
</div>
{% endif %}