feat(storefront): homepage, module gating, widget protocol, i18n fixes
Some checks failed
Some checks failed
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:
@@ -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 %}
|
||||
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
Reference in New Issue
Block a user