alsaifkhan/pharmasafe-adr-tracker
0
1<!DOCTYPE html>2<html lang="en">3<head>4 <meta charset="UTF-8">5 <meta name="viewport" content="width=device-width, initial-scale=1.0">6 <title>PS-ADR | Admin Panel</title>7 <link rel="icon" type="image/x-icon" href="/static/favicon.ico">8 <script src="https://cdn.tailwindcss.com"></script>9 <script src="https://unpkg.com/feather-icons"></script>10 <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>11 <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"></script>12 <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-database.js"></script>13 <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-auth.js"></script>14 <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>15 <style>16 .sidebar {17 min-height: calc(100vh - 4rem);18 }19 .file-upload:hover {20 background-color: #f0f9ff;21 border-color: #3b82f6;22 }23 </style>24</head>25<body class="bg-gray-100 font-sans">26 <div class="flex">27 <!-- Sidebar -->28 <div class="bg-blue-800 text-white w-64 sidebar sticky top-0">29 <div class="p-4 border-b border-blue-700">30 <h2 class="text-xl font-bold">PS-ADR Admin</h2>31 </div>32 <nav class="mt-4">33 <div>34 <a href="#" class="block py-2 px-4 bg-blue-700">35 <i data-feather="home" class="inline mr-2 w-4 h-4"></i> Dashboard36 </a>37 <a href="#drugs" class="block py-2 px-4 hover:bg-blue-700">38 <i data-feather="package" class="inline mr-2 w-4 h-4"></i> Drug Management39 </a>40 <a href="#reports" class="block py-2 px-4 hover:bg-blue-700">41 <i data-feather="file-text" class="inline mr-2 w-4 h-4"></i> ADR Reports42 </a>43 <a href="#users" class="block py-2 px-4 hover:bg-blue-700">44 <i data-feather="users" class="inline mr-2 w-4 h-4"></i> User Management45 </a>46 <a href="#analytics" class="block py-2 px-4 hover:bg-blue-700">47 <i data-feather="bar-chart-2" class="inline mr-2 w-4 h-4"></i> Analytics48 </a>49 <a href="#settings" class="block py-2 px-4 hover:bg-blue-700">50 <i data-feather="settings" class="inline mr-2 w-4 h-4"></i> Settings51 </a>52 </div>53 </nav>54 </div>55 56 <!-- Main Content -->57 <div class="flex-1">58 <!-- Header -->59 <header class="bg-white shadow-sm p-4 flex justify-between items-center">60 <h1 class="text-2xl font-bold text-gray-800">Admin Dashboard</h1>61 <div>62 <span class="mr-4 text-gray-600">Welcome, Admin</span>63 <button id="logoutBtn" class="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded">64 <i data-feather="log-out" class="inline mr-1 w-4 h-4"></i> Logout65 </button>66 </div>67 </header>68 69 <!-- Dashboard Content -->70 <main class="p-6">71 <div id="dashboardContent">72 <!-- Stats Cards -->73 <div class="grid md:grid-cols-4 gap-6 mb-8">74 <div class="bg-white p-6 rounded-lg shadow">75 <div class="flex justify-between">76 <div>77 <p class="text-gray-500">Total Drugs</p>78 <h3 class="text-2xl font-bold" id="adminDrugsCount">0</h3>79 </div>80 <div class="bg-blue-100 p-3 rounded-full">81 <i data-feather="package" class="text-blue-600 w-6 h-6"></i>82 </div>83 </div>84 </div>85 <div class="bg-white p-6 rounded-lg shadow">86 <div class="flex justify-between">87 <div>88 <p class="text-gray-500">ADR Reports</p>89 <h3 class="text-2xl font-bold" id="adminReportsCount">0</h3>90 </div>91 <div class="bg-green-100 p-3 rounded-full">92 <i data-feather="file-text" class="text-green-600 w-6 h-6"></i>93 </div>94 </div>95 </div>96 <div class="bg-white p-6 rounded-lg shadow">97 <div class="flex justify-between">98 <div>99 <p class="text-gray-500">Active Users</p>100 <h3 class="text-2xl font-bold" id="adminUsersCount">0</h3>101 </div>102 <div class="bg-purple-100 p-3 rounded-full">103 <i data-feather="users" class="text-purple-600 w-6 h-6"></i>104 </div>105 </div>106 </div>107 <div class="bg-white p-6 rounded-lg shadow">108 <div class="flex justify-between">109 <div>110 <p class="text-gray-500">Safety Signals</p>111 <h3 class="text-2xl font-bold" id="adminSignalsCount">0</h3>112 </div>113 <div class="bg-yellow-100 p-3 rounded-full">114 <i data-feather="alert-triangle" class="text-yellow-600 w-6 h-6"></i>115 </div>116 </div>117 </div>118 </div>119 120 <!-- Drug Management Section -->121 <section id="drugs" class="mb-12">122 <div class="bg-white rounded-lg shadow overflow-hidden">123 <div class="p-4 bg-gray-50 border-b flex justify-between items-center">124 <h2 class="text-xl font-semibold">Drug Management</h2>125 <button class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded flex items-center" id="addDrugBtn">126 <i data-feather="plus" class="mr-1 w-4 h-4"></i> Add Drug127 </button>128 </div>129 <div class="p-4">130 <!-- Excel Upload -->131 <div class="mb-6 p-4 border-2 border-dashed border-gray-300 rounded-lg file-upload transition duration-300">132 <div class="text-center">133 <i data-feather="upload-cloud" class="mx-auto w-10 h-10 text-blue-500 mb-2"></i>134 <h3 class="text-lg font-medium text-gray-700">Upload Excel File</h3>135 <p class="text-sm text-gray-500 mb-3">Drag & drop your Excel file here or click to browse</p>136 <input type="file" id="excelUpload" accept=".xlsx, .xls" class="hidden">137 <label for="excelUpload" class="cursor-pointer bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded inline-block">138 Select File139 </label>140 <p class="text-xs text-gray-400 mt-2">Supported formats: .xlsx, .xls</p>141 </div>142 </div>143 144 <!-- Drug Table -->145 <div class="overflow-x-auto">146 <table class="min-w-full bg-white">147 <thead>148 <tr class="bg-gray-100 text-gray-700">149 <th class="py-3 px-4 text-left">Drug Name</th>150 <th class="py-3 px-4 text-left">Generic Name</th>151 <th class="py-3 px-4 text-left">Categories</th>152 <th class="py-3 px-4 text-left">Actions</th>153 </tr>154 </thead>155 <tbody id="drugsTableBody" class="divide-y divide-gray-200">156 <!-- Drugs will be populated here -->157 </tbody>158 </table>159 </div>160 </div>161 </div>162 </section>163 164 <!-- Add Drug Modal -->165 <div id="addDrugModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50">166 <div class="bg-white rounded-lg shadow-xl w-full max-w-md">167 <div class="p-4 border-b flex justify-between items-center">168 <h3 class="text-lg font-semibold">Add New Drug</h3>169 <button id="closeModalBtn" class="text-gray-500 hover:text-gray-700">170 <i data-feather="x"></i>171 </button>172 </div>173 <div class="p-4">174 <form id="drugForm">175 <div class="mb-4">176 <label class="block text-gray-700 mb-2">Drug Name</label>177 <input type="text" id="drugName" class="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" required>178 </div>179 <div class="mb-4">180 <label class="block text-gray-700 mb-2">Generic Name</label>181 <input type="text" id="genericName" class="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" required>182 </div>183 <div class="mb-4">184 <label class="block text-gray-700 mb-2">Description</label>185 <textarea id="drugDescription" rows="3" class="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"></textarea>186 </div>187 <div class="mb-4">188 <label class="block text-gray-700 mb-2">Categories (comma separated)</label>189 <input type="text" id="drugCategories" class="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="e.g., Cardiovascular, Analgesic">190 </div>191 <div class="flex justify-end">192 <button type="button" id="cancelDrugBtn" class="mr-2 bg-gray-200 hover:bg-gray-300 text-gray-800 px-4 py-2 rounded-lg">Cancel</button>193 <button type="submit" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg">Save Drug</button>194 </div>195 </form>196 </div>197 </div>198 </div>199 </div>200 </main>201 </div>202 </div>203 204 <!-- Firebase Configuration -->205 <script>206 // Your web app's Firebase configuration207 const firebaseConfig = {208 apiKey: "AIzaSyAEXAMPLEKEY",209 authDomain: "ps-adr.firebaseapp.com",210 databaseURL: "https://ps-adr-default-rtdb.firebaseio.com",211 projectId: "ps-adr",212 storageBucket: "ps-adr.appspot.com",213 messagingSenderId: "123456789012",214 appId: "1:123456789012:web:abcdef1234567890"215 };216 217 // Initialize Firebase218 firebase.initializeApp(firebaseConfig);219 const database = firebase.database();220 const auth = firebase.auth();221 222 // Check authentication state223 auth.onAuthStateChanged((user) => {224 if (!user) {225 window.location.href = 'admin-login.html';226 } else {227 // User is signed in228 loadAdminData();229 }230 });231 232 // Logout function233 document.getElementById('logoutBtn').addEventListener('click', () => {234 auth.signOut().then(() => {235 window.location.href = 'admin-login.html';236 });237 });238 239 // Load admin data240 function loadAdminData() {241 // Reference to statistics242 const statsRef = database.ref('statistics');243 statsRef.on('value', (snapshot) => {244 const statsData = snapshot.val();245 if (statsData) {246 document.getElementById('adminDrugsCount').textContent = statsData.drugsCount;247 document.getElementById('adminReportsCount').textContent = statsData.reportsCount;248 document.getElementById('adminUsersCount').textContent = statsData.usersCount;249 document.getElementById('adminSignalsCount').textContent = statsData.signalsCount;250 }251 });252 253 // Reference to drugs database254 const drugsRef = database.ref('drugs');255 drugsRef.on('value', (snapshot) => {256 const drugsData = snapshot.val();257 const drugsTableBody = document.getElementById('drugsTableBody');258 drugsTableBody.innerHTML = '';259 260 if (drugsData) {261 Object.entries(drugsData).forEach(([key, drug]) => {262 const row = document.createElement('tr');263 row.className = 'hover:bg-gray-50';264 row.innerHTML = `265 <td class="py-3 px-4">${drug.name}</td>266 <td class="py-3 px-4">${drug.genericName}</td>267 <td class="py-3 px-4">268 <div class="flex flex-wrap gap-1">269 ${drug.categories.map(cat => `<span class="bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded">${cat}</span>`).join('')}270 </div>271 </td>272 <td class="py-3 px-4">273 <button class="text-blue-600 hover:text-blue-800 mr-2 edit-drug" data-id="${key}">274 <i data-feather="edit" class="w-4 h-4"></i>275 </button>276 <button class="text-red-600 hover:text-red-800 delete-drug" data-id="${key}">277 <i data-feather="trash-2" class="w-4 h-4"></i>278 </button>279 </td>280 `;281 drugsTableBody.appendChild(row);282 });283 feather.replace();284 }285 });286 }287 288 // Modal management289 const addDrugModal = document.getElementById('addDrugModal');290 const addDrugBtn = document.getElementById('addDrugBtn');291 const closeModalBtn = document.getElementById('closeModalBtn');292 const cancelDrugBtn = document.getElementById('cancelDrugBtn');293 const drugForm = document.getElementById('drugForm');294 295 addDrugBtn.addEventListener('click', () => {296 addDrugModal.classList.remove('hidden');297 });298 299 closeModalBtn.addEventListener('click', () => {300 addDrugModal.classList.add('hidden');301 });302 303 cancelDrugBtn.addEventListener('click', () => {304 addDrugModal.classList.add('hidden');305 });306 307 // Handle form submission308 drugForm.addEventListener('submit', (e) => {309 e.preventDefault();310 311 const drugName = document.getElementById('drugName').value;312 const genericName = document.getElementById('genericName').value;313 const drugDescription = document.getElementById('drugDescription').value;314 const categoriesInput = document.getElementById('drugCategories').value;315 316 const categories = categoriesInput.split(',').map(cat => cat.trim()).filter(cat => cat.length > 0);317 318 const drugsRef = database.ref('drugs');319 const newDrugRef = drugsRef.push();320 321 newDrugRef.set({322 name: drugName,323 genericName: genericName,324 description: drugDescription,325 categories: categories || []326 }).then(() => {327 addDrugModal.classList.add('hidden');328 drugForm.reset();329 330 // Update statistics331 const statsRef = database.ref('statistics/drugsCount');332 statsRef.transaction((currentCount) => {333 return (currentCount || 0) + 1;334 });335 });336 });337 338 // Excel file upload functionality339 document.getElementById('excelUpload').addEventListener('change', function(e) {340 const file = e.target.files[0];341 if (!file) return;342 343 const reader = new FileReader();344 reader.onload = function(e) {345 const data = new Uint8Array(e.target.result);346 const workbook = XLSX.read(data, { type: 'array' });347 348 // Assuming first sheet is the one we want349 const firstSheetName = workbook.SheetNames[0];350 const worksheet = workbook.Sheets[firstSheetName];351 352 // Convert to JSON353 const jsonData = XLSX.utils.sheet_to_json(worksheet);354 355 if (jsonData.length > 0) {356 // Process and upload to Firebase357 const drugsRef = database.ref('drugs');358 let count = 0;359 360 // Clear existing data if needed (uncomment if desired)361 // drugsRef.remove();362 363 jsonData.forEach((row) => {364 const categories = row.categories ? row.categories.split(',').map(cat => cat.trim()) : [];365 366 drugsRef.push().set({367 name: row.name || '',368 genericName: row.genericName || '',369 description: row.description || '',370 categories: categories371 }).then(() => {372 count++;373 if (count === jsonData.length) {374 alert(`${count} drugs imported successfully!`);375 376 // Update statistics377 const statsRef = database.ref('statistics/drugsCount');378 statsRef.transaction((currentCount) => {379 return (currentCount || 0) + count;380 });381 }382 });383 });384 }385 };386 reader.readAsArrayBuffer(file);387 });388 389 // Initialize feather icons390 feather.replace();391 </script>392</body>393</html>