const POCKETBASE_URL = 'https://pocketbase.ccllc.pro';
const pb = new PocketBase(POCKETBASE_URL);
// Load auth from localStorage or cookies
try {
pb.authStore.loadFromCookie(document.cookie);
} catch (e) {
const storedToken = localStorage.getItem('pb_auth_token');
const storedModel = localStorage.getItem('pb_auth_model');
if (storedToken && storedModel) {
try {
pb.authStore.save(storedToken, JSON.parse(storedModel));
} catch (e2) {
console.error('Error loading auth:', e2);
}
}
}
let currentPage = 1;
const perPage = 50;
let allEmployees = [];
let currentFilter = 'all';
let currentSearch = '';
let currentEditingEmployeeId = null;
let quickReportEditor = null;
// Get auth token for API requests
function getAuthToken() {
// Try to get from PocketBase auth store first
if (pb.authStore.token) {
return pb.authStore.token;
}
// Fallback to localStorage
const storedToken = localStorage.getItem('pb_auth_token');
if (storedToken) {
// Also update the auth store with the token
const storedModel = localStorage.getItem('pb_auth_model');
if (storedModel) {
try {
pb.authStore.save(storedToken, JSON.parse(storedModel));
} catch (e) {
console.error('Error loading auth from localStorage:', e);
}
}
return storedToken;
}
return '';
}
// Show message
function showMessage(message, type = 'success') {
const container = document.getElementById('messageContainer');
const bgColor = type === 'success' ? 'bg-green-50 border-green-200 text-green-700' : 'bg-red-50 border-red-200 text-red-700';
container.innerHTML = `
${message}
`;
setTimeout(() => {
container.innerHTML = '';
}, 5000);
}
// Load employees
async function loadEmployees(page = 1) {
try {
const token = getAuthToken();
console.log('Loading employees, token present:', !!token);
if (!token) {
console.error('No auth token found');
window.location.href = '/index.html';
return;
}
const url = `/api/employees?page=${page}&perPage=${perPage}&sort=Last_Name`;
console.log('Fetching from:', url);
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${token}`,
},
});
console.log('Response status:', response.status);
if (response.status === 401) {
console.error('Unauthorized - redirecting to login');
window.location.href = '/index.html';
return;
}
if (!response.ok) {
const error = await response.json();
console.error('Error response:', error);
throw new Error(error.error || 'Failed to load employees');
}
const data = await response.json();
console.log('Successfully loaded employees:', data);
allEmployees = data.items;
applyFiltersAndSearch();
displayPagination(data);
currentPage = page;
} catch (error) {
console.error('Error loading employees:', error);
showMessage(error.message || 'Failed to load employees', 'error');
document.getElementById('employeesTableBody').innerHTML = `
| Error loading employees: ${error.message} |
`;
}
}
// Filter and search employees
function applyFiltersAndSearch() {
let filtered = [...allEmployees];
// Apply type filter
if (currentFilter === 'employee') {
filtered = filtered.filter(emp => emp.Type === 'Employee');
} else if (currentFilter === 'sub-contractor') {
filtered = filtered.filter(emp => emp.Type === 'Sub-Contractor');
}
// Apply search
if (currentSearch.trim()) {
const searchLower = currentSearch.toLowerCase().trim();
filtered = filtered.filter(emp => {
const firstName = (emp.First_Name || '').toLowerCase();
const lastName = (emp.Last_Name || '').toLowerCase();
const id = (emp.id || '').toLowerCase();
const fullName = `${firstName} ${lastName}`;
return firstName.includes(searchLower) ||
lastName.includes(searchLower) ||
fullName.includes(searchLower) ||
id.includes(searchLower);
});
}
// Sort by last name A to Z
filtered.sort((a, b) => {
const lastNameA = (a.Last_Name || '').toLowerCase();
const lastNameB = (b.Last_Name || '').toLowerCase();
if (lastNameA < lastNameB) return -1;
if (lastNameA > lastNameB) return 1;
// If last names are the same, sort by first name
const firstNameA = (a.First_Name || '').toLowerCase();
const firstNameB = (b.First_Name || '').toLowerCase();
if (firstNameA < firstNameB) return -1;
if (firstNameA > firstNameB) return 1;
return 0;
});
displayEmployees(filtered);
}
// Display employees in table
function displayEmployees(employees) {
const tbody = document.getElementById('employeesTableBody');
if (employees.length === 0) {
tbody.innerHTML = `
| No employees found |
`;
return;
}
tbody.innerHTML = employees.map(emp => `
| ${emp.id || '-'} |
${emp.First_Name || '-'} |
${emp.Last_Name || '-'} |
${emp.Type || '-'} |
|
`).join('');
}
// Update filter button styles
function updateFilterButtons() {
const allBtn = document.getElementById('filterAll');
const employeeBtn = document.getElementById('filterEmployee');
const subContractorBtn = document.getElementById('filterSubContractor');
// Reset all buttons
[allBtn, employeeBtn, subContractorBtn].forEach(btn => {
btn.classList.remove('bg-indigo-600', 'text-white', 'hover:bg-indigo-700');
btn.classList.add('bg-gray-200', 'text-gray-700', 'hover:bg-gray-300');
});
// Set active button
let activeBtn;
if (currentFilter === 'all') {
activeBtn = allBtn;
} else if (currentFilter === 'employee') {
activeBtn = employeeBtn;
} else if (currentFilter === 'sub-contractor') {
activeBtn = subContractorBtn;
}
if (activeBtn) {
activeBtn.classList.remove('bg-gray-200', 'text-gray-700', 'hover:bg-gray-300');
activeBtn.classList.add('bg-indigo-600', 'text-white', 'hover:bg-indigo-700');
}
}
// Display pagination
function displayPagination(data) {
const pagination = document.getElementById('pagination');
if (data.totalPages <= 1) {
pagination.innerHTML = `Total: ${data.totalItems} employees
`;
return;
}
pagination.innerHTML = `
Showing ${(data.page - 1) * data.perPage + 1} to ${Math.min(data.page * data.perPage, data.totalItems)} of ${data.totalItems} employees
Page ${data.page} of ${data.totalPages}
`;
}
// Open modal for adding employee
function openAddModal() {
currentEditingEmployeeId = null;
document.getElementById('modalTitle').textContent = 'Add Employee';
document.getElementById('employeeForm').reset();
document.getElementById('employeeId').value = '';
// Hide Reports tab for new employees
document.getElementById('employeeReportsTab').style.display = 'none';
// Show Employee Info tab
switchToEmployeeInfoTab();
document.getElementById('employeeModal').classList.remove('hidden');
}
// Switch to Employee Info tab
function switchToEmployeeInfoTab() {
document.getElementById('employeeInfoTab').classList.add('border-indigo-500', 'text-indigo-600');
document.getElementById('employeeInfoTab').classList.remove('border-transparent', 'text-gray-500');
document.getElementById('employeeReportsTab').classList.remove('border-indigo-500', 'text-indigo-600');
document.getElementById('employeeReportsTab').classList.add('border-transparent', 'text-gray-500');
document.getElementById('employeeInfoContent').classList.remove('hidden');
document.getElementById('employeeReportsContent').classList.add('hidden');
}
// Switch to Reports tab
function switchToReportsTab() {
document.getElementById('employeeReportsTab').classList.add('border-indigo-500', 'text-indigo-600');
document.getElementById('employeeReportsTab').classList.remove('border-transparent', 'text-gray-500');
document.getElementById('employeeInfoTab').classList.remove('border-indigo-500', 'text-indigo-600');
document.getElementById('employeeInfoTab').classList.add('border-transparent', 'text-gray-500');
document.getElementById('employeeInfoContent').classList.add('hidden');
document.getElementById('employeeReportsContent').classList.remove('hidden');
}
// Initialize quick report editor
function initQuickReportEditor() {
if (!quickReportEditor) {
const editorContainer = document.getElementById('quickReportEditor');
if (editorContainer && typeof Quill !== 'undefined') {
try {
quickReportEditor = new Quill('#quickReportEditor', {
theme: 'snow',
modules: {
toolbar: [
[{ 'header': [1, 2, 3, false] }],
['bold', 'italic', 'underline'],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
['link'],
['clean']
]
}
});
// Force text color to be dark
const style = document.createElement('style');
style.textContent = `
#quickReportEditor .ql-editor {
color: #1f2937 !important;
background-color: #ffffff !important;
}
#quickReportEditor .ql-editor.ql-blank::before {
color: #9ca3af !important;
}
#quickReportEditor .ql-editor p,
#quickReportEditor .ql-editor h1,
#quickReportEditor .ql-editor h2,
#quickReportEditor .ql-editor h3 {
color: #1f2937 !important;
}
`;
document.head.appendChild(style);
quickReportEditor.on('text-change', function() {
const htmlContent = quickReportEditor.root.innerHTML;
document.getElementById('quickReport').value = htmlContent;
});
} catch (error) {
console.error('Error initializing quick report editor:', error);
}
}
}
return quickReportEditor;
}
// Load employee reports
async function loadEmployeeReports(employeeId) {
try {
const token = getAuthToken();
const response = await fetch(`/api/reports?employee=${employeeId}&perPage=1000&sort=-Report_Date`, {
headers: {
'Authorization': `Bearer ${token}`,
},
});
if (!response.ok) {
throw new Error('Failed to load reports');
}
const data = await response.json();
displayEmployeeReports(data.items || []);
} catch (error) {
console.error('Error loading employee reports:', error);
document.getElementById('employeeReportsList').innerHTML = 'Failed to load reports
';
}
}
// Display employee reports in post board style
function displayEmployeeReports(reports) {
const container = document.getElementById('employeeReportsList');
if (reports.length === 0) {
container.innerHTML = 'No reports yet. Add one to get started!
';
return;
}
const reportsHtml = reports.map(report => {
// Format date and time (convert from UTC to local for display)
const reportDate = report.Report_Date
? new Date(report.Report_Date).toLocaleString(undefined, {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
timeZoneName: 'short'
})
: 'No date';
const sentimentColor = {
'Positive': 'bg-green-100 text-green-800',
'Negative': 'bg-red-100 text-red-800',
'Neutral': 'bg-gray-100 text-gray-800'
}[report.Centiment] || 'bg-gray-100 text-gray-800';
const reportText = report.Report || '';
// Collect all links and detect Voxer links
const links = [];
const isVoxerLink = (url) => {
if (!url) return false;
const lowerUrl = url.toLowerCase();
return lowerUrl.includes('voxer.com') || lowerUrl.includes('voxer');
};
if (report.Link_01) links.push({ num: 1, url: report.Link_01, isVoxer: isVoxerLink(report.Link_01) });
if (report.Link_02) links.push({ num: 2, url: report.Link_02, isVoxer: isVoxerLink(report.Link_02) });
if (report.Link_03) links.push({ num: 3, url: report.Link_03, isVoxer: isVoxerLink(report.Link_03) });
if (report.Link_04) links.push({ num: 4, url: report.Link_04, isVoxer: isVoxerLink(report.Link_04) });
if (report.Link_05) links.push({ num: 5, url: report.Link_05, isVoxer: isVoxerLink(report.Link_05) });
return `
📅 ${reportDate}
${report.Centiment ? `${escapeHtml(report.Centiment)}` : ''}
${report.Report || 'No content'}
${links.length > 0 ? `
` : ''}
`;
}).join('');
container.innerHTML = reportsHtml;
}
// Edit employee report
let currentEditingReportId = null;
window.editEmployeeReport = async function(reportId) {
try {
currentEditingReportId = reportId;
const token = getAuthToken();
const response = await fetch(`/api/reports/${reportId}`, {
headers: {
'Authorization': `Bearer ${token}`,
},
});
if (!response.ok) {
throw new Error('Failed to load report');
}
const report = await response.json();
// Populate the quick report form
initQuickReportEditor();
// Set rich text editor content
const reportContent = report.Report || '';
setTimeout(() => {
if (quickReportEditor) {
quickReportEditor.root.innerHTML = reportContent || '
';
document.getElementById('quickReport').value = reportContent;
}
}, 100);
document.getElementById('quickSentiment').value = report.Centiment || '';
// Format date and time for input field (convert from UTC to local)
if (report.Report_Date) {
const date = new Date(report.Report_Date);
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('quickReportDate').value = `${year}-${month}-${day}T${hours}:${minutes}`;
} else {
document.getElementById('quickReportDate').value = '';
}
// Set links
document.getElementById('quickLink01').value = report.Link_01 || '';
document.getElementById('quickLink02').value = report.Link_02 || '';
document.getElementById('quickLink03').value = report.Link_03 || '';
document.getElementById('quickLink04').value = report.Link_04 || '';
document.getElementById('quickLink05').value = report.Link_05 || '';
// Update form title
const formTitle = document.querySelector('#addReportForm h4');
if (formTitle) {
formTitle.textContent = 'Edit Report';
}
// Show the form
document.getElementById('addReportForm').classList.remove('hidden');
// Scroll to form
document.getElementById('addReportForm').scrollIntoView({ behavior: 'smooth', block: 'nearest' });
} catch (error) {
console.error('Error loading report:', error);
showMessage('Failed to load report', 'error');
}
};
// Delete employee report
window.deleteEmployeeReport = async function(reportId) {
if (!confirm('Are you sure you want to delete this report?')) {
return;
}
try {
const token = getAuthToken();
const response = await fetch(`/api/reports/${reportId}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
},
});
if (!response.ok) {
throw new Error('Failed to delete report');
}
// Reload reports
if (currentEditingEmployeeId) {
await loadEmployeeReports(currentEditingEmployeeId);
}
showMessage('Report deleted successfully', 'success');
} catch (error) {
console.error('Error deleting report:', error);
showMessage('Failed to delete report', 'error');
}
};
// Edit employee
async function editEmployee(id) {
try {
currentEditingEmployeeId = id;
const token = getAuthToken();
const response = await fetch(`/api/employees/${id}`, {
headers: {
'Authorization': `Bearer ${token}`,
},
});
if (!response.ok) {
throw new Error('Failed to load employee');
}
const employee = await response.json();
document.getElementById('modalTitle').textContent = 'Edit Employee';
document.getElementById('employeeId').value = employee.id || '';
document.getElementById('firstName').value = employee.First_Name || '';
document.getElementById('lastName').value = employee.Last_Name || '';
document.getElementById('email').value = employee.Email || '';
document.getElementById('phoneNumber').value = employee.Phone_Number || '';
document.getElementById('voxerId').value = employee.Voxer_ID || '';
document.getElementById('type').value = employee.Type || '';
// Show Reports tab button
document.getElementById('employeeReportsTab').style.display = 'block';
// Show Employee Info tab by default
switchToEmployeeInfoTab();
// Load employee reports
await loadEmployeeReports(id);
document.getElementById('employeeModal').classList.remove('hidden');
} catch (error) {
console.error('Error loading employee:', error);
showMessage('Failed to load employee', 'error');
}
}
// Delete employee
async function deleteEmployee(id) {
if (!confirm('Are you sure you want to delete this employee?')) {
return;
}
try {
const token = getAuthToken();
const response = await fetch(`/api/employees/${id}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
},
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'Failed to delete employee');
}
showMessage('Employee deleted successfully');
// Reset search and filter when reloading
currentSearch = '';
currentFilter = 'all';
const searchInput = document.getElementById('searchInput');
if (searchInput) {
searchInput.value = '';
}
updateFilterButtons();
loadEmployees(currentPage);
} catch (error) {
console.error('Error deleting employee:', error);
showMessage(error.message || 'Failed to delete employee', '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', () => {
// Initialize page (auth check, user display, logout)
initPage();
// Load employees on page load
loadEmployees();
// Add employee button
document.getElementById('addEmployeeBtn').addEventListener('click', openAddModal);
// Cancel button
document.getElementById('cancelBtn').addEventListener('click', () => {
document.getElementById('employeeModal').classList.add('hidden');
document.getElementById('addReportForm').classList.add('hidden');
if (quickReportEditor) {
quickReportEditor.setContents([]);
quickReportEditor.root.innerHTML = '
';
}
});
// Close modal button
const closeModalBtn = document.getElementById('closeEmployeeModal');
if (closeModalBtn) {
closeModalBtn.addEventListener('click', () => {
document.getElementById('employeeModal').classList.add('hidden');
document.getElementById('addReportForm').classList.add('hidden');
if (quickReportEditor) {
quickReportEditor.setContents([]);
quickReportEditor.root.innerHTML = '
';
}
});
}
// Tab switching
document.getElementById('employeeInfoTab').addEventListener('click', switchToEmployeeInfoTab);
document.getElementById('employeeReportsTab').addEventListener('click', switchToReportsTab);
// Add Report button
const addReportBtn = document.getElementById('addReportBtn');
if (addReportBtn) {
addReportBtn.addEventListener('click', () => {
currentEditingReportId = null;
initQuickReportEditor();
document.getElementById('addReportForm').classList.remove('hidden');
// Set current date/time as default
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
document.getElementById('quickReportDate').value = `${year}-${month}-${day}T${hours}:${minutes}`;
// Reset form title
const formTitle = document.querySelector('#addReportForm h4');
if (formTitle) {
formTitle.textContent = 'Add New Report';
}
});
}
// Cancel quick report
const cancelQuickReport = document.getElementById('cancelQuickReport');
if (cancelQuickReport) {
cancelQuickReport.addEventListener('click', () => {
document.getElementById('addReportForm').classList.add('hidden');
currentEditingReportId = null;
if (quickReportEditor) {
quickReportEditor.setContents([]);
quickReportEditor.root.innerHTML = '
';
}
document.getElementById('quickReportForm').reset();
// Clear all link fields
document.getElementById('quickLink01').value = '';
document.getElementById('quickLink02').value = '';
document.getElementById('quickLink03').value = '';
document.getElementById('quickLink04').value = '';
document.getElementById('quickLink05').value = '';
// Reset form title
const formTitle = document.querySelector('#addReportForm h4');
if (formTitle) {
formTitle.textContent = 'Add New Report';
}
});
}
// Quick report form submission
const quickReportForm = document.getElementById('quickReportForm');
if (quickReportForm) {
quickReportForm.addEventListener('submit', async (e) => {
e.preventDefault();
if (!currentEditingEmployeeId) {
showMessage('Please save the employee first', 'error');
return;
}
try {
const token = getAuthToken();
// Convert datetime-local to UTC ISO string
let reportDateUTC = undefined;
const reportDateValue = document.getElementById('quickReportDate').value;
if (reportDateValue) {
const localDate = new Date(reportDateValue);
reportDateUTC = localDate.toISOString();
}
const formData = {
Employee: currentEditingEmployeeId,
Report: document.getElementById('quickReport').value || undefined,
Centiment: document.getElementById('quickSentiment').value || undefined,
Report_Date: reportDateUTC,
Link_01: document.getElementById('quickLink01').value || undefined,
Link_02: document.getElementById('quickLink02').value || undefined,
Link_03: document.getElementById('quickLink03').value || undefined,
Link_04: document.getElementById('quickLink04').value || undefined,
Link_05: document.getElementById('quickLink05').value || undefined,
};
const url = currentEditingReportId ? `/api/reports/${currentEditingReportId}` : '/api/reports';
const method = currentEditingReportId ? '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 ${currentEditingReportId ? 'updated' : 'added'} successfully`, 'success');
document.getElementById('addReportForm').classList.add('hidden');
quickReportForm.reset();
currentEditingReportId = null;
if (quickReportEditor) {
quickReportEditor.setContents([]);
quickReportEditor.root.innerHTML = '
';
}
// Clear all link fields
document.getElementById('quickLink01').value = '';
document.getElementById('quickLink02').value = '';
document.getElementById('quickLink03').value = '';
document.getElementById('quickLink04').value = '';
document.getElementById('quickLink05').value = '';
// Update form title back to "Add New Report"
const formTitle = document.querySelector('#addReportForm h4');
if (formTitle) {
formTitle.textContent = 'Add New Report';
}
// Reload reports
await loadEmployeeReports(currentEditingEmployeeId);
} catch (error) {
console.error('Error saving report:', error);
showMessage(error.message || 'Failed to save report', 'error');
}
});
}
// Search input
const searchInput = document.getElementById('searchInput');
if (searchInput) {
searchInput.addEventListener('input', (e) => {
currentSearch = e.target.value;
applyFiltersAndSearch();
});
}
// Filter buttons
const filterAll = document.getElementById('filterAll');
const filterEmployee = document.getElementById('filterEmployee');
const filterSubContractor = document.getElementById('filterSubContractor');
if (filterAll) {
filterAll.addEventListener('click', () => {
currentFilter = 'all';
updateFilterButtons();
applyFiltersAndSearch();
});
}
if (filterEmployee) {
filterEmployee.addEventListener('click', () => {
currentFilter = 'employee';
updateFilterButtons();
applyFiltersAndSearch();
});
}
if (filterSubContractor) {
filterSubContractor.addEventListener('click', () => {
currentFilter = 'sub-contractor';
updateFilterButtons();
applyFiltersAndSearch();
});
}
// Initialize filter button styles
updateFilterButtons();
// Form submission
document.getElementById('employeeForm').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const employeeId = formData.get('id');
const data = {
First_Name: formData.get('First_Name') || '',
Last_Name: formData.get('Last_Name') || '',
Email: formData.get('Email') || '',
Phone_Number: formData.get('Phone_Number') || '',
Voxer_ID: formData.get('Voxer_ID') || '',
Type: formData.get('Type') || '',
};
// Note: ID is only needed in URL for updates, not in body
// For creates, ID is optional and auto-generated if not provided
try {
const token = getAuthToken();
const url = employeeId ? `/api/employees/${employeeId}` : '/api/employees';
const method = employeeId ? 'PATCH' : 'POST';
const response = await fetch(url, {
method: method,
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'Failed to save employee');
}
showMessage(`Employee ${employeeId ? 'updated' : 'created'} successfully`);
document.getElementById('employeeModal').classList.add('hidden');
// Reset search and filter when reloading
currentSearch = '';
currentFilter = 'all';
const searchInput = document.getElementById('searchInput');
if (searchInput) {
searchInput.value = '';
}
updateFilterButtons();
loadEmployees(currentPage);
} catch (error) {
console.error('Error saving employee:', error);
showMessage(error.message || 'Failed to save employee', 'error');
}
});
});
// Utility function to escape HTML
function escapeHtml(text) {
if (!text) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// Make functions globally available
window.editEmployee = editEmployee;
window.deleteEmployee = deleteEmployee;
window.loadEmployees = loadEmployees;