adding employee page. needs reports

This commit is contained in:
2025-12-17 15:58:04 -06:00
parent 13bb6542bc
commit d4f244609a
4 changed files with 1266 additions and 1 deletions
+445
View File
@@ -0,0 +1,445 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Job Tracking - Employees</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/pocketbase@latest/dist/pocketbase.umd.js"></script>
</head>
<body class="min-h-screen bg-gradient-to-br from-gray-50 via-blue-50/30 to-indigo-50/40">
<!-- Navigation Header -->
<nav class="backdrop-blur-xl bg-white/70 border-b border-white/20 shadow-sm sticky top-0 z-40">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex flex-row justify-between items-center py-4 px-2">
<div class="flex items-center gap-4">
<a href="dashboard" class="text-indigo-600 hover:text-indigo-700 font-medium text-sm sm:text-base transition-colors">← Dashboard</a>
</div>
<div class="flex items-center gap-3 relative">
<div class="relative">
<button
onclick="toggleUserDropdown()"
class="w-10 h-10 rounded-full bg-gradient-to-br from-indigo-500 via-purple-500 to-pink-500 flex items-center justify-center text-white font-medium text-sm hover:scale-105 focus:outline-none transition-all duration-300 shadow-lg shadow-indigo-500/30 hover:shadow-indigo-500/50"
id="userAvatarBtn"
>
<span id="userInitials" class="text-xs font-semibold"></span>
</button>
<div
id="userDropdown"
class="hidden absolute right-0 mt-2 w-48 backdrop-blur-xl bg-white/80 rounded-2xl shadow-2xl border border-white/30 py-2 z-50 overflow-hidden"
>
<div class="px-4 py-3 border-b border-white/20">
<p class="text-xs text-gray-500 font-medium">Signed in as</p>
<p class="text-sm font-semibold text-gray-900 truncate mt-0.5" id="userEmail"></p>
</div>
<a
href="preferences"
class="block px-4 py-2.5 text-sm text-gray-700 hover:bg-white/40 focus:outline-none transition-colors font-medium"
>
Preferences
</a>
<button
onclick="logout()"
class="w-full text-left px-4 py-2.5 text-sm text-red-600 hover:bg-red-50/50 focus:outline-none transition-colors font-medium"
>
Logout
</button>
</div>
</div>
</div>
</div>
</div>
</nav>
<!-- Main Content -->
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<!-- Page Header -->
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-6">
<div>
<h1 class="text-xl sm:text-2xl font-bold text-gray-800 mb-2">Employees</h1>
<p class="text-sm sm:text-base text-gray-600">Manage employee records</p>
</div>
<button
onclick="openEmployeeModal()"
class="w-full sm:w-auto bg-indigo-600 text-white px-4 sm:px-6 py-2 sm:py-3 rounded-lg text-sm sm:text-base font-medium hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition"
>
+ Add Employee
</button>
</div>
<!-- Message Container -->
<div id="messageContainer" class="mb-4"></div>
<!-- Search Section -->
<div class="backdrop-blur-xl bg-white/60 rounded-2xl shadow-xl border border-white/30 p-6 mb-6">
<input
type="text"
id="searchInput"
placeholder="Search by name, email, phone, or department..."
class="w-full px-4 py-3 border-2 border-gray-300/60 rounded-xl backdrop-blur-sm bg-white/40 focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/70 outline-none text-base transition-all shadow-sm"
>
</div>
<!-- View Toggle -->
<div class="mb-4 flex justify-end">
<div class="inline-flex rounded-2xl border border-white/30 backdrop-blur-xl bg-white/60 p-1 shadow-lg">
<button
onclick="switchView('table')"
id="tableViewBtn"
class="px-4 py-2 rounded-xl text-sm font-medium transition-all focus:outline-none focus:ring-2 focus:ring-indigo-500/50 backdrop-blur-sm bg-indigo-600/90 text-white shadow-lg hover:bg-indigo-700/90"
>
<svg class="w-5 h-5 inline-block mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"></path>
</svg>
Table
</button>
<button
onclick="switchView('card')"
id="cardViewBtn"
class="px-4 py-2 rounded-xl text-sm font-medium transition-all focus:outline-none focus:ring-2 focus:ring-indigo-500/50 text-gray-700 hover:bg-white/40 backdrop-blur-sm"
>
<svg class="w-5 h-5 inline-block mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z"></path>
</svg>
Cards
</button>
</div>
</div>
<!-- Employees Table View -->
<div id="tableView" class="backdrop-blur-xl bg-white/60 rounded-2xl shadow-xl border border-white/30 overflow-hidden">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="backdrop-blur-sm bg-white/40">
<tr>
<th class="px-3 sm:px-6 py-2 sm:py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">First Name</th>
<th class="px-3 sm:px-6 py-2 sm:py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Last Name</th>
<th class="px-3 sm:px-6 py-2 sm:py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Phone</th>
<th class="px-3 sm:px-6 py-2 sm:py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Email</th>
<th class="px-3 sm:px-6 py-2 sm:py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Voxer ID</th>
<th class="px-3 sm:px-6 py-2 sm:py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
<th class="px-3 sm:px-6 py-2 sm:py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
</tr>
</thead>
<tbody id="employeesTableBody" class="bg-white/30 divide-y divide-white/20">
<tr id="loadingRow">
<td colspan="7" class="px-6 py-8 text-center text-gray-500">Loading...</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Employees Card View -->
<div id="cardView" class="hidden">
<div id="employeesCardContainer" class="space-y-4">
<div class="text-center py-8 text-gray-500">Loading...</div>
</div>
</div>
<!-- Pagination -->
<div id="paginationContainer" class="mt-4 flex justify-between items-center"></div>
</main>
<!-- Employee Modal -->
<div id="employeeModal" class="hidden fixed inset-0 backdrop-blur-sm bg-black/20 overflow-y-auto z-50">
<div class="relative top-0 sm:top-10 mx-auto p-4 sm:p-6 w-full sm:max-w-3xl shadow-2xl rounded-none sm:rounded-3xl backdrop-blur-2xl bg-white/80 border border-white/30 mb-0 sm:mb-10 min-h-screen sm:min-h-[600px]">
<!-- Modal Header -->
<div class="backdrop-blur-xl bg-white/60 rounded-2xl shadow-xl border border-white/30 p-6 mb-6">
<div class="flex justify-between items-center mb-4">
<h2 class="text-2xl font-bold text-gray-900" id="employeeModalTitle">Add Employee</h2>
<button
onclick="closeEmployeeModal()"
class="text-gray-400 hover:text-gray-500"
>
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<!-- Tabs Navigation -->
<div class="border-b border-gray-200">
<nav class="flex space-x-8 overflow-x-auto">
<button onclick="switchEmployeeTab('overview')" id="tab-overview" class="employee-tab border-b-2 border-indigo-500 text-indigo-600 font-medium text-sm py-2 px-1 whitespace-nowrap">Overview</button>
<button onclick="switchEmployeeTab('reports')" id="tab-reports" class="employee-tab border-b-2 border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 font-medium text-sm py-2 px-1 whitespace-nowrap hidden">Reports</button>
</nav>
</div>
</div>
<!-- Employee Form -->
<form id="employeeForm">
<input type="hidden" id="employeeId" name="id">
<div class="space-y-6">
<!-- Overview Tab Content -->
<div id="employee-tab-overview" class="employee-tab-content space-y-6 min-h-[500px]">
<div class="backdrop-blur-xl bg-white/60 rounded-2xl shadow-xl border border-white/30 p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">Basic Information</h3>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label for="First_Name" class="block text-sm font-medium text-gray-700 mb-1">First Name *</label>
<input type="text" id="First_Name" name="First_Name" required class="w-full px-3 py-2 border-2 border-gray-300/60 rounded-xl backdrop-blur-sm bg-white/40 focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/70 outline-none text-base transition-all shadow-sm">
</div>
<div>
<label for="Last_Name" class="block text-sm font-medium text-gray-700 mb-1">Last Name *</label>
<input type="text" id="Last_Name" name="Last_Name" required class="w-full px-3 py-2 border-2 border-gray-300/60 rounded-xl backdrop-blur-sm bg-white/40 focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/70 outline-none text-base transition-all shadow-sm">
</div>
<div>
<label for="Email_Address" class="block text-sm font-medium text-gray-700 mb-1">Email Address</label>
<input type="email" id="Email_Address" name="Email_Address" class="w-full px-3 py-2 border-2 border-gray-300/60 rounded-xl backdrop-blur-sm bg-white/40 focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/70 outline-none text-base transition-all shadow-sm">
</div>
<div>
<label for="Phone_Number" class="block text-sm font-medium text-gray-700 mb-1">Phone Number</label>
<input type="tel" id="Phone_Number" name="Phone_Number" class="w-full px-3 py-2 border-2 border-gray-300/60 rounded-xl backdrop-blur-sm bg-white/40 focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/70 outline-none text-base transition-all shadow-sm">
</div>
<div>
<label for="Voxer_ID" class="block text-sm font-medium text-gray-700 mb-1">Voxer ID</label>
<input type="text" id="Voxer_ID" name="Voxer_ID" class="w-full px-3 py-2 border-2 border-gray-300/60 rounded-xl backdrop-blur-sm bg-white/40 focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/70 outline-none text-base transition-all shadow-sm">
</div>
<div>
<label for="Status" class="block text-sm font-medium text-gray-700 mb-1">Status</label>
<input type="text" id="Status" name="Status" class="w-full px-3 py-2 border-2 border-gray-300/60 rounded-xl backdrop-blur-sm bg-white/40 focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/70 outline-none text-base transition-all shadow-sm">
</div>
</div>
</div>
<!-- Additional Fields Section (for any extra fields) -->
<div class="backdrop-blur-xl bg-white/60 rounded-2xl shadow-xl border border-white/30 p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">Additional Information</h3>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4" id="additionalFieldsContainer">
<!-- Additional fields will be dynamically added here -->
</div>
</div>
</div>
<!-- Reports Tab Content -->
<div id="employee-tab-reports" class="employee-tab-content hidden space-y-6 min-h-[500px]">
<div class="backdrop-blur-xl bg-white/60 rounded-2xl shadow-xl border border-white/30 p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold text-gray-900">Employee Reports</h3>
<button
type="button"
onclick="openReportModal()"
class="bg-indigo-600 text-white px-4 py-2 rounded-lg text-sm font-medium hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500"
>
+ Add Report
</button>
</div>
<div id="reportsList" class="space-y-4">
<p class="text-center text-gray-500 py-8">Loading reports...</p>
</div>
</div>
</div>
<!-- Form Buttons -->
<div class="flex flex-col sm:flex-row justify-end gap-3 pt-6 border-t border-gray-200">
<button
type="button"
onclick="closeEmployeeModal()"
class="w-full sm:w-auto px-6 py-2.5 backdrop-blur-sm bg-white/60 border-2 border-gray-300/60 text-gray-700 rounded-xl font-medium hover:bg-white/80 focus:outline-none focus:ring-2 focus:ring-gray-500/50 transition-all shadow-lg hover:shadow-xl"
>
Cancel
</button>
<button
type="submit"
class="w-full sm:w-auto px-6 py-2.5 backdrop-blur-sm bg-indigo-600/90 text-white rounded-xl font-medium hover:bg-indigo-700/90 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 transition-all shadow-lg hover:shadow-xl"
>
Save Employee
</button>
</div>
</div>
</form>
</div>
</div>
<!-- Report Modal -->
<div id="reportModal" class="hidden fixed inset-0 backdrop-blur-sm bg-black/20 overflow-y-auto z-50">
<div class="relative top-0 sm:top-10 mx-auto p-4 sm:p-6 w-full sm:max-w-2xl shadow-2xl rounded-none sm:rounded-3xl backdrop-blur-2xl bg-white/80 border border-white/30 mb-0 sm:mb-10 min-h-screen sm:min-h-[400px]">
<div class="backdrop-blur-xl bg-white/60 rounded-2xl shadow-xl border border-white/30 p-6 mb-6">
<div class="flex justify-between items-center">
<h2 class="text-2xl font-bold text-gray-900" id="reportModalTitle">Add Report</h2>
<button
onclick="closeReportModal()"
class="text-gray-400 hover:text-gray-500"
>
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
</div>
<form id="reportForm" class="space-y-6">
<input type="hidden" id="reportId" name="id">
<input type="hidden" id="reportEmployeeId" name="id">
<div class="backdrop-blur-xl bg-white/60 rounded-2xl shadow-xl border border-white/30 p-6">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label for="reportRow" class="block text-sm font-medium text-gray-700 mb-1">Row</label>
<input type="text" id="reportRow" name="row" class="w-full px-3 py-2 border-2 border-gray-300/60 rounded-xl backdrop-blur-sm bg-white/40 focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/70 outline-none text-base transition-all shadow-sm">
</div>
<div>
<label for="reportEnteredBy" class="block text-sm font-medium text-gray-700 mb-1">Entered By</label>
<input type="text" id="reportEnteredBy" name="entered_by" class="w-full px-3 py-2 border-2 border-gray-300/60 rounded-xl backdrop-blur-sm bg-white/40 focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/70 outline-none text-base transition-all shadow-sm">
</div>
<div>
<label for="reportEnteredDate" class="block text-sm font-medium text-gray-700 mb-1">Entered Date</label>
<input type="date" id="reportEnteredDate" name="entered_date" class="w-full px-3 py-2 border-2 border-gray-300/60 rounded-xl backdrop-blur-sm bg-white/40 focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/70 outline-none text-base transition-all shadow-sm">
</div>
<div>
<label for="reportIdNumber" class="block text-sm font-medium text-gray-700 mb-1">ID Number</label>
<input type="text" id="reportIdNumber" name="id_number" class="w-full px-3 py-2 border-2 border-gray-300/60 rounded-xl backdrop-blur-sm bg-white/40 focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/70 outline-none text-base transition-all shadow-sm">
</div>
<div class="sm:col-span-2">
<label for="reportContent" class="block text-sm font-medium text-gray-700 mb-1">Report</label>
<textarea id="reportContent" name="report" rows="4" class="w-full px-3 py-2 border-2 border-gray-300/60 rounded-xl backdrop-blur-sm bg-white/40 focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/70 outline-none text-base transition-all shadow-sm"></textarea>
</div>
</div>
</div>
<div class="flex flex-col sm:flex-row justify-end gap-3 pt-6 border-t border-gray-200">
<button
type="button"
onclick="closeReportModal()"
class="w-full sm:w-auto px-6 py-2.5 backdrop-blur-sm bg-white/60 border-2 border-gray-300/60 text-gray-700 rounded-xl font-medium hover:bg-white/80 focus:outline-none focus:ring-2 focus:ring-gray-500/50 transition-all shadow-lg hover:shadow-xl"
>
Cancel
</button>
<button
type="submit"
class="w-full sm:w-auto px-6 py-2.5 backdrop-blur-sm bg-indigo-600/90 text-white rounded-xl font-medium hover:bg-indigo-700/90 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 transition-all shadow-lg hover:shadow-xl"
>
Save Report
</button>
</div>
</form>
</div>
</div>
<script src="js/pocketbase.js"></script>
<script src="js/config.js"></script>
<script src="js/auth.js"></script>
<script src="js/preferences.js"></script>
<script src="js/employees.js"></script>
<script src="js/employee-reports.js"></script>
<script>
// Check authentication
checkAuth();
// Initialize dark mode
initializeDarkMode();
// Set user email and initials
const user = pb.authStore.model;
if (user) {
const email = user.email || '';
document.getElementById('userEmail').textContent = email;
// Set initials for avatar
const initials = email
.split('@')[0]
.split('.')
.map(part => part.charAt(0).toUpperCase())
.join('')
.substring(0, 2) || 'U';
document.getElementById('userInitials').textContent = initials;
}
// Toggle user dropdown
function toggleUserDropdown() {
const dropdown = document.getElementById('userDropdown');
dropdown.classList.toggle('hidden');
}
// Close dropdown when clicking outside
document.addEventListener('click', (e) => {
const dropdown = document.getElementById('userDropdown');
const button = document.getElementById('userAvatarBtn');
if (dropdown && !dropdown.contains(e.target) && !button.contains(e.target)) {
dropdown.classList.add('hidden');
}
});
// Make function globally accessible
window.toggleUserDropdown = toggleUserDropdown;
// Modal functions
function openEmployeeModal(employeeId = null) {
document.getElementById('employeeModal').classList.remove('hidden');
if (employeeId) {
document.getElementById('employeeId').value = employeeId;
// Show reports tab for existing employees (do this before loading to ensure it's visible)
const reportsTabButton = document.getElementById('tab-reports');
if (reportsTabButton) {
reportsTabButton.classList.remove('hidden');
}
loadEmployeeForEdit(employeeId);
} else {
document.getElementById('employeeModalTitle').textContent = 'Add Employee';
document.getElementById('employeeForm').reset();
document.getElementById('employeeId').value = '';
// Hide reports tab for new employees
const reportsTabButton = document.getElementById('tab-reports');
if (reportsTabButton) {
reportsTabButton.classList.add('hidden');
}
// Clear additional fields
document.getElementById('additionalFieldsContainer').innerHTML = '';
// Ensure standard fields are cleared
document.getElementById('First_Name').value = '';
document.getElementById('Last_Name').value = '';
document.getElementById('Email_Address').value = '';
document.getElementById('Phone_Number').value = '';
document.getElementById('Voxer_ID').value = '';
document.getElementById('Status').value = '';
}
// Start with overview tab
switchEmployeeTab('overview');
}
function closeEmployeeModal() {
document.getElementById('employeeModal').classList.add('hidden');
document.getElementById('employeeForm').reset();
document.getElementById('employeeId').value = '';
document.getElementById('additionalFieldsContainer').innerHTML = '';
// Reset tab to overview
switchEmployeeTab('overview');
}
// Make functions globally accessible
window.openEmployeeModal = openEmployeeModal;
window.closeEmployeeModal = closeEmployeeModal;
// Form submission
document.getElementById('employeeForm').addEventListener('submit', async (e) => {
e.preventDefault();
await saveEmployee();
});
// Report form submission
document.getElementById('reportForm').addEventListener('submit', async (e) => {
e.preventDefault();
await saveReport();
});
// Search functionality
document.getElementById('searchInput').addEventListener('input', (e) => {
clearTimeout(window.searchTimeout);
window.searchTimeout = setTimeout(() => {
loadEmployees(currentPage);
}, 300);
});
// Load employees on page load
setTimeout(() => {
// Initialize view display
if (typeof updateViewDisplay === 'function') {
updateViewDisplay();
}
loadEmployees();
}, 100);
</script>
</body>
</html>