Replace all ~1,086 occurrences of Wizamart/wizamart/WIZAMART/WizaMart with Orion/orion/ORION across 184 files. This includes database identifiers, email addresses, domain references, R2 bucket names, DNS prefixes, encryption salt, Celery app name, config defaults, Docker configs, CI configs, documentation, seed data, and templates. Renames homepage-wizamart.html template to homepage-orion.html. Fixes duplicate file_pattern key in api.yaml architecture rule. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
356 lines
17 KiB
HTML
356 lines
17 KiB
HTML
{# app/templates/platform/base.html #}
|
|
{# Base template for platform pages (homepage, about, faq, pricing, signup, etc.) #}
|
|
<!DOCTYPE html>
|
|
<html lang="{{ current_language|default('en') }}" x-data="platformLayoutData()" x-bind:class="{ 'dark': dark }">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
{# Dynamic page title #}
|
|
<title>{% block title %}Orion - Order Management for Letzshop Sellers{% endblock %}</title>
|
|
|
|
{# SEO Meta Tags #}
|
|
<meta name="description" content="{% block meta_description %}Lightweight OMS for Letzshop stores in Luxembourg. Order management, inventory, and invoicing made simple.{% endblock %}">
|
|
<meta name="keywords" content="{% block meta_keywords %}letzshop, order management, oms, luxembourg, e-commerce, invoicing, inventory{% endblock %}">
|
|
|
|
{# Favicon #}
|
|
<link rel="icon" type="image/x-icon" href="{{ url_for('static', path='favicon.ico') }}">
|
|
|
|
{# Platform color scheme #}
|
|
<style id="platform-theme-variables">
|
|
:root {
|
|
/* Platform Colors */
|
|
--color-primary: #6366f1; /* Indigo */
|
|
--color-secondary: #8b5cf6; /* Purple */
|
|
--color-accent: #ec4899; /* Pink */
|
|
|
|
/* Typography */
|
|
--font-heading: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
--font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
}
|
|
|
|
/* Dark mode colors */
|
|
.dark {
|
|
--color-primary: #818cf8;
|
|
--color-secondary: #a78bfa;
|
|
--color-accent: #f472b6;
|
|
}
|
|
</style>
|
|
|
|
{# Fonts: Local fallback + Google Fonts #}
|
|
<link href="/static/shared/fonts/inter.css" rel="stylesheet" />
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
|
|
|
|
{# Tailwind CSS v4 (built locally via standalone CLI) #}
|
|
<link rel="stylesheet" href="{{ url_for('static', path='platform/css/tailwind.output.css') }}">
|
|
|
|
{# Flag icons for language selector #}
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/lipis/flag-icons@7.0.0/css/flag-icons.min.css"/>
|
|
|
|
{% block extra_head %}{% endblock %}
|
|
</head>
|
|
|
|
<body class="bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors duration-200">
|
|
|
|
{# Header / Navigation #}
|
|
<header class="sticky top-0 z-50 bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700">
|
|
<nav class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div class="flex justify-between items-center h-16">
|
|
|
|
{# Logo / Brand #}
|
|
<div class="flex items-center">
|
|
<a href="/" class="flex items-center space-x-3">
|
|
<div class="w-8 h-8 rounded-lg bg-gradient-to-r from-indigo-600 to-purple-600 flex items-center justify-center">
|
|
<span class="text-white font-bold text-xl">W</span>
|
|
</div>
|
|
<span class="text-xl font-bold text-gray-900 dark:text-white">
|
|
Orion
|
|
</span>
|
|
</a>
|
|
</div>
|
|
|
|
{# Desktop Navigation #}
|
|
<div class="hidden md:flex items-center space-x-8">
|
|
{# Main Navigation #}
|
|
<a href="/pricing" class="text-gray-700 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 font-medium transition-colors">
|
|
{{ _("cms.platform.nav.pricing") }}
|
|
</a>
|
|
<a href="/find-shop" class="text-gray-700 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 font-medium transition-colors">
|
|
{{ _("cms.platform.nav.find_shop") }}
|
|
</a>
|
|
<a href="/signup" class="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 text-white font-medium rounded-lg transition-colors">
|
|
{{ _("cms.platform.nav.start_trial") }}
|
|
</a>
|
|
|
|
{# Dynamic header navigation from CMS #}
|
|
{% if header_pages %}
|
|
{% for page in header_pages %}
|
|
<a href="/{{ page.slug }}"
|
|
class="text-gray-700 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 font-medium transition-colors">
|
|
{{ page.title }}
|
|
</a>
|
|
{% endfor %}
|
|
{% endif %}
|
|
|
|
{# Language selector - inline version for platform #}
|
|
<div x-data="platformLanguageSelector()" class="relative">
|
|
<button
|
|
@click="isOpen = !isOpen"
|
|
@click.outside="isOpen = false"
|
|
type="button"
|
|
class="p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors"
|
|
:class="{ 'bg-gray-100 dark:bg-gray-700': isOpen }"
|
|
>
|
|
<span class="fi text-lg" :class="'fi-' + flags[currentLang]"></span>
|
|
</button>
|
|
<div
|
|
x-show="isOpen"
|
|
x-transition
|
|
class="absolute right-0 z-50 mt-1 w-44 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 py-1"
|
|
>
|
|
<template x-for="lang in languages" :key="lang">
|
|
<button
|
|
@click="setLanguage(lang)"
|
|
type="button"
|
|
class="flex items-center gap-3 w-full px-4 py-2 text-sm font-medium transition-colors"
|
|
:class="currentLang === lang
|
|
? 'bg-indigo-50 dark:bg-indigo-900/20 text-indigo-700 dark:text-indigo-300'
|
|
: 'text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700'"
|
|
>
|
|
<span class="fi" :class="'fi-' + flags[lang]"></span>
|
|
<span x-text="names[lang]"></span>
|
|
<svg x-show="currentLang === lang" class="w-4 h-4 ml-auto text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
|
|
</svg>
|
|
</button>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
|
|
{# Dark mode toggle #}
|
|
<button
|
|
@click="toggleDarkMode()"
|
|
class="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"
|
|
aria-label="{{ _('cms.platform.nav.toggle_dark_mode') }}"
|
|
>
|
|
<svg x-show="!dark" class="w-5 h-5 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path>
|
|
</svg>
|
|
<svg x-show="dark" class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
{# Mobile menu button #}
|
|
<div class="md:hidden">
|
|
<button
|
|
@click="mobileMenuOpen = !mobileMenuOpen"
|
|
class="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
aria-label="{{ _('cms.platform.nav.toggle_menu') }}"
|
|
>
|
|
<svg x-show="!mobileMenuOpen" class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
|
|
</svg>
|
|
<svg x-show="mobileMenuOpen" class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{# Mobile menu #}
|
|
<div x-show="mobileMenuOpen" x-cloak class="md:hidden py-4 border-t border-gray-200 dark:border-gray-700">
|
|
{% if header_pages %}
|
|
{% for page in header_pages %}
|
|
<a href="/{{ page.slug }}"
|
|
class="block px-4 py-2 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg">
|
|
{{ page.title }}
|
|
</a>
|
|
{% endfor %}
|
|
{% endif %}
|
|
</div>
|
|
</nav>
|
|
</header>
|
|
|
|
{# Main Content #}
|
|
<main class="min-h-screen">
|
|
{% block content %}{% endblock %}
|
|
</main>
|
|
|
|
{# Footer #}
|
|
<footer class="bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700 mt-16">
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-8">
|
|
|
|
{# Brand Column #}
|
|
<div class="col-span-1">
|
|
<div class="flex items-center space-x-3 mb-4">
|
|
<div class="w-8 h-8 rounded-lg bg-gradient-to-r from-indigo-600 to-purple-600 flex items-center justify-center">
|
|
<span class="text-white font-bold text-xl">W</span>
|
|
</div>
|
|
<span class="text-xl font-bold text-gray-900 dark:text-white">
|
|
Orion
|
|
</span>
|
|
</div>
|
|
<p class="text-gray-600 dark:text-gray-400 text-sm">
|
|
{{ _("cms.platform.footer.tagline") }}
|
|
</p>
|
|
</div>
|
|
|
|
{# Quick Links #}
|
|
<div>
|
|
<h4 class="font-semibold text-gray-900 dark:text-white mb-4">{{ _("cms.platform.footer.quick_links") }}</h4>
|
|
<ul class="space-y-2">
|
|
{% if footer_pages %}
|
|
{% for page in footer_pages %}
|
|
<li>
|
|
<a href="/{{ page.slug }}"
|
|
class="text-gray-600 dark:text-gray-400 hover:text-primary dark:hover:text-primary transition-colors">
|
|
{{ page.title }}
|
|
</a>
|
|
</li>
|
|
{% endfor %}
|
|
{% endif %}
|
|
</ul>
|
|
</div>
|
|
|
|
{# Platform Links #}
|
|
<div>
|
|
<h4 class="font-semibold text-gray-900 dark:text-white mb-4">{{ _("cms.platform.footer.platform") }}</h4>
|
|
<ul class="space-y-2">
|
|
<li>
|
|
<a href="/admin/login" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">
|
|
{{ _("cms.platform.nav.admin_login") }}
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/store/orion/login" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">
|
|
{{ _("cms.platform.nav.store_login") }}
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
{# Contact Info #}
|
|
<div>
|
|
<h4 class="font-semibold text-gray-900 dark:text-white mb-4">{{ _("cms.platform.footer.contact") }}</h4>
|
|
<ul class="space-y-2 text-gray-600 dark:text-gray-400 text-sm">
|
|
<li>support@marketplace.com</li>
|
|
<li>+1 (555) 123-4567</li>
|
|
<li>123 Business St, Suite 100</li>
|
|
<li>San Francisco, CA 94102</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
{# Bottom Bar #}
|
|
<div class="mt-12 pt-8 border-t border-gray-200 dark:border-gray-700">
|
|
<div class="flex flex-col md:flex-row justify-between items-center">
|
|
<p class="text-gray-600 dark:text-gray-400 text-sm">
|
|
{{ _("cms.platform.footer.copyright", year=2025) }}
|
|
</p>
|
|
<div class="flex space-x-6 mt-4 md:mt-0">
|
|
{% if legal_pages %}
|
|
{% for page in legal_pages %}
|
|
<a href="/{{ page.slug }}" class="text-gray-600 dark:text-gray-400 hover:text-primary text-sm transition-colors">
|
|
{{ page.title }}
|
|
</a>
|
|
{% endfor %}
|
|
{% else %}
|
|
{# Fallback to hardcoded links if no CMS pages #}
|
|
<a href="/privacy" class="text-gray-600 dark:text-gray-400 hover:text-primary text-sm transition-colors">
|
|
{{ _("cms.platform.footer.privacy") }}
|
|
</a>
|
|
<a href="/terms" class="text-gray-600 dark:text-gray-400 hover:text-primary text-sm transition-colors">
|
|
{{ _("cms.platform.footer.terms") }}
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
{# Scripts #}
|
|
<!-- Alpine.js for interactivity -->
|
|
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.13.3/dist/cdn.min.js"></script>
|
|
|
|
<!-- Platform layout data -->
|
|
<script>
|
|
function platformLayoutData() {
|
|
return {
|
|
// Dark mode
|
|
dark: localStorage.getItem('darkMode') === 'true',
|
|
|
|
// Mobile menu
|
|
mobileMenuOpen: false,
|
|
|
|
// Initialize
|
|
init() {
|
|
// Apply dark mode on load
|
|
if (this.dark) {
|
|
document.documentElement.classList.add('dark');
|
|
}
|
|
},
|
|
|
|
// Toggle dark mode
|
|
toggleDarkMode() {
|
|
this.dark = !this.dark;
|
|
localStorage.setItem('darkMode', this.dark);
|
|
|
|
if (this.dark) {
|
|
document.documentElement.classList.add('dark');
|
|
} else {
|
|
document.documentElement.classList.remove('dark');
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
// Language selector for platform pages
|
|
function platformLanguageSelector() {
|
|
return {
|
|
isOpen: false,
|
|
currentLang: '{{ current_language|default("en") }}',
|
|
languages: {{ SUPPORTED_LANGUAGES|default(['en', 'fr', 'de', 'lb'])|tojson }},
|
|
names: {
|
|
'en': 'English',
|
|
'fr': 'Français',
|
|
'de': 'Deutsch',
|
|
'lb': 'Lëtzebuergesch'
|
|
},
|
|
flags: {
|
|
'en': 'gb',
|
|
'fr': 'fr',
|
|
'de': 'de',
|
|
'lb': 'lu'
|
|
},
|
|
async setLanguage(lang) {
|
|
if (lang === this.currentLang) {
|
|
this.isOpen = false;
|
|
return;
|
|
}
|
|
try {
|
|
const response = await fetch('/api/v1/platform/language/set', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ language: lang })
|
|
});
|
|
if (response.ok) {
|
|
this.currentLang = lang;
|
|
window.location.reload();
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to set language:', error);
|
|
}
|
|
this.isOpen = false;
|
|
}
|
|
};
|
|
}
|
|
</script>
|
|
|
|
{% block extra_scripts %}{% endblock %}
|
|
</body>
|
|
</html>
|