fix: resolve homepage sections editor and rendering issues

- Fix sections editor not showing by converting isHomepage getter to property
- Add Alpine Collapse plugin for accordion animations
- Fix Quill editor content not syncing after page load
- Add platform dropdown to content page edit form
- Create shared templates config (app/templates_config.py) with i18n globals
  to make _() translation function available in Jinja2 macros
- Fix pricing template field names (monthly_price → price_monthly)
- Fix translation key (pricing.save_20 → pricing.save_months)
- Add tiers context to CMS homepage route for pricing section
- Fix architecture validation issues (language defaults, inline SVGs → $icon)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-23 20:03:13 +01:00
parent 8662fcd6da
commit 7e39bb0564
10 changed files with 161 additions and 34 deletions

View File

@@ -130,7 +130,10 @@
<!-- 7. SEVENTH: Vendor Selector (depends on Tom Select and API Client) -->
<script src="{{ url_for('static', path='shared/js/vendor-selector.js') }}"></script>
<!-- 8. EIGHTH: Alpine.js v3 with CDN fallback (with defer) -->
<!-- 8a. Alpine.js Collapse Plugin (must load before Alpine) -->
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/collapse@3.13.3/dist/cdn.min.js"></script>
<!-- 8b. Alpine.js v3 with CDN fallback (with defer) -->
<script>
(function() {
var script = document.createElement('script');

View File

@@ -91,24 +91,43 @@
</p>
</div>
<!-- Vendor ID (Platform vs Vendor-specific) -->
<!-- Platform Selection -->
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Page Type
Platform <span class="text-red-500">*</span>
</label>
<select
x-model="form.platform_id"
class="w-full px-3 py-2 text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:border-purple-500 dark:bg-gray-700"
:disabled="loadingPlatforms"
>
<template x-for="plat in (platforms || [])" :key="plat.id">
<option :value="plat.id" x-text="plat.name"></option>
</template>
</select>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
Which platform this page belongs to (e.g., OMS, Loyalty+)
</p>
</div>
<!-- Vendor Override (optional) -->
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Vendor Override
</label>
<select
x-model="form.vendor_id"
class="w-full px-3 py-2 text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:border-purple-500 dark:bg-gray-700"
:disabled="loadingVendors"
>
<option :value="null">Platform Default</option>
<option :value="null">None (Platform Default)</option>
<template x-for="vendor in (vendors || [])" :key="vendor.id">
<option :value="vendor.id" x-text="vendor.name"></option>
</template>
</select>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
<span x-show="!form.vendor_id">Platform defaults are shown to all vendors</span>
<span x-show="form.vendor_id">This page will only be visible for the selected vendor</span>
<span x-show="!form.vendor_id">This is a platform-wide default page</span>
<span x-show="form.vendor_id">This page overrides the default for selected vendor only</span>
</p>
</div>
</div>
@@ -222,9 +241,7 @@
<input type="checkbox" x-model="sections.hero.enabled" class="w-4 h-4 text-purple-600 rounded">
<span class="ml-2 text-sm text-gray-500">Enabled</span>
</label>
<svg :class="openSection === 'hero' ? 'rotate-180' : ''" class="w-5 h-5 text-gray-400 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
<span :class="openSection === 'hero' ? 'rotate-180' : ''" class="transition-transform" x-html="$icon('chevron-down', 'w-5 h-5 text-gray-400')"></span>
</div>
</button>
<div x-show="openSection === 'hero'" x-collapse class="p-4 space-y-4 border-t border-gray-200 dark:border-gray-700">
@@ -307,9 +324,7 @@
<input type="checkbox" x-model="sections.features.enabled" class="w-4 h-4 text-purple-600 rounded">
<span class="ml-2 text-sm text-gray-500">Enabled</span>
</label>
<svg :class="openSection === 'features' ? 'rotate-180' : ''" class="w-5 h-5 text-gray-400 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
<span :class="openSection === 'features' ? 'rotate-180' : ''" class="transition-transform" x-html="$icon('chevron-down', 'w-5 h-5 text-gray-400')"></span>
</div>
</button>
<div x-show="openSection === 'features'" x-collapse class="p-4 space-y-4 border-t border-gray-200 dark:border-gray-700">
@@ -378,9 +393,7 @@
<input type="checkbox" x-model="sections.pricing.enabled" class="w-4 h-4 text-purple-600 rounded">
<span class="ml-2 text-sm text-gray-500">Enabled</span>
</label>
<svg :class="openSection === 'pricing' ? 'rotate-180' : ''" class="w-5 h-5 text-gray-400 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
<span :class="openSection === 'pricing' ? 'rotate-180' : ''" class="transition-transform" x-html="$icon('chevron-down', 'w-5 h-5 text-gray-400')"></span>
</div>
</button>
<div x-show="openSection === 'pricing'" x-collapse class="p-4 space-y-4 border-t border-gray-200 dark:border-gray-700">
@@ -418,9 +431,7 @@
<input type="checkbox" x-model="sections.cta.enabled" class="w-4 h-4 text-purple-600 rounded">
<span class="ml-2 text-sm text-gray-500">Enabled</span>
</label>
<svg :class="openSection === 'cta' ? 'rotate-180' : ''" class="w-5 h-5 text-gray-400 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
<span :class="openSection === 'cta' ? 'rotate-180' : ''" class="transition-transform" x-html="$icon('chevron-down', 'w-5 h-5 text-gray-400')"></span>
</div>
</button>
<div x-show="openSection === 'cta'" x-collapse class="p-4 space-y-4 border-t border-gray-200 dark:border-gray-700">