fix: improve platform homepage pricing UI and restore footer links

- Fix toggle button alignment with consistent min-widths
- Add € currency signs to all prices
- Show all tier features with greyed unavailable ones
- Add multi-channel integration feature for Enterprise tier
- Change Contact Sales to mailto link (fixes 404)
- Restore footer CMS page links (About, FAQ, Contact)
- Add footer link translations for all 4 languages

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-27 18:08:05 +01:00
parent bb0aabb918
commit 29a06d8c46
6 changed files with 87 additions and 33 deletions

View File

@@ -32,6 +32,10 @@ def get_platform_context(request: Request, db: Session) -> dict:
# Get language from request state (set by middleware) # Get language from request state (set by middleware)
language = getattr(request.state, "language", "fr") language = getattr(request.state, "language", "fr")
# Get translation function
i18n_globals = get_jinja2_globals(language)
t = i18n_globals["t"]
context = { context = {
"request": request, "request": request,
"platform_name": "Wizamart", "platform_name": "Wizamart",
@@ -41,7 +45,14 @@ def get_platform_context(request: Request, db: Session) -> dict:
} }
# Add i18n globals (_, t, current_language, SUPPORTED_LANGUAGES, etc.) # Add i18n globals (_, t, current_language, SUPPORTED_LANGUAGES, etc.)
context.update(get_jinja2_globals(language)) context.update(i18n_globals)
# Add footer CMS pages
context["footer_pages"] = [
{"slug": "about", "title": t("platform.footer.about")},
{"slug": "faq", "title": t("platform.footer.faq")},
{"slug": "contact", "title": t("platform.footer.contact_us")},
]
return context return context

View File

