Platform Settings: - Add PlatformSettings utility in init-alpine.js with 5-min cache - Add Display tab in /admin/settings for rows_per_page config - Integrate PlatformSettings.getRowsPerPage() in all paginated pages - Standardize default per_page to 20 across all admin pages - Add documentation at docs/frontend/shared/platform-settings.md Architecture Rules: - Add JS-010: enforce PlatformSettings usage for pagination - Add JS-011: enforce standard pagination structure - Add JS-012: detect double /api/v1 prefix in apiClient calls - Implement all rules in validate_architecture.py Vendor Filter (Tom Select): - Add vendor filter to marketplace-products, vendor-products, customers, inventory, and vendor-themes pages - Add selectedVendor display panel with clear button - Add localStorage persistence for vendor selection - Fix double /api/v1 prefix in vendor-selector.js Bug Fixes: - Remove duplicate PlatformSettings from utils.js - Fix customers.js pagination structure (page_size → per_page) - Fix code-quality-violations.js pagination structure 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
131 lines
5.5 KiB
HTML
131 lines
5.5 KiB
HTML
{# app/templates/admin/vendor-themes.html #}
|
|
{% extends "admin/base.html" %}
|
|
{% from 'shared/macros/headers.html' import page_header %}
|
|
{% from 'shared/macros/alerts.html' import loading_state, error_state %}
|
|
|
|
{% block title %}Vendor Themes{% endblock %}
|
|
|
|
{% block extra_head %}
|
|
<link href="https://cdn.jsdelivr.net/npm/tom-select@2.3.1/dist/css/tom-select.css" rel="stylesheet">
|
|
<style>
|
|
.ts-wrapper { width: 100%; }
|
|
.ts-control {
|
|
background-color: rgb(249 250 251) !important;
|
|
border-color: rgb(209 213 219) !important;
|
|
border-radius: 0.5rem !important;
|
|
padding: 0.5rem 0.75rem !important;
|
|
}
|
|
.dark .ts-control {
|
|
background-color: rgb(55 65 81) !important;
|
|
border-color: rgb(75 85 99) !important;
|
|
color: rgb(229 231 235) !important;
|
|
}
|
|
.ts-dropdown {
|
|
border-radius: 0.5rem !important;
|
|
border-color: rgb(209 213 219) !important;
|
|
}
|
|
.dark .ts-dropdown {
|
|
background-color: rgb(55 65 81) !important;
|
|
border-color: rgb(75 85 99) !important;
|
|
}
|
|
.dark .ts-dropdown .option {
|
|
color: rgb(229 231 235) !important;
|
|
}
|
|
.dark .ts-dropdown .option.active {
|
|
background-color: rgb(75 85 99) !important;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block alpine_data %}adminVendorThemes(){% endblock %}
|
|
|
|
{% block content %}
|
|
{{ page_header('Vendor Themes', subtitle='Customize vendor theme colors and branding') }}
|
|
|
|
<!-- Selected Vendor Display (when filtered) -->
|
|
<div x-show="selectedVendor" x-cloak class="mb-6">
|
|
<div class="px-4 py-3 bg-purple-50 dark:bg-purple-900/20 border border-purple-200 dark:border-purple-800 rounded-lg">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center gap-3">
|
|
<span x-html="$icon('color-swatch', 'w-6 h-6 text-purple-600')"></span>
|
|
<div>
|
|
<p class="text-sm font-medium text-purple-700 dark:text-purple-300">Filtered by Vendor</p>
|
|
<p class="text-lg font-semibold text-purple-900 dark:text-purple-100" x-text="selectedVendor?.name"></p>
|
|
</div>
|
|
</div>
|
|
<button
|
|
@click="clearVendorFilter()"
|
|
class="flex items-center gap-1 px-3 py-1.5 text-sm text-purple-700 dark:text-purple-300 bg-purple-100 dark:bg-purple-800 rounded-md hover:bg-purple-200 dark:hover:bg-purple-700 transition-colors"
|
|
>
|
|
<span x-html="$icon('x-mark', 'w-4 h-4')"></span>
|
|
Clear Filter
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Vendor Search/Filter -->
|
|
<div class="px-4 py-6 mb-6 bg-white rounded-lg shadow-md dark:bg-gray-800">
|
|
<h3 class="mb-4 text-lg font-semibold text-gray-700 dark:text-gray-200">
|
|
Search Vendor
|
|
</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
|
Search for a vendor to customize their theme
|
|
</p>
|
|
|
|
<div class="max-w-md">
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
|
Vendor
|
|
</label>
|
|
<select x-ref="vendorSelect" placeholder="Search vendor by name or code..."></select>
|
|
</div>
|
|
</div>
|
|
|
|
{{ loading_state('Loading vendors...') }}
|
|
|
|
{{ error_state('Error loading vendors') }}
|
|
|
|
<!-- Vendors List -->
|
|
<div x-show="!loading && filteredVendors.length > 0">
|
|
<div class="px-4 py-3 bg-white rounded-lg shadow-md dark:bg-gray-800">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="text-lg font-semibold text-gray-700 dark:text-gray-200">
|
|
<span x-text="selectedVendor ? 'Selected Vendor' : 'All Vendors'"></span>
|
|
<span class="text-sm font-normal text-gray-500 dark:text-gray-400" x-text="`(${filteredVendors.length})`"></span>
|
|
</h3>
|
|
</div>
|
|
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
|
<template x-for="vendor in filteredVendors" :key="vendor.vendor_code">
|
|
<a
|
|
:href="`/admin/vendors/${vendor.vendor_code}/theme`"
|
|
class="block p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:border-purple-500 dark:hover:border-purple-500 hover:shadow-md transition-all"
|
|
>
|
|
<div class="flex items-center justify-between mb-2">
|
|
<h4 class="font-semibold text-gray-700 dark:text-gray-200" x-text="vendor.name"></h4>
|
|
<span x-html="$icon('color-swatch', 'w-5 h-5 text-purple-600')"></span>
|
|
</div>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400" x-text="vendor.vendor_code"></p>
|
|
<div class="mt-3 flex items-center text-xs text-purple-600 dark:text-purple-400">
|
|
<span>Customize theme</span>
|
|
<span x-html="$icon('chevron-right', 'w-4 h-4 ml-1')"></span>
|
|
</div>
|
|
</a>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Empty State -->
|
|
<div x-show="!loading && filteredVendors.length === 0" class="text-center py-12">
|
|
<span x-html="$icon('shopping-bag', 'inline w-12 h-12 text-gray-400 mb-4')"></span>
|
|
<p class="text-gray-600 dark:text-gray-400">No vendors found</p>
|
|
</div>
|
|
|
|
{% endblock %}
|
|
|
|
{% block extra_scripts %}
|
|
<script src="https://cdn.jsdelivr.net/npm/tom-select@2.3.1/dist/js/tom-select.complete.min.js"></script>
|
|
<script src="{{ url_for('static', path='shared/js/vendor-selector.js') }}"></script>
|
|
<script src="{{ url_for('static', path='admin/js/vendor-themes.js') }}"></script>
|
|
{% endblock %}
|