@@ -85,6 +85,20 @@
Manage job notes and reports
View Notes →
+
+
+
diff --git a/employees.html b/employees.html
new file mode 100644
index 0000000..639bd75
--- /dev/null
+++ b/employees.html
@@ -0,0 +1,445 @@
+
+
+
+
+
+
Job Tracking - Employees
+
+
+
+
+
+
+
+
+
+
+
+
+
Employees
+
Manage employee records
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | First Name |
+ Last Name |
+ Phone |
+ Email |
+ Voxer ID |
+ Status |
+ Actions |
+
+
+
+
+ | Loading... |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Add Employee
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/js/employee-reports.js b/js/employee-reports.js
new file mode 100644
index 0000000..55d9641
--- /dev/null
+++ b/js/employee-reports.js
@@ -0,0 +1,264 @@
+// Employee Reports CRUD operations
+
+const reportsCollectionName = 'Employee_Reports';
+window.currentEmployeeId = null;
+
+/**
+ * Load reports for a specific employee
+ */
+async function loadEmployeeReports(employeeId) {
+ try {
+ if (!employeeId) {
+ document.getElementById('reportsList').innerHTML = '
No employee selected
';
+ return;
+ }
+
+ window.currentEmployeeId = employeeId;
+
+ // Filter reports by id matching the employee id (Employee_Records id)
+ // The id field in Employee_Reports links to Employee_Records id
+ const result = await pb.collection(reportsCollectionName).getList(1, 100, {
+ filter: `id = "${employeeId}"`,
+ sort: '-entered_date',
+ });
+
+ displayReports(result.items);
+ } catch (error) {
+ console.error('Error loading reports:', error);
+ document.getElementById('reportsList').innerHTML = '
Error loading reports. Please try again.
';
+ }
+}
+
+/**
+ * Display reports in the reports list
+ */
+function displayReports(reports) {
+ const container = document.getElementById('reportsList');
+ if (!container) return;
+
+ if (!reports || reports.length === 0) {
+ container.innerHTML = '
No reports found. Click "Add Report" to create one.
';
+ return;
+ }
+
+ container.innerHTML = reports.map(report => {
+ const enteredDate = report.entered_date
+ ? new Date(report.entered_date).toLocaleDateString()
+ : '-';
+
+ return `
+
+
+
+
+ ${report.entered_date ? `
+ ${escapeHtml(enteredDate)}
+ ` : ''}
+ ${report.entered_by ? `
+ Entered by: ${escapeHtml(report.entered_by)}
+ ` : ''}
+ ${report.row ? `
+ Row: ${escapeHtml(report.row)}
+ ` : ''}
+
+ ${report.report ? `
+
${escapeHtml(report.report)}
+ ` : '
No report content
'}
+ ${report.id_number ? `
+
ID Number: ${escapeHtml(report.id_number)}
+ ` : ''}
+
+
+
+
+
+
+
+ `;
+ }).join('');
+}
+
+/**
+ * Open report modal for creating or editing
+ */
+async function openReportModal(reportId = null) {
+ document.getElementById('reportModal').classList.remove('hidden');
+
+ if (reportId) {
+ document.getElementById('reportModalTitle').textContent = 'Edit Report';
+ document.getElementById('reportId').value = reportId;
+ await loadReportForEdit(reportId);
+ } else {
+ document.getElementById('reportModalTitle').textContent = 'Add Report';
+ document.getElementById('reportForm').reset();
+ document.getElementById('reportId').value = '';
+ // Set the employee id for linking
+ document.getElementById('reportEmployeeId').value = window.currentEmployeeId || '';
+ }
+}
+
+/**
+ * Close report modal
+ */
+function closeReportModal() {
+ document.getElementById('reportModal').classList.add('hidden');
+ document.getElementById('reportForm').reset();
+ document.getElementById('reportId').value = '';
+}
+
+/**
+ * Load report for editing
+ */
+async function loadReportForEdit(reportId) {
+ try {
+ const report = await pb.collection(reportsCollectionName).getOne(reportId);
+
+ // Populate form fields
+ document.getElementById('reportRow').value = report.row || '';
+ document.getElementById('reportEnteredBy').value = report.entered_by || '';
+ document.getElementById('reportEnteredDate').value = report.entered_date
+ ? new Date(report.entered_date).toISOString().split('T')[0]
+ : '';
+ document.getElementById('reportIdNumber').value = report.id_number || '';
+ document.getElementById('reportContent').value = report.report || '';
+ document.getElementById('reportEmployeeId').value = report.id || window.currentEmployeeId || '';
+
+ return report;
+ } catch (error) {
+ console.error('Error loading report:', error);
+ showMessage('Error loading report: ' + (error.message || 'Unknown error'), 'error');
+ return null;
+ }
+}
+
+/**
+ * Save report (create or update)
+ */
+async function saveReport() {
+ try {
+ const form = document.getElementById('reportForm');
+ if (!form) {
+ showMessage('Form not found', 'error');
+ return;
+ }
+
+ const formData = new FormData(form);
+ const reportId = document.getElementById('reportId')?.value;
+ const employeeId = window.currentEmployeeId || document.getElementById('reportEmployeeId')?.value;
+
+ if (!employeeId) {
+ showMessage('No employee ID found. Please save the employee first.', 'error');
+ return;
+ }
+
+ // Build report object
+ // Note: In PocketBase, when creating, we can't set the id field directly
+ // So we'll use the id field value to link to Employee_Records
+ // But we need to check if this is actually a relation field or a text field
+ // For now, we'll set it as a field value
+ const reportData = {};
+
+ // Set the id field to link to Employee_Records (this is the linking field)
+ reportData.id = employeeId;
+
+ // Get all form fields
+ for (const [key, value] of formData.entries()) {
+ if (key === 'id') continue; // Skip the hidden id field
+
+ if (value !== null && value !== undefined) {
+ if (key === 'entered_date' && value) {
+ // Convert date to ISO string
+ reportData[key] = new Date(value).toISOString();
+ } else {
+ reportData[key] = value.trim();
+ }
+ }
+ }
+
+ // Get employee info to populate name fields if available
+ if (employeeId && typeof loadEmployeeForEdit === 'undefined') {
+ // Try to get employee data if we have access to it
+ try {
+ const employee = await pb.collection('Employee_Records').getOne(employeeId);
+ if (employee) {
+ reportData.first_name = employee.First_Name || '';
+ reportData.last_name = employee.Last_Name || '';
+ reportData.combined_name = `${employee.First_Name || ''} ${employee.Last_Name || ''}`.trim();
+ }
+ } catch (e) {
+ console.warn('Could not load employee data for report:', e);
+ }
+ }
+
+ if (reportId) {
+ // Update existing report
+ await pb.collection(reportsCollectionName).update(reportId, reportData);
+ showMessage('Report updated successfully', 'success');
+ } else {
+ // Create new report
+ await pb.collection(reportsCollectionName).create(reportData);
+ showMessage('Report created successfully', 'success');
+ }
+
+ closeReportModal();
+ if (window.currentEmployeeId) {
+ loadEmployeeReports(window.currentEmployeeId);
+ }
+ } catch (error) {
+ console.error('Error saving report:', error);
+ const errorMsg = error.message || 'Unknown error';
+ showMessage('Error saving report: ' + errorMsg, 'error');
+ }
+}
+
+/**
+ * Delete report
+ */
+async function deleteReport(reportId) {
+ if (!confirm('Are you sure you want to delete this report? This action cannot be undone.')) {
+ return;
+ }
+
+ try {
+ await pb.collection(reportsCollectionName).delete(reportId);
+ showMessage('Report deleted successfully', 'success');
+ if (window.currentEmployeeId) {
+ loadEmployeeReports(window.currentEmployeeId);
+ }
+ } catch (error) {
+ console.error('Error deleting report:', error);
+ showMessage('Error deleting report: ' + (error.message || 'Unknown error'), 'error');
+ }
+}
+
+/**
+ * Escape HTML to prevent XSS
+ */
+function escapeHtml(text) {
+ if (text == null) return '';
+ const map = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": '''
+ };
+ return String(text).replace(/[&<>"']/g, m => map[m]);
+}
+
+// Make functions globally accessible
+window.loadEmployeeReports = loadEmployeeReports;
+window.openReportModal = openReportModal;
+window.closeReportModal = closeReportModal;
+window.saveReport = saveReport;
+window.deleteReport = deleteReport;
diff --git a/js/employees.js b/js/employees.js
new file mode 100644
index 0000000..aa908e1
--- /dev/null
+++ b/js/employees.js
@@ -0,0 +1,542 @@
+// Employee CRUD operations
+
+let currentPage = 1;
+let itemsPerPage = 20;
+let allEmployees = [];
+let employeesCollectionName = 'Employee_Records';
+let currentView = localStorage.getItem('employeesView') || 'table'; // 'table' or 'card'
+
+// Common employee field names that we'll display (matching PocketBase schema)
+const standardFields = ['First_Name', 'Last_Name', 'Email_Address', 'Phone_Number', 'Voxer_ID', 'Status'];
+
+/**
+ * Load all employees with optional search filter
+ */
+async function loadEmployees(page = 1) {
+ try {
+ // Show loading state based on current view
+ if (currentView === 'table') {
+ const tbody = document.getElementById('employeesTableBody');
+ if (tbody) {
+ tbody.innerHTML = '
| Loading... |
';
+ }
+ } else {
+ const container = document.getElementById('employeesCardContainer');
+ if (container) {
+ container.innerHTML = '
Loading...
';
+ }
+ }
+
+ currentPage = page;
+ const searchTerm = document.getElementById('searchInput')?.value || '';
+
+ // Build search filter
+ let searchFilter = '';
+ if (searchTerm) {
+ // Escape special characters for PocketBase filter
+ const escapedTerm = searchTerm.replace(/"/g, '\\"');
+ // Search across common text fields
+ searchFilter = `First_Name ~ "${escapedTerm}" || Last_Name ~ "${escapedTerm}" || Email_Address ~ "${escapedTerm}" || Phone_Number ~ "${escapedTerm}" || Voxer_ID ~ "${escapedTerm}" || Status ~ "${escapedTerm}"`;
+ }
+
+ const result = await pb.collection(employeesCollectionName).getList(page, itemsPerPage, {
+ filter: searchFilter || undefined,
+ sort: 'Last_Name',
+ });
+
+ allEmployees = result.items;
+ displayEmployees(allEmployees);
+ displayPagination(result.page, result.totalPages, result.totalItems);
+
+ // Update view based on current view preference
+ updateViewDisplay();
+ } catch (error) {
+ console.error('Error loading employees:', error);
+ showMessage('Error loading employees: ' + (error.message || 'Unknown error'), 'error');
+ if (currentView === 'table') {
+ const tbody = document.getElementById('employeesTableBody');
+ if (tbody) {
+ tbody.innerHTML = '
| Error loading employees. Please refresh the page. |
';
+ }
+ } else {
+ const container = document.getElementById('employeesCardContainer');
+ if (container) {
+ container.innerHTML = '
Error loading employees. Please refresh the page.
';
+ }
+ }
+ }
+}
+
+/**
+ * Display employees in table or card view
+ */
+function displayEmployees(employees) {
+ if (currentView === 'table') {
+ displayEmployeesTable(employees);
+ } else {
+ displayEmployeesCards(employees);
+ }
+}
+
+/**
+ * Display employees in table view
+ */
+function displayEmployeesTable(employees) {
+ const tbody = document.getElementById('employeesTableBody');
+ if (!tbody) return;
+
+ if (!employees || employees.length === 0) {
+ tbody.innerHTML = '
| No employees found |
';
+ return;
+ }
+
+ tbody.innerHTML = employees.map(employee => {
+ // Use correct field names from schema
+ const firstName = employee.First_Name || '-';
+ const lastName = employee.Last_Name || '-';
+ const email = employee.Email_Address || '-';
+ const phone = employee.Phone_Number || '-';
+ const voxerId = employee.Voxer_ID || '-';
+ const status = employee.Status || '-';
+
+ return `
+
+ | ${escapeHtml(firstName)} |
+ ${escapeHtml(lastName)} |
+ ${escapeHtml(phone)} |
+ ${escapeHtml(email)} |
+ ${escapeHtml(voxerId)} |
+ ${escapeHtml(status)} |
+
+
+
+
+
+ |
+
+ `;
+ }).join('');
+}
+
+/**
+ * Display employees in card view
+ */
+function displayEmployeesCards(employees) {
+ const container = document.getElementById('employeesCardContainer');
+ if (!container) return;
+
+ if (!employees || employees.length === 0) {
+ container.innerHTML = '
No employees found
';
+ return;
+ }
+
+ container.innerHTML = employees.map(employee => {
+ // Use correct field names from schema
+ const firstName = employee.First_Name || '';
+ const lastName = employee.Last_Name || '';
+ const fullName = `${firstName} ${lastName}`.trim() || 'N/A';
+ const email = employee.Email_Address || '-';
+ const phone = employee.Phone_Number || '-';
+ const voxerId = employee.Voxer_ID || '-';
+ const status = employee.Status || '-';
+
+ return `
+
+
+
+
+
${escapeHtml(fullName)}
+ ${status !== '-' ? `
+
+
+ ${escapeHtml(status)}
+
+
+ ` : ''}
+
+
+
+
+
+
+
+
Email
+ ${email !== '-' ? `
+
${escapeHtml(email)}
+
Send Email
+ ` : '
-
'}
+
+
+
+
Phone
+ ${phone !== '-' ? `
+
${escapeHtml(phone)}
+
Call
+ ` : '
-
'}
+
+
+
+
Voxer ID
+
${escapeHtml(voxerId)}
+
+
+
+ `;
+ }).join('');
+}
+
+/**
+ * Display pagination controls
+ */
+function displayPagination(currentPage, totalPages, totalItems) {
+ const container = document.getElementById('paginationContainer');
+ if (!container) return;
+
+ if (totalPages <= 1) {
+ container.innerHTML = '';
+ return;
+ }
+
+ let html = '
';
+
+ // Previous button
+ if (currentPage > 1) {
+ html += ``;
+ }
+
+ // Page info
+ html += `Page ${currentPage} of ${totalPages} (${totalItems} total)`;
+
+ // Next button
+ if (currentPage < totalPages) {
+ html += ``;
+ }
+
+ html += '
';
+ container.innerHTML = html;
+}
+
+/**
+ * Load employee for editing
+ */
+async function loadEmployeeForEdit(employeeId) {
+ try {
+ if (!employeeId) {
+ showMessage('No employee ID provided', 'error');
+ return null;
+ }
+
+ const employee = await pb.collection(employeesCollectionName).getOne(employeeId);
+
+ // Set current employee ID for reports
+ window.currentEmployeeId = employeeId;
+
+ // Update modal header
+ if (typeof updateEmployeeModalInfo === 'function') {
+ updateEmployeeModalInfo(employee);
+ }
+
+ // Show reports tab for existing employees - do this after a short delay to ensure DOM is ready
+ setTimeout(() => {
+ const reportsTabButton = document.getElementById('tab-reports');
+ if (reportsTabButton) {
+ reportsTabButton.classList.remove('hidden');
+ }
+ }, 50);
+
+ // Populate standard form fields using correct field names
+ const firstNameField = document.getElementById('First_Name');
+ if (firstNameField) firstNameField.value = employee.First_Name || '';
+
+ const lastNameField = document.getElementById('Last_Name');
+ if (lastNameField) lastNameField.value = employee.Last_Name || '';
+
+ const emailField = document.getElementById('Email_Address');
+ if (emailField) emailField.value = employee.Email_Address || '';
+
+ const phoneField = document.getElementById('Phone_Number');
+ if (phoneField) phoneField.value = employee.Phone_Number || '';
+
+ const voxerField = document.getElementById('Voxer_ID');
+ if (voxerField) voxerField.value = employee.Voxer_ID || '';
+
+ const statusField = document.getElementById('Status');
+ if (statusField) statusField.value = employee.Status || '';
+
+ // Handle additional fields dynamically
+ const additionalFieldsContainer = document.getElementById('additionalFieldsContainer');
+ if (additionalFieldsContainer) {
+ additionalFieldsContainer.innerHTML = '';
+
+ // Get all fields from the employee record
+ const allFields = Object.keys(employee);
+ const systemFields = new Set(['id', 'created', 'updated', 'collectionId', 'collectionName']);
+
+ // Add any fields that aren't in the standard fields
+ allFields.forEach(field => {
+ // Skip system fields
+ if (systemFields.has(field) || field.startsWith('@')) {
+ return;
+ }
+
+ // Skip standard fields (already handled above)
+ if (standardFields.includes(field)) {
+ return;
+ }
+
+ // Create input for this additional field
+ if (employee[field] !== undefined) {
+ const fieldLabel = field.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
+ const fieldId = `field_${field}`;
+
+ const fieldDiv = document.createElement('div');
+ fieldDiv.innerHTML = `
+
+
+ `;
+ additionalFieldsContainer.appendChild(fieldDiv.firstElementChild);
+ }
+ });
+ }
+
+ return employee;
+ } catch (error) {
+ console.error('Error loading employee:', error);
+ showMessage('Error loading employee: ' + (error.message || 'Unknown error'), 'error');
+ return null;
+ }
+}
+
+
+/**
+ * Escape HTML to prevent XSS
+ */
+function escapeHtml(text) {
+ const map = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": '''
+ };
+ return text.replace(/[&<>"']/g, m => map[m]);
+}
+
+/**
+ * Save employee (create or update)
+ */
+async function saveEmployee() {
+ try {
+ const form = document.getElementById('employeeForm');
+ if (!form) {
+ showMessage('Form not found', 'error');
+ return;
+ }
+
+ const formData = new FormData(form);
+ const employeeId = document.getElementById('employeeId')?.value;
+
+ // Build employee object
+ const employeeData = {};
+
+ // Get all form fields from FormData (this includes standard fields)
+ for (const [key, value] of formData.entries()) {
+ if (key === 'id') continue;
+ // Include the value (even if empty for standard fields to allow clearing)
+ if (value !== null && value !== undefined) {
+ employeeData[key] = value.trim();
+ }
+ }
+
+ // Also get additional fields from dynamically created inputs
+ const additionalFields = document.querySelectorAll('#additionalFieldsContainer input');
+ additionalFields.forEach(input => {
+ if (input.name && input.value !== null && input.value !== undefined) {
+ employeeData[input.name] = input.value.trim();
+ }
+ });
+
+ if (employeeId) {
+ // Update existing employee
+ const updatedEmployee = await pb.collection(employeesCollectionName).update(employeeId, employeeData);
+ const employeeName = `${updatedEmployee.First_Name || ''} ${updatedEmployee.Last_Name || ''}`.trim() || 'Employee';
+ showMessage(`${employeeName} updated successfully`, 'success');
+ } else {
+ // Create new employee
+ const newEmployee = await pb.collection(employeesCollectionName).create(employeeData);
+ const employeeName = `${newEmployee.First_Name || ''} ${newEmployee.Last_Name || ''}`.trim() || 'Employee';
+ showMessage(`${employeeName} created successfully`, 'success');
+ }
+
+ if (typeof closeEmployeeModal === 'function') {
+ closeEmployeeModal();
+ }
+ loadEmployees(currentPage);
+ } catch (error) {
+ console.error('Error saving employee:', error);
+ const errorMsg = error.message || 'Unknown error';
+ showMessage('Error saving employee: ' + errorMsg, 'error');
+ }
+}
+
+/**
+ * Delete employee
+ */
+async function deleteEmployee(employeeId) {
+ // Find the employee name for the confirmation message
+ const employee = allEmployees.find(emp => emp.id === employeeId);
+ const employeeName = employee
+ ? `${employee.First_Name || ''} ${employee.Last_Name || ''}`.trim() || 'this employee'
+ : 'this employee';
+
+ if (!confirm(`Are you sure you want to delete ${employeeName}? This action cannot be undone.`)) {
+ return;
+ }
+
+ try {
+ await pb.collection(employeesCollectionName).delete(employeeId);
+ showMessage(`Employee ${employeeName} deleted successfully`, 'success');
+ // Reload employees with current view state
+ loadEmployees(currentPage);
+ } catch (error) {
+ console.error('Error deleting employee:', error);
+ showMessage('Error deleting employee: ' + (error.message || 'Unknown error'), 'error');
+ }
+}
+
+/**
+ * Show message to user
+ */
+function showMessage(message, type = 'success') {
+ const container = document.getElementById('messageContainer');
+ if (!container) return;
+
+ 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}
+
+ `;
+
+ // Auto-hide after 5 seconds
+ setTimeout(() => {
+ container.innerHTML = '';
+ }, 5000);
+}
+
+/**
+ * Switch between table and card view
+ */
+function switchView(view) {
+ currentView = view;
+ localStorage.setItem('employeesView', view);
+ updateViewDisplay();
+ displayEmployees(allEmployees);
+}
+
+/**
+ * Update view display based on current view preference
+ */
+function updateViewDisplay() {
+ const tableView = document.getElementById('tableView');
+ const cardView = document.getElementById('cardView');
+ const tableViewBtn = document.getElementById('tableViewBtn');
+ const cardViewBtn = document.getElementById('cardViewBtn');
+
+ if (currentView === 'table') {
+ // Show table, hide card
+ if (tableView) tableView.classList.remove('hidden');
+ if (cardView) cardView.classList.add('hidden');
+
+ // Table button: active (indigo with shadow)
+ if (tableViewBtn) {
+ tableViewBtn.classList.remove('text-gray-700', 'hover:bg-white/40');
+ tableViewBtn.classList.add('bg-indigo-600/90', 'text-white', 'shadow-lg', 'hover:bg-indigo-700/90');
+ }
+ // Card button: inactive (transparent)
+ if (cardViewBtn) {
+ cardViewBtn.classList.remove('bg-indigo-600/90', 'text-white', 'shadow-lg', 'hover:bg-indigo-700/90');
+ cardViewBtn.classList.add('text-gray-700', 'hover:bg-white/40');
+ }
+ } else {
+ // Show card, hide table
+ if (tableView) tableView.classList.add('hidden');
+ if (cardView) cardView.classList.remove('hidden');
+
+ // Table button: inactive (transparent)
+ if (tableViewBtn) {
+ tableViewBtn.classList.remove('bg-indigo-600/90', 'text-white', 'shadow-lg', 'hover:bg-indigo-700/90');
+ tableViewBtn.classList.add('text-gray-700', 'hover:bg-white/40');
+ }
+ // Card button: active (indigo with shadow)
+ if (cardViewBtn) {
+ cardViewBtn.classList.remove('text-gray-700', 'hover:bg-white/40');
+ cardViewBtn.classList.add('bg-indigo-600/90', 'text-white', 'shadow-lg', 'hover:bg-indigo-700/90');
+ }
+ }
+}
+
+/**
+ * Switch employee modal tab
+ */
+function switchEmployeeTab(tabName) {
+ // Hide all tab contents
+ document.querySelectorAll('.employee-tab-content').forEach(tab => {
+ tab.classList.add('hidden');
+ });
+
+ // Remove active state from all tabs
+ document.querySelectorAll('.employee-tab').forEach(btn => {
+ btn.classList.remove('border-indigo-500', 'text-indigo-600');
+ btn.classList.add('border-transparent', 'text-gray-500');
+ });
+
+ // Show selected tab content
+ const selectedTab = document.getElementById(`employee-tab-${tabName}`);
+ if (selectedTab) {
+ selectedTab.classList.remove('hidden');
+ }
+
+ // Activate selected tab button
+ const selectedButton = document.getElementById(`tab-${tabName}`);
+ if (selectedButton) {
+ selectedButton.classList.add('border-indigo-500', 'text-indigo-600');
+ selectedButton.classList.remove('border-transparent', 'text-gray-500');
+ }
+
+ // Load reports if reports tab is selected
+ if (tabName === 'reports' && window.currentEmployeeId && typeof loadEmployeeReports === 'function') {
+ setTimeout(() => {
+ loadEmployeeReports(window.currentEmployeeId);
+ }, 100);
+ }
+}
+
+/**
+ * Update employee modal header info
+ */
+function updateEmployeeModalInfo(employee) {
+ const firstName = employee.First_Name || '';
+ const lastName = employee.Last_Name || '';
+ const fullName = `${firstName} ${lastName}`.trim() || 'Employee';
+ document.getElementById('employeeModalTitle').textContent = fullName;
+}
+
+// Make functions globally accessible
+window.loadEmployees = loadEmployees;
+window.loadEmployeeForEdit = loadEmployeeForEdit;
+window.saveEmployee = saveEmployee;
+window.deleteEmployee = deleteEmployee;
+window.switchView = switchView;
+window.updateViewDisplay = updateViewDisplay;
+window.switchEmployeeTab = switchEmployeeTab;