`;
tableBody.appendChild(row);
});
}
// Render pagination
function renderPagination() {
const container = document.getElementById('paginationContainer');
if (totalPages <= 1) {
container.innerHTML = '';
return;
}
let html = '
';
html += '
';
if (currentPage > 1) {
html += ``;
}
if (currentPage < totalPages) {
html += ``;
}
html += '
';
html += '
';
html += `
Page ${currentPage} of ${totalPages}
`;
html += '
';
if (currentPage > 1) {
html += ``;
}
if (currentPage < totalPages) {
html += ``;
}
html += '
';
container.innerHTML = html;
}
// Initialize rich text editor
function initRichTextEditor() {
if (!reportEditor) {
const editorContainer = document.getElementById('reportEditor');
if (editorContainer && typeof Quill !== 'undefined') {
try {
reportEditor = new Quill('#reportEditor', {
theme: 'snow',
modules: {
toolbar: [
[{ 'header': [1, 2, 3, false] }],
['bold', 'italic', 'underline', 'strike'],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'color': [] }, { 'background': [] }],
['link'],
['clean']
]
}
});
// Sync editor content with hidden textarea for form submission
reportEditor.on('text-change', function() {
const htmlContent = reportEditor.root.innerHTML;
const textarea = document.getElementById('Report');
if (textarea) {
textarea.value = htmlContent;
}
});
} catch (error) {
console.error('Error initializing rich text editor:', error);
}
}
}
return reportEditor;
}
// Open modal for add/edit
async function openModal(reportId = null) {
const modal = document.getElementById('reportModal');
const form = document.getElementById('reportForm');
const modalTitle = document.getElementById('modalTitle');
const reportIdInput = document.getElementById('reportId');
// Show modal first so editor container is visible
modal.classList.remove('hidden');
// Initialize rich text editor (with a small delay to ensure DOM is ready)
setTimeout(() => {
initRichTextEditor();
}, 50);
// Ensure employees are loaded
if (employeesList.length === 0) {
await loadEmployees();
}
if (reportId) {
modalTitle.textContent = 'Edit Employee Report';
reportIdInput.value = reportId;
await loadReportForEdit(reportId);
} else {
modalTitle.textContent = 'Add Employee Report';
reportIdInput.value = '';
form.reset();
// Clear the rich text editor after it's initialized
setTimeout(() => {
if (reportEditor) {
reportEditor.setContents([]);
reportEditor.root.innerHTML = '
';
document.getElementById('Report').value = '';
}
}, 100);
}
}
// Load report data for editing
async function loadReportForEdit(id) {
try {
const token = getAuthToken();
const response = await fetch(`${API_BASE}/${id}`, {
headers: {
'Authorization': `Bearer ${token}`,
},
});
if (!response.ok) {
throw new Error('Failed to load report');
}
const report = await response.json();
document.getElementById('Employee').value = report.Employee || '';
// Set rich text editor content
const reportContent = report.Report || '';
if (reportEditor) {
// Set the HTML content in the editor
reportEditor.root.innerHTML = reportContent || '
';
document.getElementById('Report').value = reportContent;
} else {
// Editor not initialized yet, try again after a short delay
setTimeout(() => {
if (reportEditor) {
reportEditor.root.innerHTML = reportContent || '
';
document.getElementById('Report').value = reportContent;
} else {
document.getElementById('Report').value = reportContent;
}
}, 150);
}
document.getElementById('Centiment').value = report.Centiment || '';
// Format date and time for input field (YYYY-MM-DDTHH:mm) - convert from UTC to local
if (report.Report_Date) {
const date = new Date(report.Report_Date);
// Convert UTC to local time for display
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
document.getElementById('Report_Date').value = `${year}-${month}-${day}T${hours}:${minutes}`;
} else {
document.getElementById('Report_Date').value = '';
}
document.getElementById('Link_01').value = report.Link_01 || '';
document.getElementById('Link_02').value = report.Link_02 || '';
document.getElementById('Link_03').value = report.Link_03 || '';
document.getElementById('Link_04').value = report.Link_04 || '';
document.getElementById('Link_05').value = report.Link_05 || '';
} catch (error) {
console.error('Error loading report:', error);
showMessage('Failed to load report data.', 'error');
}
}
// Edit report
window.editReport = function(id) {
openModal(id);
};
// Delete report
window.deleteReport = async function(id) {
if (!confirm('Are you sure you want to delete this report?')) {
return;
}
try {
const token = getAuthToken();
const response = await fetch(`${API_BASE}/${id}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
},
});
if (!response.ok) {
throw new Error('Failed to delete report');
}
showMessage('Report deleted successfully.', 'success');
loadReports(currentPage);
} catch (error) {
console.error('Error deleting report:', error);
showMessage('Failed to delete report.', 'error');
}
};
// Initialize page - check auth and display user info
async function initPage() {
// First, ensure we have the token loaded from localStorage if not in auth store
const token = getAuthToken();
if (!token) {
// No token at all, redirect to login
console.log('No auth token found, redirecting to login');
window.location.href = '/index.html';
return;
}
// Check if auth store is valid, if not try to refresh
if (!pb.authStore.isValid) {
try {
// Try to refresh the token
await pb.collection('users').authRefresh();
// Update localStorage after refresh
if (pb.authStore.token && pb.authStore.model) {
localStorage.setItem('pb_auth_token', pb.authStore.token);
localStorage.setItem('pb_auth_model', JSON.stringify(pb.authStore.model));
}
} catch (e) {
console.error('Token refresh failed:', e);
// If refresh fails but we have a token, still try to continue
// The API will validate it
if (!pb.authStore.token) {
pb.authStore.clear();
localStorage.removeItem('pb_auth_token');
localStorage.removeItem('pb_auth_model');
window.location.href = '/index.html';
return;
}
}
}
// Display user information
const user = pb.authStore.model;
if (user) {
const userEmailElement = document.getElementById('userEmail');
if (userEmailElement) {
userEmailElement.textContent = user.email || 'User';
}
} else {
// Try to get user from localStorage
const storedModel = localStorage.getItem('pb_auth_model');
if (storedModel) {
try {
const userData = JSON.parse(storedModel);
const userEmailElement = document.getElementById('userEmail');
if (userEmailElement) {
userEmailElement.textContent = userData.email || 'User';
}
} catch (e) {
console.error('Error parsing stored user model:', e);
}
}
}
// Handle logout button
const logoutButton = document.getElementById('logoutButton');
if (logoutButton) {
logoutButton.addEventListener('click', async () => {
try {
await pb.authStore.clear();
localStorage.removeItem('pb_auth_token');
localStorage.removeItem('pb_auth_model');
window.location.href = '/index.html';
} catch (error) {
console.error('Logout error:', error);
pb.authStore.clear();
localStorage.removeItem('pb_auth_token');
localStorage.removeItem('pb_auth_model');
window.location.href = '/index.html';
}
});
}
}
// Handle form submission
document.addEventListener('DOMContentLoaded', async () => {
// Initialize page (auth check, user display, logout)
await initPage();
const form = document.getElementById('reportForm');
const modal = document.getElementById('reportModal');
const closeModal = document.getElementById('closeModal');
const cancelButton = document.getElementById('cancelButton');
const addReportButton = document.getElementById('addReportButton');
const addReportButtonEmpty = document.getElementById('addReportButtonEmpty');
// Load reports on page load
loadReports();
// Open modal handlers
if (addReportButton) {
addReportButton.addEventListener('click', () => openModal());
}
if (addReportButtonEmpty) {
addReportButtonEmpty.addEventListener('click', () => openModal());
}
// Close modal handlers
if (closeModal) {
closeModal.addEventListener('click', () => {
modal.classList.add('hidden');
});
}
if (cancelButton) {
cancelButton.addEventListener('click', () => {
modal.classList.add('hidden');
});
}
// Form submission
if (form) {
form.addEventListener('submit', async (e) => {
e.preventDefault();
const reportId = document.getElementById('reportId').value;
// Convert datetime-local to UTC ISO string
let reportDateUTC = undefined;
const reportDateValue = document.getElementById('Report_Date').value;
if (reportDateValue) {
const localDate = new Date(reportDateValue);
reportDateUTC = localDate.toISOString();
}
const formData = {
Employee: document.getElementById('Employee').value || undefined,
Report: document.getElementById('Report').value || undefined,
Centiment: document.getElementById('Centiment').value || undefined,
Report_Date: reportDateUTC,
Link_01: document.getElementById('Link_01').value || undefined,
Link_02: document.getElementById('Link_02').value || undefined,
Link_03: document.getElementById('Link_03').value || undefined,
Link_04: document.getElementById('Link_04').value || undefined,
Link_05: document.getElementById('Link_05').value || undefined,
};
try {
const token = getAuthToken();
const url = reportId ? `${API_BASE}/${reportId}` : API_BASE;
const method = reportId ? 'PATCH' : 'POST';
const response = await fetch(url, {
method,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify(formData),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'Failed to save report');
}
showMessage(`Report ${reportId ? 'updated' : 'created'} successfully.`, 'success');
modal.classList.add('hidden');
loadReports(reportId ? currentPage : 1);
} catch (error) {
console.error('Error saving report:', error);
showMessage(error.message || 'Failed to save report.', 'error');
}
});
}
// Load employees when page loads
loadEmployees();
});
// Utility function to escape HTML
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}