325 lines
10 KiB
JavaScript
325 lines
10 KiB
JavaScript
// 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);
|
|
}
|
|
});
|
|
}
|
|
}
|