Spaces:
Running
Running
| <html lang="vi"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Nha Khoa TTL - Hệ Thống Quản Lý Công Việc</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <script src="https://www.gstatic.com/firebasejs/9.6.0/firebase-app-compat.js"></script> | |
| <script src="https://www.gstatic.com/firebasejs/9.6.0/firebase-firestore-compat.js"></script> | |
| <script src="https://www.gstatic.com/firebasejs/9.6.0/firebase-auth-compat.js"></script> | |
| <script src="https://www.gstatic.com/firebasejs/9.6.0/firebase-database-compat.js"></script> | |
| <script src="https://www.gstatic.com/firebasejs/9.6.0/firebase-storage-compat.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/locale/vi.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
| <style> | |
| /* Custom styles for better scrollbar and modal backdrop */ | |
| /* Desktop layout */ | |
| @media (min-width: 768px) { | |
| body { | |
| display: flex; /* Use flexbox for desktop layout */ | |
| } | |
| } | |
| body { | |
| height: 100vh; | |
| position: relative; | |
| background-color: #f3f4f6; /* Light gray background */ | |
| } | |
| /* Ẩn tất cả section */ | |
| .content-section { | |
| display: none; | |
| } | |
| /* Chỉ show section được gắn .active */ | |
| .content-section.active, | |
| .content-section:target { /* :target để hỗ trợ deep linking ban đầu nếu có */ | |
| display: block; | |
| } | |
| .modal { | |
| display: none; /* Hidden by default */ | |
| position: fixed; /* Stay in place */ | |
| z-index: 1000; /* Sit on top */ | |
| left: 0; | |
| top: 0; | |
| width: 100%; /* Full width */ | |
| height: 100%; /* Full height */ | |
| overflow: auto; /* Enable scroll if needed */ | |
| background-color: rgba(0,0,0,0.5); /* Black w/ opacity */ | |
| justify-content: center; /* Center content horizontally */ | |
| align-items: center; /* Center content vertically */ | |
| padding: 1rem; /* Add some padding for smaller screens */ | |
| } | |
| #confirmModal { | |
| z-index: 1050; /* Ensure confirm modal is always on top of other modals */ | |
| } | |
| .modal-content { | |
| background-color: #fefefe; | |
| margin: auto; | |
| padding: 2rem; | |
| border-radius: 0.5rem; | |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); | |
| width: 90%; /* Responsive width */ | |
| max-width: 500px; /* Max width for larger screens */ | |
| } | |
| @media (min-width: 768px) { | |
| .modal-content { | |
| width: 50%; | |
| } | |
| } | |
| /* Custom scrollbar for kanban columns */ | |
| .kanban-column { | |
| max-height: calc(100vh - 250px); /* Adjust based on header/footer height */ | |
| overflow-y: auto; | |
| -ms-overflow-style: none; /* IE and Edge */ | |
| scrollbar-width: none; /* Firefox */ | |
| } | |
| .kanban-column::-webkit-scrollbar { | |
| display: none; /* Chrome, Safari, Opera*/ | |
| } | |
| .dropdown-menu { | |
| display: none; | |
| } | |
| .dropdown:hover .dropdown-menu { | |
| display: block; | |
| } | |
| .admin-only { | |
| display: none; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50"> | |
| <div id="react-sidebar-root"> | |
| </div> | |
| <div class="flex h-screen overflow-hidden" id="main-content"> | |
| <div class="flex flex-col flex-1 overflow-hidden"> | |
| <div class="flex items-center justify-between h-16 px-6 bg-white border-b border-gray-200"> | |
| <button id="mobile-menu-button" class="md:hidden text-gray-500 focus:outline-none"> | |
| <i class="fas fa-bars"></i> | |
| </button> | |
| <div class="flex-1 max-w-md ml-4 md:ml-6"> | |
| <div class="relative"> | |
| <div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none"> | |
| <i class="fas fa-search text-gray-400"></i> | |
| </div> | |
| <input class="block w-full py-2 pl-10 pr-3 text-sm bg-gray-100 border border-transparent rounded-md focus:bg-white focus:border-gray-300 focus:ring-0" placeholder="Tìm kiếm công việc, nhân viên..."> | |
| </div> | |
| </div> | |
| <div class="flex items-center"> | |
| <div class="relative mr-4 dropdown"> | |
| <button class="flex items-center px-3 py-1 text-sm font-medium text-gray-700 bg-gray-100 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <i class="mr-2 fas fa-plus"></i> Tạo mới | |
| </button> | |
| <div class="absolute right-0 z-50 hidden w-48 py-1 mt-2 bg-white rounded-md shadow-lg dropdown-menu"> | |
| <a href="#" id="create-task-btn-top" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Công việc mới</a> | |
| <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Cuộc họp</a> | |
| <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Báo cáo</a> | |
| </div> | |
| </div> | |
| <button class="relative p-1 text-gray-400 rounded-full hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <span class="sr-only">Thông báo</span> | |
| <i class="fas fa-bell"></i> | |
| <span class="absolute top-0 right-0 w-2 h-2 bg-red-500 rounded-full notification-badge"></span> | |
| </button> | |
| <button class="relative p-1 ml-4 text-gray-400 rounded-full hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <span class="sr-only">Tin nhắn</span> | |
| <i class="fas fa-envelope"></i> | |
| <span class="absolute top-0 right-0 w-2 h-2 bg-blue-500 rounded-full notification-badge"></span> | |
| </button> | |
| <div class="relative ml-4 dropdown"> | |
| <button class="flex items-center max-w-xs text-sm rounded-full focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <span class="sr-only">Mở menu người dùng</span> | |
| <img id="user-dropdown-avatar" class="w-8 h-8 rounded-full" src="https://ui-avatars.com/api/?name=User&background=3b82f6&color=fff" alt="User"> | |
| </button> | |
| <div class="absolute right-0 z-50 hidden w-48 py-1 mt-2 bg-white rounded-md shadow-lg dropdown-menu"> | |
| <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Hồ sơ</a> | |
| <a href="#" id="changePasswordBtn" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Đổi mật khẩu</a> | |
| <a href="#" id="logoutButton" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Đăng xuất</a> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="flex-1 overflow-auto p-6 bg-gray-50"> | |
| <div id="dashboard-section" class="content-section active"> | |
| <div class="flex flex-col mb-6 md:flex-row md:items-center md:justify-between"> | |
| <div> | |
| <h1 class="text-2xl font-bold text-gray-900">Dashboard</h1> | |
| <p class="text-gray-600">Tổng quan công việc và hiệu suất toàn hệ thống</p> | |
| </div> | |
| <div class="mt-4 md:mt-0"> | |
| <select class="text-sm border-gray-300 rounded-md focus:border-blue-500 focus:ring-blue-500"> | |
| <option>Hôm nay</option> | |
| <option>Tuần này</option> | |
| <option>Tháng này</option> | |
| <option>Quý này</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="grid grid-cols-1 gap-6 mb-6 sm:grid-cols-2 lg:grid-cols-4" id="stats-cards-container"> | |
| <div class="p-6 bg-white rounded-lg shadow"> | |
| <div class="flex items-center"> | |
| <div class="p-3 bg-blue-100 rounded-full"> | |
| <i class="text-blue-600 fas fa-tasks"></i> | |
| </div> | |
| <div class="ml-4"> | |
| <p class="text-sm font-medium text-gray-500">Tổng công việc</p> | |
| <p id="totalTasks" class="text-2xl font-semibold text-gray-900">0</p> | |
| <p class="text-xs text-gray-500 mt-1"><span class="text-green-500">+0%</span> so với tuần trước</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="p-6 bg-white rounded-lg shadow"> | |
| <div class="flex items-center"> | |
| <div class="p-3 bg-green-100 rounded-full"> | |
| <i class="text-green-600 fas fa-check-circle"></i> | |
| </div> | |
| <div class="ml-4"> | |
| <p class="text-sm font-medium text-gray-500">Đã hoàn thành</p> | |
| <p id="completedTasks" class="text-2xl font-semibold text-gray-900">0</p> | |
| <p class="text-xs text-gray-500 mt-1"><span class="text-green-500">+0%</span> hiệu suất</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="p-6 bg-white rounded-lg shadow"> | |
| <div class="flex items-center"> | |
| <div class="p-3 bg-yellow-100 rounded-full"> | |
| <i class="text-yellow-600 fas fa-exclamation-circle"></i> | |
| </div> | |
| <div class="ml-4"> | |
| <p class="text-sm font-medium text-gray-500">Đang chờ</p> | |
| <p id="pendingTasks" class="text-2xl font-semibold text-gray-900">0</p> | |
| <p class="text-xs text-gray-500 mt-1"><span class="text-red-500">-0%</span> so với tuần trước</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="p-6 bg-white rounded-lg shadow"> | |
| <div class="flex items-center"> | |
| <div class="p-3 bg-red-100 rounded-full"> | |
| <i class="text-red-600 fas fa-clock"></i> | |
| </div> | |
| <div class="ml-4"> | |
| <p class="text-sm font-medium text-gray-500">Quá hạn</p> | |
| <p id="overdueTasks" class="text-2xl font-semibold text-gray-900">0</p> | |
| <p class="text-xs text-gray-500 mt-1"><span class="text-green-500">-0%</span> so với tuần trước</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="grid grid-cols-1 gap-6 lg:grid-cols-3"> | |
| <div class="lg:col-span-2"> | |
| <div class="p-6 mb-6 bg-white rounded-lg shadow"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h2 class="text-lg font-medium text-gray-900">Trạng thái công việc theo phòng ban</h2> | |
| <select class="text-sm border-gray-300 rounded-md focus:border-blue-500 focus:ring-blue-500"> | |
| <option>Tuần này</option> | |
| <option>Tháng này</option> | |
| <option>Quý này</option> | |
| </select> | |
| </div> | |
| <div class="chart-container" style="height: 300px;"> | |
| <canvas id="taskStatusByDepartmentChart"></canvas> | |
| </div> | |
| </div> | |
| <div class="p-6 bg-white rounded-lg shadow"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h2 class="text-lg font-medium text-gray-900">Hiệu suất phòng ban</h2> | |
| <a href="#" class="text-sm font-medium text-blue-600 hover:text-blue-500">Xem chi tiết</a> | |
| </div> | |
| <div id="departmentPerformanceList" class="space-y-4"> | |
| </div> | |
| </div> | |
| </div> | |
| <div> | |
| <div class="p-6 mb-6 bg-white rounded-lg shadow"> | |
| <h2 class="text-lg font-medium text-gray-900 mb-4">Giao việc nhanh</h2> | |
| <form id="quick-assign-form"> | |
| <div class="mb-4"> | |
| <label for="assign-department" class="block text-sm font-medium text-gray-700 mb-1">Phòng ban</label> | |
| <select id="assign-department" class="block w-full text-sm border-gray-300 rounded-md focus:border-blue-500 focus:ring-blue-500"> | |
| <option value="">Chọn phòng ban</option> | |
| </select> | |
| </div> | |
| <div class="mb-4"> | |
| <label for="assign-employee" class="block text-sm font-medium text-gray-700 mb-1">Nhân viên</label> | |
| <select id="assign-employee" class="block w-full text-sm border-gray-300 rounded-md focus:border-blue-500 focus:ring-blue-500"> | |
| <option value="">Chọn nhân viên</option> | |
| </select> | |
| </div> | |
| <div class="mb-4"> | |
| <label for="assign-task-title" class="block text-sm font-medium text-gray-700 mb-1">Công việc</label> | |
| <input type="text" id="assign-task-title" class="block w-full text-sm border-gray-300 rounded-md focus:border-blue-500 focus:ring-blue-500" placeholder="Mô tả công việc" required> | |
| </div> | |
| <div class="mb-4"> | |
| <label for="assign-due-date" class="block text-sm font-medium text-gray-700 mb-1">Hạn chót</label> | |
| <input type="date" id="assign-due-date" class="block w-full text-sm border-gray-300 rounded-md focus:border-blue-500 focus:ring-blue-500" required> | |
| </div> | |
| <button type="submit" class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| Giao việc | |
| </button> | |
| </form> | |
| </div> | |
| <div class="p-6 bg-white rounded-lg shadow"> | |
| <h2 class="text-lg font-medium text-gray-900 mb-4">Hoạt động gần đây</h2> | |
| <div id="recentActivitiesList" class="space-y-4"> | |
| </div> | |
| <a href="#" class="block mt-4 text-sm font-medium text-blue-600 hover:text-blue-500 text-center">Xem tất cả</a> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="mt-8"> | |
| <div class="flex items-center justify-between mb-6"> | |
| <h2 class="text-xl font-bold text-gray-900">Bảng Kanban Công việc (Tổng quan)</h2> | |
| <div class="flex space-x-2"> | |
| <button class="px-3 py-1 text-sm font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <i class="fas fa-plus mr-1"></i> Tạo công việc | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-4" id="kanban-board-dashboard"> | |
| <div id="todoTasks-dashboard" class="p-4 bg-gray-100 rounded-lg kanban-column"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h3 class="font-medium text-gray-700">Cần làm</h3> | |
| <span id="todo-count-dashboard" class="px-2 py-1 text-xs font-medium text-gray-700 bg-gray-200 rounded-full">0</span> | |
| </div> | |
| <div id="kanban-todo-dashboard" class="space-y-4"> | |
| </div> | |
| </div> | |
| <div id="inProgressTasks-dashboard" class="p-4 bg-gray-100 rounded-lg kanban-column"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h3 class="font-medium text-gray-700">Đang thực hiện</h3> | |
| <span id="in-progress-count-dashboard" class="px-2 py-1 text-xs font-medium text-gray-700 bg-gray-200 rounded-full">0</span> | |
| </div> | |
| <div id="kanban-in-progress-dashboard" class="space-y-4"> | |
| </div> | |
| </div> | |
| <div id="reviewTasks-dashboard" class="p-4 bg-gray-100 rounded-lg kanban-column"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h3 class="font-medium text-gray-700">Chờ xét duyệt</h3> | |
| <span id="review-count-dashboard" class="px-2 py-1 text-xs font-medium text-gray-700 bg-gray-200 rounded-full">0</span> | |
| </div> | |
| <div id="kanban-review-dashboard" class="space-y-4"> | |
| </div> | |
| </div> | |
| <div id="completedTasksBoard-dashboard" class="p-4 bg-gray-100 rounded-lg kanban-column"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h3 class="font-medium text-gray-700">Hoàn thành</h3> | |
| <span id="done-count-dashboard" class="px-2 py-1 text-xs font-medium text-gray-700 bg-gray-200 rounded-full">0</span> | |
| </div> | |
| <div id="kanban-done-dashboard" class="space-y-4"> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="mt-8"> | |
| <div class="flex items-center justify-between mb-6"> | |
| <h2 class="text-xl font-bold text-gray-900">Đánh giá hiệu suất nhân viên</h2> | |
| <select class="text-sm border-gray-300 rounded-md focus:border-blue-500 focus:ring-blue-500"> | |
| <option>Tháng 10/2023</option> | |
| <option>Tháng 9/2023</option> | |
| <option>Tháng 8/2023</option> | |
| </select> | |
| </div> | |
| <div class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4"> | |
| <div class="p-6 bg-white rounded-lg shadow department-card"> | |
| <div class="flex flex-col items-center"> | |
| <img class="w-16 h-16 rounded-full mb-3" src="https://ui-avatars.com/api/?name=Nguyễn+Văn+A&background=3b82f6&color=fff" alt="User"> | |
| <h3 class="text-lg font-medium text-gray-900">Nguyễn Văn A</h3> | |
| <p class="text-sm text-gray-500 mb-4">Quản lý kho</p> | |
| <div class="relative performance-meter" style="width: 100px; height: 100px;"> | |
| <svg class="w-full h-full" viewBox="0 0 36 36"> | |
| <path d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" | |
| fill="none" stroke="#eee" stroke-width="3" stroke-dasharray="100, 100" /> | |
| <path d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" | |
| fill="none" stroke="#3b82f6" stroke-width="3" stroke-dasharray="85, 100" /> | |
| </svg> | |
| <div class="absolute inset-0 flex items-center justify-center"> | |
| <span class="text-2xl font-bold text-gray-900">85%</span> | |
| </div> | |
| </div> | |
| <div class="mt-4 text-center"> | |
| <p class="text-sm text-gray-500">Hoàn thành: <span class="font-medium text-gray-900">17/20</span> công việc</p> | |
| <p class="text-sm text-gray-500">Đúng hạn: <span class="font-medium text-gray-900">15</span> công việc</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="p-6 bg-white rounded-lg shadow department-card"> | |
| <div class="flex flex-col items-center"> | |
| <img class="w-16 h-16 rounded-full mb-3" src="https://ui-avatars.com/api/?name=Trần+Thị+B&background=10b981&color=fff" alt="User"> | |
| <h3 class="text-lg font-medium text-gray-900">Trần Thị B</h3> | |
| <p class="text-sm text-gray-500 mb-4">Kế toán</p> | |
| <div class="relative performance-meter" style="width: 100px; height: 100px;"> | |
| <svg class="w-full h-full" viewBox="0 0 36 36"> | |
| <path d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" | |
| fill="none" stroke="#eee" stroke-width="3" stroke-dasharray="100, 100" /> | |
| <path d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" | |
| fill="none" stroke="#10b981" stroke-width="3" stroke-dasharray="92, 100" /> | |
| </svg> | |
| <div class="absolute inset-0 flex items-center justify-center"> | |
| <span class="text-2xl font-bold text-gray-900">92%</span> | |
| </div> | |
| </div> | |
| <div class="mt-4 text-center"> | |
| <p class="text-sm text-gray-500">Hoàn thành: <span class="font-medium text-gray-900">23/25</span> công việc</p> | |
| <p class="text-sm text-gray-500">Đúng hạn: <span class="font-medium text-gray-900">22</span> công việc</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="tasks-section" class="content-section"> | |
| <div class="mt-8"> | |
| <div class="flex items-center justify-between mb-6"> | |
| <h2 class="text-xl font-bold text-gray-900">Bảng Kanban Công việc</h2> | |
| <div class="flex space-x-2"> | |
| <button id="openAddTaskModal" class="px-3 py-1 text-sm font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <i class="fas fa-plus mr-1"></i> Tạo công việc | |
| </button> | |
| <button id="filterTasksBtn" class="px-3 py-1 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <i class="fas fa-filter mr-1"></i> Lọc | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-4" id="kanban-board"> | |
| <div id="todoTasks" class="p-4 bg-gray-100 rounded-lg kanban-column"> | |
| <div class="flex items-center justify-between mb-4" id="kanban-todo-tasks-header"> | |
| <h3 class="font-medium text-gray-700">Cần làm</h3> | |
| <span id="todo-count" class="px-2 py-1 text-xs font-medium text-gray-700 bg-gray-200 rounded-full">0</span> | |
| </div> | |
| <div id="kanban-todo" class="space-y-4"> | |
| </div> | |
| </div> | |
| <div id="inProgressTasks" class="p-4 bg-gray-100 rounded-lg kanban-column"> | |
| <div class="flex items-center justify-between mb-4" id="kanban-in-progress-tasks-header"> | |
| <h3 class="font-medium text-gray-700">Đang thực hiện</h3> | |
| <span id="in-progress-count" class="px-2 py-1 text-xs font-medium text-gray-700 bg-gray-200 rounded-full">0</span> | |
| </div> | |
| <div id="kanban-in-progress" class="space-y-4"> | |
| </div> | |
| </div> | |
| <div id="reviewTasks" class="p-4 bg-gray-100 rounded-lg kanban-column"> | |
| <div class="flex items-center justify-between mb-4" id="kanban-review-tasks-header"> | |
| <h3 class="font-medium text-gray-700">Chờ xét duyệt</h3> | |
| <span id="review-count" class="px-2 py-1 text-xs font-medium text-gray-700 bg-gray-200 rounded-full">0</span> | |
| </div> | |
| <div id="kanban-review" class="space-y-4"> | |
| </div> | |
| </div> | |
| <div id="completedTasksBoard" class="p-4 bg-gray-100 rounded-lg kanban-column"> | |
| <div class="flex items-center justify-between mb-4" id="kanban-done-tasks-header"> | |
| <h3 class="font-medium text-gray-700">Hoàn thành</h3> | |
| <span id="done-count" class="px-2 py-1 text-xs font-medium text-gray-700 bg-gray-200 rounded-full">0</span> | |
| </div> | |
| <div id="kanban-done" class="space-y-4"> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="personnel-section" class="content-section"> | |
| <div class="mt-8"> | |
| <div class="flex items-center justify-between mb-6"> | |
| <h2 class="text-xl font-bold text-gray-900">Quản lý Nhân sự</h2> | |
| <select class="text-sm border-gray-300 rounded-md focus:border-blue-500 focus:ring-blue-500"> | |
| <option>Tháng 10/2023</option> | |
| <option>Tháng 9/2023</option> | |
| <option>Tháng 8/2023</option> | |
| </select> | |
| </div> | |
| <div id="employeePerformanceList" class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4"> | |
| </div> | |
| </div> | |
| <div id="users-list-container" class="mt-8"> | |
| <h2 class="text-xl font-bold text-gray-900 mb-4">Danh sách Người dùng (<span id="totalUsers">0</span>)</h2> | |
| <div class="flex justify-end mb-4 admin-only"> <button id="openAddUserModal" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 transition duration-200"> | |
| <i class="fas fa-user-plus mr-2"></i> Thêm người dùng mới | |
| </button> | |
| </div> | |
| <div class="p-6 bg-white rounded-lg shadow"> | |
| <ul id="usersList" class="divide-y divide-gray-200"> | |
| </ul> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="departments-section" class="content-section"> | |
| <div class="mt-8"> | |
| <h2 class="text-2xl font-bold text-gray-900 mb-4">Quản lý Phòng ban</h2> | |
| <div class="flex justify-end mb-4 admin-only"> <button id="openAddDepartmentModal" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 transition duration-200"> | |
| <i class="fas fa-plus mr-2"></i> Thêm phòng ban mới | |
| </button> | |
| </div> | |
| <div class="p-6 bg-white rounded-lg shadow"> | |
| <h3 class="text-lg font-medium text-gray-900 mb-4">Danh sách Phòng ban</h3> | |
| <ul id="departmentsList" class="divide-y divide-gray-200"> | |
| </ul> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="reports-section" class="content-section"> | |
| <h1 class="text-2xl font-bold text-gray-900 mb-4">Báo cáo & Thống kê</h1> | |
| <p class="text-gray-600 mb-6">Tổng hợp các báo cáo hiệu suất và hoạt động.</p> | |
| <div class="p-6 bg-white rounded-lg shadow"> | |
| <h3 class="text-lg font-medium text-gray-900 mb-4">Báo cáo tổng quan</h3> | |
| <p class="text-gray-700">Nội dung báo cáo sẽ được hiển thị tại đây.</p> | |
| </div> | |
| </div> | |
| <div id="calendar-section" class="content-section"> | |
| <h1 class="text-2xl font-bold text-gray-900 mb-4">Lịch làm việc</h1> | |
| <p class="text-gray-600 mb-6">Quản lý lịch làm việc và các sự kiện.</p> | |
| <div class="p-6 bg-white rounded-lg shadow"> | |
| <h3 class="text-lg font-medium text-gray-900 mb-4">Lịch biểu</h3> | |
| <p class="text-gray-700">Nội dung lịch làm việc sẽ được hiển thị tại đây.</p> | |
| </div> | |
| </div> | |
| <div id="settings-section" class="content-section"> | |
| <h1 class="text-2xl font-bold text-gray-900 mb-4">Cài đặt hệ thống</h1> | |
| <p class="text-gray-600 mb-6">Cấu hình các tùy chọn của ứng dụng.</p> | |
| <div class="p-6 bg-white rounded-lg shadow"> | |
| <h3 class="text-lg font-medium text-gray-900 mb-4">Tùy chọn chung</h3> | |
| <p class="text-gray-700">Nội dung cài đặt sẽ được hiển thị tại đây.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="loginModal" class="modal"> | |
| <div class="modal-content"> | |
| <h3 class="text-2xl font-bold text-center text-gray-900 mb-6">Đăng nhập</h3> | |
| <form id="loginForm" class="space-y-4"> | |
| <div> | |
| <label for="login-email" class="sr-only">Email</label> | |
| <input type="email" id="login-email" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" placeholder="Email" required> | |
| </div> | |
| <div> | |
| <label for="login-password" class="sr-only">Mật khẩu</label> | |
| <input type="password" id="login-password" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" placeholder="Mật khẩu" required> | |
| </div> | |
| <p id="login-error-message" class="text-red-500 text-sm text-center hidden"></p> | |
| <button type="submit" id="vanillaLoginButton" class="w-full bg-blue-600 text-white py-2 rounded-md hover:bg-blue-700 transition duration-200">Đăng nhập</button> | |
| </form> | |
| <div class="mt-4 text-center"> | |
| <a href="#" id="showResetPassword" class="text-blue-600 hover:underline text-sm">Quên mật khẩu?</a> | |
| <p class="text-sm text-gray-600 mt-2">Chưa có tài khoản? <a href="#" id="showRegister" class="text-blue-600 hover:underline">Đăng ký ngay</a></p> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="registerModal" class="modal"> | |
| <div class="modal-content"> | |
| <h3 class="text-2xl font-bold text-center text-gray-900 mb-6">Đăng ký</h3> | |
| <form id="registerForm" class="space-y-4"> | |
| <div> | |
| <label for="register-name" class="sr-only">Tên của bạn</label> | |
| <input type="text" id="register-name" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" placeholder="Tên của bạn" required> | |
| </div> | |
| <div> | |
| <label for="register-email" class="sr-only">Email</label> | |
| <input type="email" id="register-email" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" placeholder="Email" required> | |
| </div> | |
| <div> | |
| <label for="register-password" class="sr-only">Mật khẩu</label> | |
| <input type="password" id="register-password" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" placeholder="Mật khẩu (ít nhất 6 ký tự)" required> | |
| </div> | |
| <button type="submit" id="registerButton" class="w-full bg-green-600 text-white py-2 rounded-md hover:bg-green-700 transition duration-200">Đăng ký</button> | |
| </form> | |
| <div class="mt-4 text-center"> | |
| <p class="text-sm text-gray-600">Đã có tài khoản? <a href="#" id="showLoginFromRegister" class="text-blue-600 hover:underline close-modal">Đăng nhập</a></p> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="resetPasswordModal" class="modal"> | |
| <div class="modal-content"> | |
| <h3 class="text-2xl font-bold text-center text-gray-900 mb-6">Đặt lại mật khẩu</h3> | |
| <form id="resetPasswordForm" class="space-y-4"> | |
| <div> | |
| <label for="reset-email" class="sr-only">Email</label> | |
| <input type="email" id="reset-email" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" placeholder="Nhập email của bạn" required> | |
| </div> | |
| <button type="submit" id="resetPasswordSubmit" class="w-full bg-blue-600 text-white py-2 rounded-md hover:bg-blue-700 transition duration-200">Gửi liên kết đặt lại</button> | |
| </form> | |
| <div class="mt-4 text-center"> | |
| <p class="text-sm text-gray-600">Quay lại <a href="#" id="showLoginFromReset" class="text-blue-600 hover:underline close-modal">Đăng nhập</a></p> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="changePasswordModal" class="modal"> | |
| <div class="modal-content"> | |
| <h3 class="text-2xl font-bold text-center text-gray-900 mb-6">Đổi mật khẩu</h3> | |
| <form id="changePasswordForm" class="space-y-4"> | |
| <div> | |
| <label for="new-password" class="sr-only">Mật khẩu mới</label> | |
| <input type="password" id="new-password" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" placeholder="Mật khẩu mới (ít nhất 6 ký tự)" required> | |
| </div> | |
| <div> | |
| <label for="confirm-new-password" class="sr-only">Xác nhận mật khẩu mới</label> | |
| <input type="password" id="confirm-new-password" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" placeholder="Xác nhận mật khẩu mới" required> | |
| </div> | |
| <button type="submit" id="updatePasswordSubmit" class="w-full bg-blue-600 text-white py-2 rounded-md hover:bg-blue-700 transition duration-200">Cập nhật mật khẩu</button> | |
| </form> | |
| <div class="mt-4 text-center"> | |
| <button type="button" class="text-gray-600 hover:underline text-sm close-modal">Hủy</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="messageModal" class="modal"> | |
| <div class="modal-content"> | |
| <h3 id="messageModalTitle" class="text-xl font-semibold text-gray-900 mb-4"></h3> | |
| <p id="messageModalContent" class="text-gray-700 mb-6"></p> | |
| <div class="flex justify-end"> | |
| <button type="button" class="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700 close-modal">Đóng</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="confirmModal" class="modal"> | |
| <div class="modal-content"> | |
| <h3 id="confirmModalTitle" class="text-xl font-semibold text-gray-900 mb-4">Xác nhận</h3> | |
| <p id="confirmModalContent" class="text-gray-700 mb-6"></p> | |
| <div class="flex justify-end space-x-3"> | |
| <button type="button" id="confirmCancelBtn" class="px-4 py-2 text-gray-700 bg-gray-200 rounded-md hover:bg-gray-300 close-modal">Hủy</button> | |
| <button type="button" id="confirmProceedBtn" class="px-4 py-2 text-white bg-red-600 rounded-md hover:bg-red-700">Xác nhận</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="addDepartmentModal" class="modal"> | |
| <div class="modal-content"> | |
| <h3 class="text-2xl font-bold text-center text-gray-900 mb-6">Thêm phòng ban</h3> | |
| <form id="addDepartmentForm" class="space-y-4"> | |
| <div> | |
| <label for="departmentName" class="block text-sm font-medium text-gray-700">Tên phòng ban</label> | |
| <input type="text" id="departmentName" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" required> | |
| </div> | |
| <div class="flex justify-end space-x-3"> | |
| <button type="button" class="px-4 py-2 text-gray-700 bg-gray-200 rounded-md hover:bg-gray-300 close-modal">Hủy</button> | |
| <button type="submit" id="saveDepartmentBtn" class="px-4 py-2 text-white bg-blue-600 rounded-md hover:bg-blue-700">Lưu</button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| <div id="editDepartmentModal" class="modal"> | |
| <div class="modal-content"> | |
| <h3 class="text-2xl font-bold text-center text-gray-900 mb-6">Sửa phòng ban</h3> | |
| <form id="editDepartmentForm" class="space-y-4"> | |
| <input type="hidden" id="editDepartmentId"> | |
| <div> | |
| <label for="editDepartmentName" class="block text-sm font-medium text-gray-700">Tên phòng ban</label> | |
| <input type="text" id="editDepartmentName" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" required> | |
| </div> | |
| <div class="flex justify-end space-x-3"> | |
| <button type="button" class="px-4 py-2 text-gray-700 bg-gray-200 rounded-md hover:bg-gray-300 close-modal">Hủy</button> | |
| <button type="submit" id="updateDepartmentBtn" class="px-4 py-2 text-white bg-blue-600 rounded-md hover:bg-blue-700">Cập nhật</button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| <div id="addUserModal" class="modal"> | |
| <div class="modal-content"> | |
| <h3 id="userModalTitle" class="text-2xl font-bold text-center text-gray-900 mb-6">Thêm người dùng</h3> | |
| <form id="addUserForm" class="space-y-4"> | |
| <div> | |
| <label for="addUserName" class="block text-sm font-medium text-gray-700">Tên người dùng</label> | |
| <input type="text" id="addUserName" name="userName" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" required> | |
| </div> | |
| <div> | |
| <label for="addUserEmail" class="block text-sm font-medium text-gray-700">Email</label> | |
| <input type="email" id="addUserEmail" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" required> | |
| </div> | |
| <div> | |
| <label for="addUserPassword" class="block text-sm font-medium text-gray-700">Mật khẩu</label> | |
| <input type="password" id="addUserPassword" name="addUserPassword" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" placeholder="Ít nhất 6 ký tự" required> | |
| </div> | |
| <div> | |
| <label for="addUserRole" class="block text-sm font-medium text-gray-700">Vai trò</label> | |
| <select id="addUserRole" name="addUserRole" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500"> | |
| <option value="employee">Nhân viên</option> | |
| <option value="admin" class="admin-only">Quản trị viên</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="addUserDepartment" class="block text-sm font-medium text-gray-700">Phòng ban</label> | |
| <select id="addUserDepartment" name="department" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500"> | |
| </select> | |
| </div> | |
| <div class="flex justify-end space-x-3"> | |
| <button type="button" class="px-4 py-2 text-gray-700 bg-gray-200 rounded-md hover:bg-gray-300 close-modal">Hủy</button> | |
| <button type="submit" id="saveUserBtn" class="px-4 py-2 text-white bg-blue-600 rounded-md hover:bg-blue-700">Lưu</button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| <div id="editUserModal" class="modal"> | |
| <div class="modal-content"> | |
| <h3 id="editUserModalLabel" class="text-2xl font-bold text-center text-gray-900 mb-6">Sửa người dùng</h3> | |
| <form id="editUserForm" class="space-y-4"> | |
| <input type="hidden" id="editUserId"> | |
| <div> | |
| <label for="editUserName" class="block text-sm font-medium text-gray-700">Tên người dùng</label> | |
| <input type="text" id="editUserName" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" required> | |
| </div> | |
| <div> | |
| <label for="editUserEmail" class="block text-sm font-medium text-gray-700">Email</label> | |
| <input type="email" id="editUserEmail" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" required> | |
| </div> | |
| <div> | |
| <label for="editUserRole" class="block text-sm font-medium text-gray-700">Vai trò</label> | |
| <select id="editUserRole" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500"> | |
| <option value="employee">Nhân viên</option> | |
| <option value="admin">Quản trị viên</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="editUserDepartment" class="block text-sm font-medium text-gray-700">Phòng ban</label> | |
| <select id="editUserDepartment" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500"> | |
| </select> | |
| </div> | |
| <div class="flex justify-end space-x-3"> | |
| <button type="button" class="px-4 py-2 text-gray-700 bg-gray-200 rounded-md hover:bg-gray-300 close-modal">Hủy</button> | |
| <button type="submit" id="updateUserBtn" class="px-4 py-2 text-white bg-blue-600 rounded-md hover:bg-blue-700">Cập nhật</button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| <div id="addTaskModal" class="modal"> | |
| <div class="modal-content"> | |
| <h3 class="text-2xl font-bold text-center text-gray-900 mb-6" id="taskModalTitle">Thêm công việc</h3> | |
| <form id="taskForm" class="space-y-4"> | |
| <input type="hidden" id="taskId"> | |
| <div> | |
| <label for="taskTitle" class="block text-sm font-medium text-gray-700">Tiêu đề công việc</label> | |
| <input id="taskTitle" name="taskTitle" type="text" class="w-full p-2 border rounded-md mt-1 focus:ring-blue-500 focus:border-blue-500" required> | |
| </div> | |
| <div> | |
| <label for="taskDescription" class="block text-sm font-medium text-gray-700">Mô tả</label> | |
| <textarea id="taskDescription" name="taskDescription" rows="3" class="w-full p-2 border rounded-md mt-1 focus:ring-blue-500 focus:border-blue-500"></textarea> | |
| </div> | |
| <div> | |
| <label for="taskDepartment" class="block text-sm font-medium text-gray-700">Phòng ban</label> | |
| <select id="taskDepartment" class="w-full p-2 border rounded-md mt-1 focus:ring-blue-500 focus:border-blue-500" required> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="taskAssignedTo" class="block text-sm font-medium text-gray-700">Người thực hiện</label> | |
| <select id="taskAssignedTo" class="w-full p-2 border rounded-md mt-1 focus:ring-blue-500 focus:border-blue-500" required> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="taskPriority" class="block text-sm font-medium text-gray-700">Mức độ ưu tiên</label> | |
| <select id="taskPriority" class="w-full p-2 border rounded-md mt-1 focus:ring-blue-500 focus:border-blue-500"> | |
| <option value="Cao">Cao</option> | |
| <option value="Trung bình" selected>Trung bình</option> | |
| <option value="Thấp">Thấp</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="taskProgress" class="block text-sm font-medium text-gray-700">Tiến độ (%)</label> | |
| <input id="taskProgress" type="number" min="0" max="100" value="0" class="w-full p-2 border rounded-md mt-1 focus:ring-blue-500 focus:border-blue-500"> | |
| </div> | |
| <div> | |
| <label for="taskDueDate" class="block text-sm font-medium text-gray-700">Ngày hết hạn</label> | |
| <input id="taskDueDate" type="date" class="w-full p-2 border rounded-md mt-1 focus:ring-blue-500 focus:border-blue-500"> | |
| </div> | |
| <div> | |
| <label for="taskStatus" class="block text-sm font-medium text-gray-700">Trạng thái</label> | |
| <select id="taskStatus" name="taskStatus" class="w-full p-2 border rounded-md mt-1 focus:ring-blue-500 focus:border-blue-500"> | |
| <option value="Cần làm">Cần làm</option> | |
| <option value="Đang tiến hành">Đang tiến hành</option> | |
| <option value="Đã duyệt">Đã duyệt</option> | |
| <option value="Từ chối">Từ chối</option> | |
| <option value="Hoàn thành">Hoàn thành</option> | |
| </select> | |
| </div> | |
| <div class="flex justify-end space-x-3 mt-6"> | |
| <button type="button" id="deleteTaskBtn" class="hidden px-4 py-2 text-white bg-red-600 rounded-md hover:bg-red-700">Xóa</button> | |
| <button type="button" class="px-4 py-2 text-gray-700 bg-gray-200 rounded-md hover:bg-gray-300 close-modal">Hủy</button> | |
| <button type="submit" id="saveTaskBtn" class="px-4 py-2 text-white bg-blue-600 rounded-md hover:bg-blue-700">Lưu</button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| <div id="taskDetailModal" class="modal"> | |
| <div class="modal-content w-full max-w-7xl max-h-[90vh] overflow-y-auto p-6 relative bg-white rounded-xl shadow-lg border border-gray-200"> | |
| <button class="absolute top-4 right-4 text-gray-400 hover:text-gray-800 transition close-modal"> | |
| <i class="fas fa-times text-xl"></i> | |
| </button> | |
| <span id="detailTaskId" class="hidden"></span> | |
| <h3 id="detailTaskTitle" class="text-2xl font-bold text-gray-800 mb-4">Chi tiết công việc</h3> | |
| <div id="detailTaskBody" class="mb-6 text-sm text-gray-700 leading-relaxed space-y-2 bg-gray-50 p-4 rounded border border-gray-200 shadow-sm"> | |
| </div> | |
| <div> | |
| <h4 class="text-lg font-semibold text-gray-800 mb-2">Bình luận</h4> | |
| <div id="commentList" class="space-y-3 max-h-72 overflow-y-auto border rounded-md bg-white p-3 shadow-inner"> | |
| </div> | |
| <form id="commentForm" class="mt-4 space-y-2"> | |
| <textarea id="commentText" class="w-full border border-gray-300 rounded-md p-3 text-sm shadow-sm focus:outline-none focus:ring focus:border-blue-500" rows="3" placeholder="Nhập bình luận..."></textarea> | |
| <button type="submit" class="bg-blue-600 text-white px-5 py-2 rounded-md hover:bg-blue-700 transition">Gửi bình luận</button> | |
| </form> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', () => { | |
| const contentSections = document.querySelectorAll('.content-section'); | |
| window.showVanillaSection = function(targetId) { | |
| console.log("VanillaJS: showVanillaSection called for", targetId); | |
| contentSections.forEach(section => { | |
| section.classList.remove('active'); | |
| }); | |
| const targetSection = document.getElementById(targetId); | |
| if (targetSection) { | |
| targetSection.classList.add('active'); | |
| } | |
| } | |
| function handleVanillaHashChangeInitial() { | |
| const hash = window.location.hash.substring(1) || 'dashboard-section'; | |
| window.showVanillaSection(hash); | |
| if (window.reactBridge && window.reactBridge.updateActiveSection) { | |
| console.log("VanillaJS: Initial hash check, updating React bridge with active section:", hash); | |
| window.reactBridge.updateActiveSection(hash); | |
| } | |
| } | |
| // window.addEventListener('hashchange', handleVanillaHashChangeInitial); // Removed, only listeners.js should handle | |
| setTimeout(() => { | |
| console.log("VanillaJS: Initial section display. Relying on listeners.js now."); | |
| // handleVanillaHashChangeInitial(); // Removed, handled by listeners.js | |
| }, 200); | |
| const mobileMenuButton = document.getElementById('mobile-menu-button'); | |
| if (mobileMenuButton) { | |
| mobileMenuButton.addEventListener('click', () => { | |
| if (window.reactBridge && window.reactBridge.setMobileMenuOpen) { | |
| console.log("VanillaJS: mobile-menu-button clicked, calling reactBridge.setMobileMenuOpen(true)"); | |
| window.reactBridge.setMobileMenuOpen(true); | |
| } else { | |
| console.warn("VanillaJS: mobile-menu-button clicked, but reactBridge or setMobileMenuOpen is not available."); | |
| } | |
| }); | |
| } | |
| // Đóng modal khi click nút .close-modal (cho các modal thuần) | |
| document.querySelectorAll('.modal .close-modal').forEach(button => { | |
| button.addEventListener('click', () => { | |
| const modal = button.closest('.modal'); | |
| if (modal) { | |
| modal.style.display = 'none'; | |
| } | |
| }); | |
| }); | |
| }); | |
| </script> | |
| <script type="module" src="public/js/utils/eventBus.js"></script> | |
| <script type="module" src="public/js/firebase-init.js"></script> | |
| <script type="module" src="public/js/utils/utils.js"></script> | |
| <script type="module" src="public/js/utils/errorHandler.js"></script> | |
| <script type="module" src="public/js/utils/dropdownHelpers.js"></script> | |
| <script type="module" src="public/js/services/userService.js"></script> | |
| <script type="module" src="public/js/services/departmentService.js"></script> | |
| <script type="module" src="public/js/services/taskService.js"></script> | |
| <script type="module" src="public/js/services/commentService.js"></script> <script type="module" src="public/js/managers/userManager.js"></script> | |
| <script type="module" src="public/js/managers/departmentManager.js"></script> | |
| <script type="module" src="public/js/managers/taskManager.js"></script> | |
| <script type="module" src="public/js/auth.js"></script> | |
| <script type="module" src="public/js/modal.js"></script> | |
| <script type="module" src="public/js/departments.js"></script> | |
| <script type="module" src="public/js/users.js"></script> | |
| <script type="module" src="public/js/tasks.js"></script> | |
| <script type="module" src="public/js/comments.js"></script> | |
| <script type="module" src="public/js/kanban.js"></script> | |
| <script type="module" src="public/js/dashboard.js"></script> | |
| <script type="module" src="public/js/listeners.js"></script> | |
| <script type="module" src="public/js/index.js"></script> <script type="module" src="/src/main.jsx"></script> | |
| </body> | |
| </html> |