wip: update frontend templates for Letzshop order management

- Add Letzshop order detail page template
- Update orders list template
- Update Letzshop orders tab with improved UI
- Add JavaScript for order confirmation flow

Note: Frontend needs alignment with new unified order schema.

🤖 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-19 21:18:48 +01:00
parent fceaba703e
commit 8e8d1d1ac0
6 changed files with 739 additions and 60 deletions

View File

@@ -49,6 +49,12 @@ function adminOrders() {
// Available vendors for filter dropdown
vendors: [],
// Selected vendor (for prominent display)
selectedVendor: null,
// Tom Select instance
vendorSelectInstance: null,
// Pagination
pagination: {
page: 1,
@@ -128,6 +134,9 @@ function adminOrders() {
}
window._adminOrdersInitialized = true;
// Initialize Tom Select for vendor filter
this.initVendorSelect();
// Load data in parallel
await Promise.all([
this.loadStats(),
@@ -138,6 +147,82 @@ function adminOrders() {
adminOrdersLog.info('Orders initialization complete');
},
/**
* Initialize Tom Select for vendor autocomplete
*/
initVendorSelect() {
const selectEl = this.$refs.vendorSelect;
if (!selectEl) {
adminOrdersLog.warn('Vendor select element not found');
return;
}
// Wait for Tom Select to be available
if (typeof TomSelect === 'undefined') {
adminOrdersLog.warn('TomSelect not loaded, retrying in 100ms');
setTimeout(() => this.initVendorSelect(), 100);
return;
}
this.vendorSelectInstance = new TomSelect(selectEl, {
valueField: 'id',
labelField: 'name',
searchField: ['name', 'vendor_code'],
placeholder: 'All vendors...',
allowEmptyOption: true,
load: async (query, callback) => {
try {
const response = await apiClient.get('/admin/vendors', {
search: query,
limit: 50
});
callback(response.vendors || []);
} catch (error) {
adminOrdersLog.error('Failed to search vendors:', error);
callback([]);
}
},
render: {
option: (data, escape) => {
return `<div class="flex items-center justify-between py-1">
<span>${escape(data.name)}</span>
<span class="text-xs text-gray-400 font-mono">${escape(data.vendor_code || '')}</span>
</div>`;
},
item: (data, escape) => {
return `<div>${escape(data.name)}</div>`;
}
},
onChange: (value) => {
if (value) {
const vendor = this.vendorSelectInstance.options[value];
this.selectedVendor = vendor;
this.filters.vendor_id = value;
} else {
this.selectedVendor = null;
this.filters.vendor_id = '';
}
this.pagination.page = 1;
this.loadOrders();
}
});
adminOrdersLog.info('Vendor select initialized');
},
/**
* Clear vendor filter
*/
clearVendorFilter() {
if (this.vendorSelectInstance) {
this.vendorSelectInstance.clear();
}
this.selectedVendor = null;
this.filters.vendor_id = '';
this.pagination.page = 1;
this.loadOrders();
},
/**
* Load order statistics
*/