diff --git a/.architecture-rules/frontend.yaml b/.architecture-rules/frontend.yaml index 3ad91dce..4189a5a4 100644 --- a/.architecture-rules/frontend.yaml +++ b/.architecture-rules/frontend.yaml @@ -145,6 +145,143 @@ javascript_rules: exceptions: - "utils.js" + - id: "JS-010" + name: "Use PlatformSettings for pagination rows per page" + severity: "error" + description: | + All pages with tables MUST use window.PlatformSettings.getRowsPerPage() + to load the platform-configured rows per page setting. This ensures + consistent pagination behavior across the entire admin and vendor interface. + + The setting is configured at /admin/settings under the Display tab. + Settings are cached client-side for 5 minutes to minimize API calls. + + Required pattern in init() method: + async init() { + // Guard against multiple initialization + if (window._pageNameInitialized) return; + window._pageNameInitialized = true; + + // REQUIRED: Load platform settings for pagination + if (window.PlatformSettings) { + this.pagination.per_page = await window.PlatformSettings.getRowsPerPage(); + } + + await this.loadData(); + } + + WRONG (hardcoded pagination): + pagination: { + page: 1, + per_page: 50, // Hardcoded! + total: 0 + } + + RIGHT (platform settings): + pagination: { + page: 1, + per_page: 20, // Default, overridden by PlatformSettings + total: 0 + } + + async init() { + if (window.PlatformSettings) { + this.pagination.per_page = await window.PlatformSettings.getRowsPerPage(); + } + } + + Documentation: docs/frontend/shared/platform-settings.md + pattern: + file_pattern: "static/admin/js/**/*.js" + required_in_pages_with_pagination: + - "PlatformSettings\\.getRowsPerPage" + - "window\\.PlatformSettings" + exceptions: + - "init-alpine.js" + - "init-api-client.js" + - "settings.js" + + - id: "JS-011" + name: "Use standard pagination object structure" + severity: "error" + description: | + All pages with tables MUST use the standard nested pagination object + structure. This ensures compatibility with the pagination macro and + consistent behavior across all pages. + + REQUIRED structure: + pagination: { + page: 1, + per_page: 20, + total: 0, + pages: 0 + } + + WRONG (flat structure): + page: 1, + limit: 20, + total: 0, + skip: 0 + + WRONG (different property names): + pagination: { + currentPage: 1, + itemsPerPage: 20 + } + + Required computed properties: + - totalPages + - startIndex + - endIndex + - pageNumbers + + Required methods: + - previousPage() + - nextPage() + - goToPage(pageNum) + + Documentation: docs/frontend/shared/pagination.md + pattern: + file_pattern: "static/**/js/**/*.js" + required_in_pages_with_pagination: + - "pagination:" + - "pagination\\.page" + - "pagination\\.per_page" + anti_patterns_in_pagination_pages: + - "^\\s*page:\\s*\\d" + - "^\\s*limit:\\s*\\d" + - "^\\s*skip:\\s*" + exceptions: + - "init-alpine.js" + + - id: "JS-012" + name: "Do not include /api/v1 prefix in API endpoints" + severity: "error" + description: | + When using apiClient.get(), apiClient.post(), etc., do NOT include + the /api/v1 prefix in the endpoint path. The apiClient automatically + prepends this prefix. + + CORRECT: + apiClient.get('/admin/vendors') + apiClient.post('/admin/products') + const apiEndpoint = '/admin/vendors' + + WRONG (causes double prefix /api/v1/api/v1/...): + apiClient.get('/api/v1/admin/vendors') + const apiEndpoint = '/api/v1/admin/vendors' + + Exception: Direct fetch() calls without apiClient should use full path. + + Documentation: docs/frontend/shared/api-client.md + pattern: + file_pattern: "static/**/js/**/*.js" + anti_patterns: + - "apiClient\\.(get|post|put|delete|patch)\\s*\\(\\s*['\"`]/api/v1" + - "apiEndpoint.*=.*['\"`]/api/v1" + exceptions: + - "init-api-client.js" + # ============================================================================ # TEMPLATE RULES (Jinja2) # ============================================================================ diff --git a/app/templates/admin/customers.html b/app/templates/admin/customers.html index 0352e8a6..22c7702a 100644 --- a/app/templates/admin/customers.html +++ b/app/templates/admin/customers.html @@ -1,16 +1,87 @@ {# app/templates/admin/customers.html #} {% extends "admin/base.html" %} -{% from 'shared/macros/headers.html' import page_header %} +{% from 'shared/macros/headers.html' import page_header_flex, refresh_button %} {% from 'shared/macros/alerts.html' import loading_state, error_state %} {% from 'shared/macros/tables.html' import table_wrapper, table_header %} -{% from 'shared/macros/pagination.html' import pagination_full %} +{% from 'shared/macros/pagination.html' import pagination %} {% block title %}Customers{% endblock %} {% block alpine_data %}adminCustomers(){% endblock %} +{% block extra_head %} + + + +{% endblock %} + {% block content %} -{{ page_header('Customer Management') }} + +{% call page_header_flex(title='Customer Management', subtitle='Manage customers across all vendors') %} +
+ +
+ +
+ {{ refresh_button(loading_var='loading', onclick='resetAndLoad()', variant='secondary') }} +
+{% endcall %} + + +
+
+
+
+ +
+
+ + +
+
+ +
+
{{ loading_state('Loading customers...') }} @@ -109,17 +180,6 @@ - - @@ -235,11 +295,25 @@ - - {{ pagination_full(load_fn="loadCustomers()", item_label="customers") }} + + {{ pagination() }} {% endblock %} {% block extra_scripts %} + + {% endblock %} diff --git a/app/templates/admin/inventory.html b/app/templates/admin/inventory.html index d9a88553..6384039f 100644 --- a/app/templates/admin/inventory.html +++ b/app/templates/admin/inventory.html @@ -1,7 +1,7 @@ {# app/templates/admin/inventory.html #} {% extends "admin/base.html" %} {% from 'shared/macros/pagination.html' import pagination %} -{% from 'shared/macros/headers.html' import page_header %} +{% from 'shared/macros/headers.html' import page_header_flex, refresh_button %} {% from 'shared/macros/alerts.html' import loading_state, error_state %} {% from 'shared/macros/tables.html' import table_wrapper %} {% from 'shared/macros/modals.html' import modal_simple %} @@ -12,7 +12,38 @@ {% block alpine_data %}adminInventory(){% endblock %} {% block content %} -{{ page_header('Inventory', subtitle='Manage stock levels across all vendors') }} + +{% call page_header_flex(title='Inventory', subtitle='Manage stock levels across all vendors') %} +
+ + {{ vendor_selector( + ref_name='vendorSelect', + id='inventory-vendor-select', + placeholder='Filter by vendor...', + width='w-80' + ) }} + {{ refresh_button(loading_var='loading', onclick='refresh()', variant='secondary') }} +
+{% endcall %} + + +
+
+
+
+ +
+
+ + +
+
+ +
+
{{ loading_state('Loading inventory...') }} @@ -102,14 +133,6 @@
- - {{ vendor_selector( - ref_name='vendorSelect', - id='inventory-vendor-select', - placeholder='Filter by vendor...', - width='w-64' - ) }} - + +
+ {{ refresh_button(loading_var='loading', onclick='refresh()', variant='secondary') }} + +{% endcall %} + + +
+
+
+
+ +
+
+ + +
+
+ +
+
{{ loading_state('Loading products...') }} @@ -128,18 +199,6 @@ - - - - - - @@ -233,7 +282,7 @@

No marketplace products found

-

+

@@ -409,5 +458,19 @@ {% endblock %} {% block extra_scripts %} + + {% endblock %} diff --git a/app/templates/admin/settings.html b/app/templates/admin/settings.html index 010d5e8a..b7621a31 100644 --- a/app/templates/admin/settings.html +++ b/app/templates/admin/settings.html @@ -18,6 +18,7 @@ {% call tabs_nav() %} + {{ tab_button('display', 'Display', icon='view-grid') }} {{ tab_button('logging', 'Logging', icon='document-text') }} {{ tab_button('shipping', 'Shipping', icon='truck') }} {{ tab_button('system', 'System', icon='cog') }} @@ -25,6 +26,66 @@ {{ tab_button('notifications', 'Notifications', icon='bell') }} {% endcall %} + +
+
+

+ Display Configuration +

+

+ Configure how data is displayed across the admin interface. +

+ + +
+ +

+ Set the default number of rows shown in tables across the admin interface. +

+
+ +
+

+ This setting applies to: Orders, Products, Customers, Inventory, and other tables. +

+
+ + +
+
+ +
+

When does this take effect?

+

Changes to the rows per page setting will apply immediately to all admin tables when refreshed.

+
+
+
+ + +
+ +
+
+
+
diff --git a/app/templates/admin/vendor-products.html b/app/templates/admin/vendor-products.html index 24f3a562..1a7522cb 100644 --- a/app/templates/admin/vendor-products.html +++ b/app/templates/admin/vendor-products.html @@ -1,7 +1,7 @@ {# app/templates/admin/vendor-products.html #} {% extends "admin/base.html" %} {% from 'shared/macros/pagination.html' import pagination %} -{% from 'shared/macros/headers.html' import page_header %} +{% from 'shared/macros/headers.html' import page_header_flex, refresh_button %} {% from 'shared/macros/alerts.html' import loading_state, error_state %} {% from 'shared/macros/tables.html' import table_wrapper %} {% from 'shared/macros/modals.html' import modal_simple %} @@ -10,8 +10,79 @@ {% block alpine_data %}adminVendorProducts(){% endblock %} +{% block extra_head %} + + + +{% endblock %} + {% block content %} -{{ page_header('Vendor Products', subtitle='Browse vendor-specific product catalogs with override capability') }} + +{% call page_header_flex(title='Vendor Products', subtitle='Browse vendor-specific product catalogs with override capability') %} +
+ +
+ +
+ {{ refresh_button(loading_var='loading', onclick='refresh()', variant='secondary') }} +
+{% endcall %} + + +
+
+
+
+ +
+
+ + +
+
+ +
+
{{ loading_state('Loading products...') }} @@ -116,18 +187,6 @@
- - - - - -
@@ -326,5 +375,19 @@ {% endblock %} {% block extra_scripts %} + + {% endblock %} diff --git a/app/templates/admin/vendor-themes.html b/app/templates/admin/vendor-themes.html index 6fdd4a84..f627ba21 100644 --- a/app/templates/admin/vendor-themes.html +++ b/app/templates/admin/vendor-themes.html @@ -5,34 +5,79 @@ {% block title %}Vendor Themes{% endblock %} +{% block extra_head %} + + +{% endblock %} + {% block alpine_data %}adminVendorThemes(){% endblock %} {% block content %} {{ page_header('Vendor Themes', subtitle='Customize vendor theme colors and branding') }} - + +
+
+
+
+ +
+

Filtered by Vendor

+

+
+
+ +
+
+
+ +

- Select Vendor + Search Vendor

- Choose a vendor to customize their theme + Search for a vendor to customize their theme

- +
@@ -41,13 +86,16 @@ {{ error_state('Error loading vendors') }} -
+
-

- All Vendors -

+
+

+ + +

+
-