// static/admin/js/vendor-product-detail.js /** * Admin vendor product detail page logic * View and manage individual vendor catalog products */ const adminVendorProductDetailLog = window.LogConfig.loggers.adminVendorProductDetail || window.LogConfig.createLogger('adminVendorProductDetail', false); adminVendorProductDetailLog.info('Loading...'); function adminVendorProductDetail() { adminVendorProductDetailLog.info('adminVendorProductDetail() called'); // Extract product ID from URL const pathParts = window.location.pathname.split('/'); const productId = parseInt(pathParts[pathParts.length - 1]); return { // Inherit base layout state ...data(), // Set page identifier currentPage: 'vendor-products', // Product ID from URL productId: productId, // Loading states loading: true, error: '', // Product data product: null, // Modals showRemoveModal: false, removing: false, async init() { adminVendorProductDetailLog.info('Vendor Product Detail init() called, ID:', this.productId); // Guard against multiple initialization if (window._adminVendorProductDetailInitialized) { adminVendorProductDetailLog.warn('Already initialized, skipping'); return; } window._adminVendorProductDetailInitialized = true; // Load product data await this.loadProduct(); adminVendorProductDetailLog.info('Vendor Product Detail initialization complete'); }, /** * Load product details */ async loadProduct() { this.loading = true; this.error = ''; try { const response = await apiClient.get(`/admin/vendor-products/${this.productId}`); this.product = response; adminVendorProductDetailLog.info('Loaded product:', this.product.id); } catch (error) { adminVendorProductDetailLog.error('Failed to load product:', error); this.error = error.message || 'Failed to load product details'; } finally { this.loading = false; } }, /** * Open edit modal (placeholder for future implementation) */ openEditModal() { window.dispatchEvent(new CustomEvent('toast', { detail: { message: 'Edit functionality coming soon', type: 'info' } })); }, /** * Toggle active status */ async toggleActive() { // TODO: Implement PATCH endpoint for status update window.dispatchEvent(new CustomEvent('toast', { detail: { message: 'Status toggle functionality coming soon', type: 'info' } })); }, /** * Confirm remove */ confirmRemove() { this.showRemoveModal = true; }, /** * Execute remove */ async executeRemove() { this.removing = true; try { await apiClient.delete(`/admin/vendor-products/${this.productId}`); adminVendorProductDetailLog.info('Product removed:', this.productId); window.dispatchEvent(new CustomEvent('toast', { detail: { message: 'Product removed from catalog successfully', type: 'success' } })); // Redirect to vendor products list setTimeout(() => { window.location.href = '/admin/vendor-products'; }, 1000); } catch (error) { adminVendorProductDetailLog.error('Failed to remove product:', error); window.dispatchEvent(new CustomEvent('toast', { detail: { message: error.message || 'Failed to remove product', type: 'error' } })); } finally { this.removing = false; this.showRemoveModal = false; } }, /** * Format price for display */ formatPrice(price, currency = 'EUR') { if (price === null || price === undefined) return '-'; const numPrice = typeof price === 'string' ? parseFloat(price) : price; if (isNaN(numPrice)) return price; return new Intl.NumberFormat('de-DE', { style: 'currency', currency: currency || 'EUR' }).format(numPrice); }, /** * Format date for display */ formatDate(dateString) { if (!dateString) return '-'; try { const date = new Date(dateString); return date.toLocaleDateString('en-GB', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); } catch (e) { return dateString; } } }; }