/** * Simple UI Components for KSTools License Manager */ class Components { // Modal system static createModal({ title, content, size = 'md' }) { console.log('🔨 Creating modal with title:', title); const modalHtml = `
`; const container = document.getElementById('modalContainer') || document.body; console.log('📍 Modal container:', container); container.insertAdjacentHTML('beforeend', modalHtml); const modal = container.lastElementChild; console.log('✅ Modal created:', modal); return modal; } static showModal(modal) { if (modal) { console.log('👁️ Showing modal...', modal); modal.classList.add('active'); document.body.style.overflow = 'hidden'; console.log('✅ Modal shown with active class'); } else { console.error('❌ Cannot show modal: modal is null or undefined'); } } static closeModal(modal) { if (modal) { modal.classList.remove('active'); setTimeout(() => { modal.remove(); document.body.style.overflow = ''; }, 300); } } // Simple modal method for quick use static modal(title, content, size = 'md') { console.log('🎯 Components.modal called with title:', title); const modal = this.createModal({ title, content, size }); this.showModal(modal); return modal; } // License creation modal static createLicenseModal() { // 防止重複創建 const existingModal = document.querySelector('.modal-overlay'); if (existingModal) { console.log('⚠️ License modal already exists, returning existing one'); return existingModal; } const content = ` `; const modal = this.createModal({ title: '建立新授權', content: content, size: 'lg' }); // Setup form handler const form = modal.querySelector('#licenseForm'); form.addEventListener('submit', async (e) => { e.preventDefault(); await this.handleLicenseCreation(form, modal); }); this.showModal(modal); return modal; } static async handleLicenseCreation(form, modal) { const formData = new FormData(form); // 驗證必要欄位 const userName = formData.get('userName')?.trim(); const validDays = formData.get('validDays'); if (!userName) { Utils.showError('驗證失敗', '請輸入用戶名稱'); return; } if (!validDays) { Utils.showError('驗證失敗', '請選擇有效天數'); return; } const licenseData = { user_name: userName, user_email: formData.get('email')?.trim() || null, expires_days: parseInt(validDays), notes: formData.get('notes')?.trim() || null }; console.log('📝 License Creation Data:', licenseData); const submitBtn = form.querySelector('button[type="submit"]'); const originalContent = submitBtn.innerHTML; try { submitBtn.disabled = true; submitBtn.innerHTML = ' 建立中...'; console.log('🚀 Sending create license request...'); const response = await api.createLicense(licenseData); console.log('✅ Create license response:', response); if (response && response.success) { Utils.showSuccess('授權建立成功'); this.closeModal(modal); // Refresh current page if it has a refresh method if (window.currentPage && window.currentPage.refresh) { window.currentPage.refresh(); } } else { throw new Error(response?.message || '建立授權失敗'); } } catch (error) { console.error('❌ Create license error:', error); Utils.handleError(error, '建立授權時'); submitBtn.disabled = false; submitBtn.innerHTML = originalContent; } } // Chart creation helper static createChart(canvas, config) { if (!window.Chart) { console.error('Chart.js not loaded'); return null; } const ctx = canvas.getContext('2d'); // Default dark theme colors const defaultConfig = { plugins: { legend: { labels: { color: '#e6edf3', font: { size: 12 } } } }, scales: config.type !== 'doughnut' && config.type !== 'pie' ? { x: { ticks: { color: '#7d8590' }, grid: { color: '#30363d' } }, y: { ticks: { color: '#7d8590' }, grid: { color: '#30363d' } } } : undefined }; // Merge configs const finalConfig = { ...config, options: { ...defaultConfig, ...config.options, responsive: true, maintainAspectRatio: false } }; return new Chart(ctx, finalConfig); } // Confirmation dialog static confirm(title, message, onConfirm) { const confirmId = 'confirm_' + Date.now(); const content = `${message}