@@ -74,15 +74,15 @@
</p> </p>
{# Billing Toggle #} {# Billing Toggle #}
<div class="flex items-center justify-center mt-8 space-x-4"> <div class="flex items-center justify-center mt-8 gap-4">
<span class="text-gray-700 dark:text-gray-300" :class="{ 'font-semibold': !annual }">{{ _("platform.pricing.monthly") }}</span> <span class="text-gray-700 dark:text-gray-300 min-w-[70px] text-right" :class="{ 'font-semibold': !annual }">{{ _("platform.pricing.monthly") }}</span>
<button @click="annual = !annual" <button @click="annual = !annual"
class="relative w-14 h-7 rounded-full transition-colors" class="relative w-14 h-7 rounded-full transition-colors flex-shrink-0"
:class="annual ? 'bg-indigo-600' : 'bg-gray-300 dark:bg-gray-600'"> :class="annual ? 'bg-indigo-600' : 'bg-gray-300 dark:bg-gray-600'">
<span class="absolute top-1 left-1 w-5 h-5 bg-white rounded-full shadow transition-transform" <span class="absolute top-1 left-1 w-5 h-5 bg-white rounded-full shadow transition-transform"
:class="annual ? 'translate-x-7' : ''"></span> :class="annual ? 'translate-x-7' : ''"></span>
</button> </button>
<span class="text-gray-700 dark:text-gray-300" :class="{ 'font-semibold': annual }"> <span class="text-gray-700 dark:text-gray-300 min-w-[150px]" :class="{ 'font-semibold': annual }">
{{ _("platform.pricing.annual") }} {{ _("platform.pricing.annual") }}
<span class="text-green-600 text-sm font-medium ml-1">{{ _("platform.pricing.save_months") }}</span> <span class="text-green-600 text-sm font-medium ml-1">{{ _("platform.pricing.save_months") }}</span>
</span> </span>
@@ -111,17 +111,17 @@
<div class="mb-6"> <div class="mb-6">
<template x-if="!annual"> <template x-if="!annual">
<div> <div>
<span class="text-4xl font-extrabold text-gray-900 dark:text-white">{{ tier.price_monthly }}</span> <span class="text-4xl font-extrabold text-gray-900 dark:text-white">{{ tier.price_monthly|int }}</span>
<span class="text-gray-500 dark:text-gray-400">{{ _("platform.pricing.per_month") }}</span> <span class="text-gray-500 dark:text-gray-400">{{ _("platform.pricing.per_month") }}</span>
</div> </div>
</template> </template>
<template x-if="annual"> <template x-if="annual">
<div> <div>
{% if tier.price_annual %} {% if tier.price_annual %}
<span class="text-4xl font-extrabold text-gray-900 dark:text-white">{{ (tier.price_annual / 12)|round(0)|int }}</span> <span class="text-4xl font-extrabold text-gray-900 dark:text-white">{{ (tier.price_annual / 12)|round(0)|int }}</span>
<span class="text-gray-500 dark:text-gray-400">{{ _("platform.pricing.per_month") }}</span> <span class="text-gray-500 dark:text-gray-400">{{ _("platform.pricing.per_month") }}</span>
<div class="text-sm text-gray-500 dark:text-gray-400"> <div class="text-sm text-gray-500 dark:text-gray-400">
{{ tier.price_annual }}{{ _("platform.pricing.per_year") }} {{ tier.price_annual|int }}{{ _("platform.pricing.per_year") }}
</div> </div>
{% else %} {% else %}
<span class="text-2xl font-bold text-gray-900 dark:text-white">{{ _("platform.pricing.custom") }}</span> <span class="text-2xl font-bold text-gray-900 dark:text-white">{{ _("platform.pricing.custom") }}</span>
@@ -130,66 +130,93 @@
</template> </template>
</div> </div>
{# Features List #} {# Features List - Show all features, grey out unavailable #}
<ul class="space-y-3 mb-8"> <ul class="space-y-2 mb-8 text-sm">
{# Orders #} {# Orders #}
<li class="flex items-center text-gray-700 dark:text-gray-300"> <li class="flex items-center text-gray-700 dark:text-gray-300">
<svg class="w-5 h-5 text-green-500 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-4 h-4 text-green-500 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/> <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg> </svg>
{% if tier.orders_per_month %}{{ _("platform.pricing.orders_per_month", count=tier.orders_per_month) }}{% else %}{{ _("platform.pricing.unlimited_orders") }}{% endif %} {% if tier.orders_per_month %}{{ _("platform.pricing.orders_per_month", count=tier.orders_per_month) }}{% else %}{{ _("platform.pricing.unlimited_orders") }}{% endif %}
</li> </li>
{# Products #} {# Products #}
<li class="flex items-center text-gray-700 dark:text-gray-300"> <li class="flex items-center text-gray-700 dark:text-gray-300">
<svg class="w-5 h-5 text-green-500 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-4 h-4 text-green-500 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/> <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg> </svg>
{% if tier.products_limit %}{{ _("platform.pricing.products_limit", count=tier.products_limit) }}{% else %}{{ _("platform.pricing.unlimited_products") }}{% endif %} {% if tier.products_limit %}{{ _("platform.pricing.products_limit", count=tier.products_limit) }}{% else %}{{ _("platform.pricing.unlimited_products") }}{% endif %}
</li> </li>
{# Team Members #} {# Team Members #}
<li class="flex items-center text-gray-700 dark:text-gray-300"> <li class="flex items-center text-gray-700 dark:text-gray-300">
<svg class="w-5 h-5 text-green-500 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-4 h-4 text-green-500 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/> <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg> </svg>
{% if tier.team_members %}{{ _("platform.pricing.team_members", count=tier.team_members) }}{% else %}{{ _("platform.pricing.unlimited_team") }}{% endif %} {% if tier.team_members %}{{ _("platform.pricing.team_members", count=tier.team_members) }}{% else %}{{ _("platform.pricing.unlimited_team") }}{% endif %}
</li> </li>
{# Letzshop Sync #} {# Letzshop Sync - always included #}
<li class="flex items-center text-gray-700 dark:text-gray-300"> <li class="flex items-center text-gray-700 dark:text-gray-300">
<svg class="w-5 h-5 text-green-500 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-4 h-4 text-green-500 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/> <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg> </svg>
{{ _("platform.pricing.letzshop_sync") }} {{ _("platform.pricing.letzshop_sync") }}
</li> </li>
{# Tier-specific features #} {# EU VAT Invoicing #}
{% if 'invoice_eu_vat' in tier.features %} <li class="flex items-center {% if 'invoice_eu_vat' in tier.features %}text-gray-700 dark:text-gray-300{% else %}text-gray-400 dark:text-gray-600{% endif %}">
<li class="flex items-center text-gray-700 dark:text-gray-300"> {% if 'invoice_eu_vat' in tier.features %}
<svg class="w-5 h-5 text-green-500 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-4 h-4 text-green-500 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/> <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg> </svg>
{% else %}
<svg class="w-4 h-4 text-gray-300 dark:text-gray-600 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/>
</svg>
{% endif %}
{{ _("platform.pricing.eu_vat_invoicing") }} {{ _("platform.pricing.eu_vat_invoicing") }}
</li> </li>
{% endif %} {# Analytics Dashboard #}
{% if 'analytics_dashboard' in tier.features %} <li class="flex items-center {% if 'analytics_dashboard' in tier.features %}text-gray-700 dark:text-gray-300{% else %}text-gray-400 dark:text-gray-600{% endif %}">
<li class="flex items-center text-gray-700 dark:text-gray-300"> {% if 'analytics_dashboard' in tier.features %}
<svg class="w-5 h-5 text-green-500 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-4 h-4 text-green-500 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/> <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg> </svg>
{% else %}
<svg class="w-4 h-4 text-gray-300 dark:text-gray-600 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/>
</svg>
{% endif %}
{{ _("platform.pricing.analytics_dashboard") }} {{ _("platform.pricing.analytics_dashboard") }}
</li> </li>
{% endif %} {# API Access #}
{% if 'api_access' in tier.features %} <li class="flex items-center {% if 'api_access' in tier.features %}text-gray-700 dark:text-gray-300{% else %}text-gray-400 dark:text-gray-600{% endif %}">
<li class="flex items-center text-gray-700 dark:text-gray-300"> {% if 'api_access' in tier.features %}
<svg class="w-5 h-5 text-green-500 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-4 h-4 text-green-500 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/> <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg> </svg>
{% else %}
<svg class="w-4 h-4 text-gray-300 dark:text-gray-600 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/>
</svg>
{% endif %}
{{ _("platform.pricing.api_access") }} {{ _("platform.pricing.api_access") }}
</li> </li>
{% endif %} {# Multi-channel Integration - Enterprise only #}
<li class="flex items-center {% if tier.is_enterprise %}text-gray-700 dark:text-gray-300{% else %}text-gray-400 dark:text-gray-600{% endif %}">
{% if tier.is_enterprise %}
<svg class="w-4 h-4 text-green-500 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
{% else %}
<svg class="w-4 h-4 text-gray-300 dark:text-gray-600 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/>
</svg>
{% endif %}
{{ _("platform.pricing.multi_channel") }}
</li>
</ul> </ul>
{# CTA Button #} {# CTA Button #}
{% if tier.is_enterprise %} {% if tier.is_enterprise %}
<a href="/contact?tier=enterprise" <a href="mailto:sales@wizamart.com?subject=Enterprise%20Plan%20Inquiry"
class="block w-full py-3 px-4 bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white font-semibold rounded-xl text-center hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors"> class="block w-full py-3 px-4 bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white font-semibold rounded-xl text-center hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">
{{ _("platform.pricing.contact_sales") }} {{ _("platform.pricing.contact_sales") }}
</a> </a>

View File

@@ -512,6 +512,7 @@
"eu_vat_invoicing": "EU-MwSt-Rechnungen", "eu_vat_invoicing": "EU-MwSt-Rechnungen",
"analytics_dashboard": "Analyse-Dashboard", "analytics_dashboard": "Analyse-Dashboard",
"api_access": "API-Zugang", "api_access": "API-Zugang",
"multi_channel": "Multi-Channel-Integration",
"products": "Produkte", "products": "Produkte",
"team_member": "Teammitglied", "team_member": "Teammitglied",
"unlimited": "Unbegrenzt", "unlimited": "Unbegrenzt",
@@ -631,7 +632,10 @@
"contact": "Kontakt", "contact": "Kontakt",
"copyright": "© {year} Wizamart. Entwickelt für den luxemburgischen E-Commerce.", "copyright": "© {year} Wizamart. Entwickelt für den luxemburgischen E-Commerce.",
"privacy": "Datenschutzerklärung", "privacy": "Datenschutzerklärung",
"terms": "Nutzungsbedingungen" "terms": "Nutzungsbedingungen",
"about": "Über uns",
"faq": "FAQ",
"contact_us": "Kontaktieren Sie uns"
}, },
"modern": { "modern": {
"badge_integration": "Offizielle Integration", "badge_integration": "Offizielle Integration",

View File

@@ -512,6 +512,7 @@
"eu_vat_invoicing": "EU VAT invoicing", "eu_vat_invoicing": "EU VAT invoicing",
"analytics_dashboard": "Analytics dashboard", "analytics_dashboard": "Analytics dashboard",
"api_access": "API access", "api_access": "API access",
"multi_channel": "Multi-channel integration",
"products": "products", "products": "products",
"team_member": "team member", "team_member": "team member",
"unlimited": "Unlimited", "unlimited": "Unlimited",
@@ -631,7 +632,10 @@
"contact": "Contact", "contact": "Contact",
"copyright": "© {year} Wizamart. Built for Luxembourg e-commerce.", "copyright": "© {year} Wizamart. Built for Luxembourg e-commerce.",
"privacy": "Privacy Policy", "privacy": "Privacy Policy",
"terms": "Terms of Service" "terms": "Terms of Service",
"about": "About Us",
"faq": "FAQ",
"contact_us": "Contact Us"
}, },
"modern": { "modern": {
"badge_integration": "Official Integration", "badge_integration": "Official Integration",

View File

@@ -512,6 +512,7 @@
"eu_vat_invoicing": "Facturation TVA UE", "eu_vat_invoicing": "Facturation TVA UE",
"analytics_dashboard": "Tableau de bord analytique", "analytics_dashboard": "Tableau de bord analytique",
"api_access": "Accès API", "api_access": "Accès API",
"multi_channel": "Intégration multi-canal",
"products": "produits", "products": "produits",
"team_member": "membre d'équipe", "team_member": "membre d'équipe",
"unlimited": "Illimité", "unlimited": "Illimité",
@@ -631,7 +632,10 @@
"contact": "Contact", "contact": "Contact",
"copyright": "© {year} Wizamart. Conçu pour le e-commerce luxembourgeois.", "copyright": "© {year} Wizamart. Conçu pour le e-commerce luxembourgeois.",
"privacy": "Politique de confidentialité", "privacy": "Politique de confidentialité",
"terms": "Conditions d'utilisation" "terms": "Conditions d'utilisation",
"about": "À propos",
"faq": "FAQ",
"contact_us": "Nous contacter"
}, },
"modern": { "modern": {
"badge_integration": "Intégration officielle", "badge_integration": "Intégration officielle",

View File

@@ -512,6 +512,7 @@
"eu_vat_invoicing": "EU TVA Rechnungen", "eu_vat_invoicing": "EU TVA Rechnungen",
"analytics_dashboard": "Analyse Dashboard", "analytics_dashboard": "Analyse Dashboard",
"api_access": "API Zougang", "api_access": "API Zougang",
"multi_channel": "Multi-Channel Integratioun",
"products": "Produkter", "products": "Produkter",
"team_member": "Teammember", "team_member": "Teammember",
"unlimited": "Onbegrenzt", "unlimited": "Onbegrenzt",
@@ -631,7 +632,10 @@
"contact": "Kontakt", "contact": "Kontakt",
"copyright": "© {year} Wizamart. Gemaach fir de lëtzebuergeschen E-Commerce.", "copyright": "© {year} Wizamart. Gemaach fir de lëtzebuergeschen E-Commerce.",
"privacy": "Dateschutzrichtlinn", "privacy": "Dateschutzrichtlinn",
"terms": "Notzungsbedéngungen" "terms": "Notzungsbedéngungen",
"about": "Iwwer eis",
"faq": "FAQ",
"contact_us": "Kontaktéiert eis"
}, },
"modern": { "modern": {
"badge_integration": "Offiziell Integratioun", "badge_integration": "Offiziell Integratioun",