// Admin functionality JavaScript class AdminManager { constructor() { this.initializeEventListeners(); } initializeEventListeners() { // Export buttons document.addEventListener('click', (e) => { if (e.target.matches('[onclick*="exportData"]')) { e.preventDefault(); const onclick = e.target.getAttribute('onclick'); const matches = onclick.match(/exportData\('([^']+)',\s*'([^']+)'\)/); if (matches) { this.exportData(matches[1], matches[2]); } } }); // Calculate rankings button document.addEventListener('click', (e) => { if (e.target.matches('[onclick*="calculateMonthlyRankings"]')) { e.preventDefault(); this.calculateMonthlyRankings(); } }); } async exportData(type, format) { try { this.showLoading(true, `正在匯出${type === 'assessments' ? '評估資料' : 'STAR回饋'}...`); const url = `/api/export/${type}?format=${format}`; // Create a temporary link to download the file const link = document.createElement('a'); link.href = url; link.download = `${type}_${new Date().toISOString().split('T')[0]}.${format === 'excel' ? 'xlsx' : 'csv'}`; document.body.appendChild(link); link.click(); document.body.removeChild(link); this.showSuccess(`${type === 'assessments' ? '評估資料' : 'STAR回饋'}匯出成功`); } catch (error) { console.error('Export failed:', error); this.showError('匯出失敗: ' + error.message); } finally { this.showLoading(false); } } async calculateMonthlyRankings() { try { const year = document.getElementById('calc-year').value; const month = document.getElementById('calc-month').value; if (!year || !month) { this.showError('請選擇年份和月份'); return; } this.showLoading(true, '正在計算月度排名...'); const response = await fetch('/api/rankings/calculate', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ year: parseInt(year), month: parseInt(month) }) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const result = await response.json(); this.showSuccess(result.message); } catch (error) { console.error('Calculate rankings failed:', error); this.showError('排名計算失敗: ' + error.message); } finally { this.showLoading(false); } } showLoading(show, message = '處理中...') { // You can implement a more sophisticated loading indicator here if (show) { console.log('Loading:', message); } else { console.log('Loading finished'); } } showSuccess(message) { console.log('Success:', message); if (window.showSuccess) { window.showSuccess(message); } } showError(message) { console.error('Error:', message); if (window.showError) { window.showError(message); } } } // Data management utilities class DataManager { constructor() { this.initializeDataManagement(); } initializeDataManagement() { // Add any data management functionality here this.setupDataValidation(); } setupDataValidation() { // Validate data integrity this.validateDataIntegrity(); } async validateDataIntegrity() { try { // Check for orphaned records, missing references, etc. console.log('Validating data integrity...'); // You can add specific validation logic here } catch (error) { console.error('Data validation failed:', error); } } async getSystemStats() { try { const [assessments, feedbacks, employees] = await Promise.all([ fetch('/api/assessments?per_page=1').then(r => r.json()), fetch('/api/star-feedbacks?per_page=1').then(r => r.json()), fetch('/api/rankings/total?limit=1').then(r => r.json()) ]); return { totalAssessments: assessments.total || 0, totalFeedbacks: feedbacks.total || 0, totalEmployees: employees.rankings.length || 0 }; } catch (error) { console.error('Failed to get system stats:', error); return null; } } } // Export functionality class ExportManager { constructor() { this.supportedFormats = ['excel', 'csv']; } async exportAssessments(format = 'excel') { return this.exportData('assessments', format); } async exportStarFeedbacks(format = 'excel') { return this.exportData('star-feedbacks', format); } async exportData(type, format) { if (!this.supportedFormats.includes(format)) { throw new Error(`Unsupported format: ${format}`); } const url = `/api/export/${type}?format=${format}`; try { const response = await fetch(url); if (!response.ok) { throw new Error(`Export failed: ${response.status}`); } // Get filename from response headers or create default const contentDisposition = response.headers.get('Content-Disposition'); let filename = `${type}_${new Date().toISOString().split('T')[0]}.${format === 'excel' ? 'xlsx' : 'csv'}`; if (contentDisposition) { const filenameMatch = contentDisposition.match(/filename="(.+)"/); if (filenameMatch) { filename = filenameMatch[1]; } } // Create blob and download const blob = await response.blob(); this.downloadBlob(blob, filename); return filename; } catch (error) { console.error('Export failed:', error); throw error; } } downloadBlob(blob, filename) { const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); window.URL.revokeObjectURL(url); } } // Ranking calculation utilities class RankingCalculator { constructor() { this.initializeRankingCalculation(); } initializeRankingCalculation() { // Add any ranking calculation setup here } async calculateMonthlyRankings(year, month) { try { const response = await fetch('/api/rankings/calculate', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ year, month }) }); if (!response.ok) { throw new Error(`Calculation failed: ${response.status}`); } const result = await response.json(); return result; } catch (error) { console.error('Ranking calculation failed:', error); throw error; } } async getRankingHistory(year, month) { try { const response = await fetch(`/api/rankings/monthly?year=${year}&month=${month}`); if (!response.ok) { throw new Error(`Failed to get ranking history: ${response.status}`); } const result = await response.json(); return result; } catch (error) { console.error('Failed to get ranking history:', error); throw error; } } } // Initialize admin functionality when DOM is loaded document.addEventListener('DOMContentLoaded', function() { // Initialize admin manager window.adminManager = new AdminManager(); // Initialize data manager window.dataManager = new DataManager(); // Initialize export manager window.exportManager = new ExportManager(); // Initialize ranking calculator window.rankingCalculator = new RankingCalculator(); }); // Global functions for HTML onclick handlers function exportData(type, format) { if (window.exportManager) { window.exportManager.exportData(type, format); } } function calculateMonthlyRankings() { if (window.rankingCalculator) { const year = document.getElementById('calc-year').value; const month = document.getElementById('calc-month').value; if (!year || !month) { if (window.showError) { window.showError('請選擇年份和月份'); } return; } window.rankingCalculator.calculateMonthlyRankings(parseInt(year), parseInt(month)) .then(result => { if (window.showSuccess) { window.showSuccess(result.message); } }) .catch(error => { if (window.showError) { window.showError('排名計算失敗: ' + error.message); } }); } }