// static/admin/js/components.js // ✅ Use centralized logger - ONE LINE! // Create custom logger for components page const componentsLog = window.LogConfig.createLogger('COMPONENTS'); /** * Components Library Alpine.js Component * UI components reference with live examples */ function adminComponents() { return { // ✅ CRITICAL: Inherit base layout functionality ...data(), // ✅ CRITICAL: Set page identifier currentPage: 'components', // Active section for navigation activeSection: 'forms', // Component sections sections: [ { id: 'ecommerce', name: 'E-commerce', icon: 'shopping-cart' }, { id: 'macros', name: 'Macros', icon: 'template' }, { id: 'pagination', name: 'Pagination', icon: 'dots-horizontal' }, { id: 'tabs', name: 'Tabs', icon: 'view-boards' }, { id: 'forms', name: 'Forms', icon: 'clipboard-list' }, { id: 'buttons', name: 'Buttons', icon: 'cursor-click' }, { id: 'cards', name: 'Cards', icon: 'collection' }, { id: 'badges', name: 'Badges', icon: 'tag' }, { id: 'tables', name: 'Tables', icon: 'table' }, { id: 'modals', name: 'Modals', icon: 'view-grid-add' }, { id: 'alerts', name: 'Alerts', icon: 'exclamation' }, { id: 'charts', name: 'Charts', icon: 'chart-pie' } ], // Tab demo state demoActiveTab: 'tab1', // Number stepper demo state demoQuantitySm: 3, demoQuantityMd: 5, demoQuantityLg: 500, // E-commerce demo state demoProducts: [ { id: 1, name: 'Premium Wireless Headphones', url: '#', image_url: 'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=300&h=300&fit=crop', price: 149.99, sale_price: 119.99, rating: 4.5, review_count: 127, stock: 15, is_new: false, in_wishlist: false }, { id: 2, name: 'Smart Watch Pro', url: '#', image_url: 'https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=300&h=300&fit=crop', price: 299.99, sale_price: null, rating: 4.8, review_count: 89, stock: 8, is_new: true, in_wishlist: true }, { id: 3, name: 'Portable Bluetooth Speaker', url: '#', image_url: 'https://images.unsplash.com/photo-1608043152269-423dbba4e7e1?w=300&h=300&fit=crop', price: 79.99, sale_price: null, rating: 4.2, review_count: 45, stock: 0, is_new: false, in_wishlist: false } ], demoCart: { items: [ { id: 1, product_id: 1, name: 'Premium Wireless Headphones', url: '#', image_url: 'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=300&h=300&fit=crop', price: 119.99, quantity: 1, variant_name: 'Black', max_quantity: 15 }, { id: 2, product_id: 2, name: 'Smart Watch Pro', url: '#', image_url: 'https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=300&h=300&fit=crop', price: 299.99, quantity: 2, variant_name: 'Silver', max_quantity: 8 } ], item_count: 3, subtotal: 719.97, discount: 0, shipping: 0, tax: 0, total: 719.97, promo_code: null }, showDemoCart: false, demoQuantity: 1, addingToCart: false, addedToCart: false, // E-commerce demo methods demoAddToCart(product) { this.addingToCart = true; setTimeout(() => { this.addingToCart = false; this.addedToCart = true; setTimeout(() => { this.addedToCart = false; }, 2000); if (typeof Utils !== 'undefined' && Utils.showToast) { Utils.showToast('Added to cart!', 'success'); } }, 800); }, demoToggleWishlist(product) { product.in_wishlist = !product.in_wishlist; const action = product.in_wishlist ? 'Added to' : 'Removed from'; if (typeof Utils !== 'undefined' && Utils.showToast) { Utils.showToast(`${action} wishlist`, 'success'); } }, demoRemoveFromCart(itemId) { this.demoCart.items = this.demoCart.items.filter(i => i.id !== itemId); this.demoCart.item_count = this.demoCart.items.reduce((sum, i) => sum + i.quantity, 0); this.demoCart.subtotal = this.demoCart.items.reduce((sum, i) => sum + (i.price * i.quantity), 0); this.demoCart.total = this.demoCart.subtotal; }, // Sample form data for examples exampleForm: { textInput: 'Sample text', email: 'user@example.com', textarea: 'Sample description text...', select: 'option1', checkbox: true, radio: 'option1', disabled: 'Read-only value' }, // Sample errors for validation examples exampleErrors: { email: 'Please enter a valid email address', required: 'This field is required' }, // Modal state variables for examples showExampleModal: false, showFormModal: false, // ✅ CRITICAL: Proper initialization with guard async init() { componentsLog.info('=== COMPONENTS PAGE INITIALIZING ==='); // Prevent multiple initializations if (window._componentsInitialized) { componentsLog.warn('Components page already initialized, skipping...'); return; } window._componentsInitialized = true; // Set active section from URL hash if present this.setActiveSectionFromHash(); // Listen for hash changes window.addEventListener('hashchange', () => { this.setActiveSectionFromHash(); }); // Initialize charts after DOM is ready this.$nextTick(() => { this.initializeCharts(); }); componentsLog.info('=== COMPONENTS PAGE INITIALIZATION COMPLETE ==='); }, /** * Set active section from URL hash */ setActiveSectionFromHash() { const hash = window.location.hash.replace('#', ''); if (hash && this.sections.find(s => s.id === hash)) { this.activeSection = hash; componentsLog.debug('Set active section from hash:', hash); } }, /** * Navigate to section */ goToSection(sectionId) { componentsLog.info('Navigating to section:', sectionId); this.activeSection = sectionId; window.location.hash = sectionId; // Smooth scroll to section const element = document.getElementById(sectionId); if (element) { element.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }, /** * Check if section is active */ isSectionActive(sectionId) { return this.activeSection === sectionId; }, /** * Copy code to clipboard */ async copyCode(code) { try { await navigator.clipboard.writeText(code); // Use the global Utils.showToast function if (typeof Utils !== 'undefined' && Utils.showToast) { Utils.showToast('Code copied to clipboard!', 'success'); } else { componentsLog.warn('Utils.showToast not available'); } componentsLog.debug('Code copied to clipboard'); } catch (error) { window.LogConfig.logError(error, 'Copy Code'); if (typeof Utils !== 'undefined' && Utils.showToast) { Utils.showToast('Failed to copy code', 'error'); } } }, /** * Show toast example */ showToastExample(type) { const messages = { success: 'Operation completed successfully!', error: 'An error occurred!', warning: 'Please review your input.', info: 'Here is some information.' }; componentsLog.info('Showing toast example:', type); if (typeof Utils !== 'undefined' && Utils.showToast) { Utils.showToast(messages[type] || messages.info, type); } else { componentsLog.error('Utils.showToast not available'); alert(messages[type] || messages.info); // Fallback to alert } }, /** * Initialize Chart.js charts */ initializeCharts() { try { // Check if Chart.js is loaded if (typeof Chart === 'undefined') { componentsLog.warn('Chart.js not loaded, skipping chart initialization'); return; } componentsLog.info('Initializing charts...'); componentsLog.time('Chart Initialization'); // Pie Chart const pieCanvas = document.getElementById('examplePieChart'); if (pieCanvas) { const pieConfig = { type: 'doughnut', data: { datasets: [{ data: [33, 33, 33], backgroundColor: ['#0694a2', '#7e3af2', '#1c64f2'], label: 'Dataset 1', }], labels: ['Shoes', 'Shirts', 'Bags'], }, options: { responsive: true, cutoutPercentage: 80, legend: { display: false, }, }, }; new Chart(pieCanvas, pieConfig); componentsLog.debug('Pie chart initialized'); } // Line Chart const lineCanvas = document.getElementById('exampleLineChart'); if (lineCanvas) { const lineConfig = { type: 'line', data: { labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], datasets: [{ label: 'Organic', backgroundColor: '#0694a2', borderColor: '#0694a2', data: [43, 48, 40, 54, 67, 73, 70], fill: false, }, { label: 'Paid', fill: false, backgroundColor: '#7e3af2', borderColor: '#7e3af2', data: [24, 50, 64, 74, 52, 51, 65], }], }, options: { responsive: true, legend: { display: false, }, tooltips: { mode: 'index', intersect: false, }, hover: { mode: 'nearest', intersect: true, }, scales: { x: { display: true, scaleLabel: { display: true, labelString: 'Month', }, }, y: { display: true, scaleLabel: { display: true, labelString: 'Value', }, }, }, }, }; new Chart(lineCanvas, lineConfig); componentsLog.debug('Line chart initialized'); } // Bar Chart const barCanvas = document.getElementById('exampleBarChart'); if (barCanvas) { const barConfig = { type: 'bar', data: { labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], datasets: [{ label: 'Shoes', backgroundColor: '#0694a2', borderColor: '#0694a2', borderWidth: 1, data: [43, 48, 40, 54, 67, 73, 70], }, { label: 'Bags', backgroundColor: '#7e3af2', borderColor: '#7e3af2', borderWidth: 1, data: [24, 50, 64, 74, 52, 51, 65], }], }, options: { responsive: true, legend: { display: false, }, }, }; new Chart(barCanvas, barConfig); componentsLog.debug('Bar chart initialized'); } componentsLog.timeEnd('Chart Initialization'); componentsLog.info('All charts initialized successfully'); } catch (error) { window.LogConfig.logError(error, 'Initialize Charts'); } } }; } componentsLog.info('Components module loaded');