1<!doctype html> 2<html lang="en"> 3 <head> 4 <link rel="icon" href="images/fevicon/favicon.ico" type="image/x-icon" /> 5 6 <!-- PNG favicons --> 7 <link 8 rel="icon" 9 type="image/png" 10 sizes="16x16" 11 href="images/fevicon/favicon-16x16.png" 12 /> 13 <link 14 rel="icon" 15 type="image/png" 16 sizes="32x32" 17 href="images/fevicon/favicon-32x32.png" 18 /> 19 20 <!-- Android Chrome --> 21 <link 22 rel="icon" 23 type="image/png" 24 sizes="192x192" 25 href="images/fevicon/android-chrome-192x192.png" 26 /> 27 <link 28 rel="icon" 29 type="image/png" 30 sizes="512x512" 31 href="images/fevicon/android-chrome-512x512.png" 32 /> 33 34 <!-- Apple Touch Icon --> 35 <link 36 rel="apple-touch-icon" 37 sizes="180x180" 38 href="images/fevicon/apple-touch-icon.png" 39 /> 40 41 <!-- Manifest for PWA --> 42 <link rel="manifest" href="images/fevicon/site.webmanifest" /> 43 <link rel="manifest" href="/manifest.json" /> 44 <meta name="theme-color" content="#4a148c" /> 45 <meta charset="UTF-8" /> 46 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 47 <meta name="google-adsense-account" content="ca-pub-9442859388560602" /> 48 <title>Library Admin Dashboard</title> 49 <style> 50 * { 51 box-sizing: border-box; 52 margin: 0; 53 padding: 0; 54 } 55 56 body { 57 font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; 58 display: flex; 59 flex-direction: row; 60 height: 100vh; 61 background: linear-gradient(135deg, #e3e3e3, #f9f9f9); 62 overflow: hidden; 63 } 64 65 .sidebar { 66 width: 220px; 67 background: #1e1e2f; 68 color: white; 69 height: 100vh; 70 padding-top: 20px; 71 box-shadow: 4px 0 12px rgba(0, 0, 0, 0.2); 72 border-top-right-radius: 10px; 73 border-bottom-right-radius: 10px; 74 transition: all 0.3s ease-in-out; 75 } 76 77 .sidebar h2 { 78 text-align: center; 79 margin-bottom: 20px; 80 font-size: 24px; 81 background: linear-gradient(90deg, #ff4081, #7c4dff); 82 -webkit-background-clip: text; 83 -webkit-text-fill-color: transparent; 84 } 85 86 .sidebar a { 87 display: block; 88 padding: 15px 20px; 89 color: #f1f1f1; 90 text-decoration: none; 91 font-weight: 500; 92 border-radius: 8px; 93 margin: 10px; 94 transition: 95 background 0.3s, 96 transform 0.2s; 97 cursor: pointer; 98 } 99 100 .sidebar a:hover { 101 background: #4e4e70; 102 transform: translateX(5px); 103 } 104 105 .content { 106 flex: 1; 107 display: flex; 108 flex-direction: column; 109 height: 100vh; /* â ADD THIS */ 110 margin: 20px; 111 border-radius: 16px; 112 background: white; 113 box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); 114 overflow: hidden; 115 position: relative; 116 } 117 118 .top-navbar { 119 background: white; 120 padding: 15px 30px; 121 border-bottom: 1px solid #eee; 122 display: flex; 123 justify-content: space-between; 124 align-items: center; 125 box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); 126 z-index: 10; 127 } 128 129 .stats-container { 130 display: flex; 131 gap: 20px; 132 } 133 134 .stat-item { 135 display: flex; 136 align-items: center; 137 gap: 10px; 138 background: #f8f9fa; 139 padding: 8px 16px; 140 border-radius: 30px; 141 font-size: 14px; 142 font-weight: 600; 143 color: #333; 144 box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); 145 } 146 147 .stat-item i { 148 color: #7c4dff; 149 } 150 151 .stat-item span.value { 152 color: #ff4081; 153 font-weight: 700; 154 } 155 156 iframe { 157 flex: 1; 158 width: 100%; 159 border: none; 160 } 161 162 .welcome-container { 163 display: flex; 164 flex-direction: column; 165 align-items: center; 166 justify-content: center; 167 height: 100%; 168 text-align: center; 169 animation: fadeInUp 1.2s ease-out; 170 padding: 20px; 171 } 172 173 .welcome-container h1 { 174 font-size: 48px; 175 background: linear-gradient(to right, #e78d16, #1879ce); 176 -webkit-background-clip: text; 177 -webkit-text-fill-color: transparent; 178 font-weight: bold; 179 margin-bottom: 10px; 180 text-shadow: 2px 2px 10px rgba(0, 0, 0, 0.3); 181 } 182 183 .welcome-container p { 184 font-size: 20px; 185 color: #555; 186 animation: fadeIn 2s ease-in; 187 } 188 189 @keyframes fadeInUp { 190 from { 191 opacity: 0; 192 transform: translateY(30px); 193 } 194 to { 195 opacity: 1; 196 transform: translateY(0); 197 } 198 } 199 200 @keyframes fadeIn { 201 from { 202 opacity: 0; 203 } 204 to { 205 opacity: 1; 206 } 207 } 208 209 /* Hamburger button */ 210 .hamburger { 211 display: none; 212 position: absolute; 213 top: 15px; 214 left: 15px; 215 background-color: #1e1e2f; 216 color: white; 217 border: none; 218 padding: 10px 15px; 219 border-radius: 5px; 220 cursor: pointer; 221 z-index: 999; 222 } 223 224 /* â Responsive Styles for Mobile Devices */ 225 @media (max-width: 768px) { 226 body { 227 flex-direction: column; 228 } 229 230 /* Hamburger Button */ 231 .hamburger { 232 display: block; 233 position: fixed; 234 top: 15px; 235 left: 15px; 236 z-index: 1001; 237 background-color: #1e1e2f; 238 color: white; 239 border: none; 240 padding: 10px 15px; 241 border-radius: 5px; 242 cursor: pointer; 243 } 244 245 /* Sidebar Hidden by Default (off screen to the left) */ 246 .sidebar { 247 position: fixed; 248 top: 0; 249 left: -220px; 250 height: 100%; 251 width: 220px; 252 background: #1e1e2f; 253 padding-top: 20px; 254 transition: left 0.3s ease-in-out; 255 z-index: 1000; 256 flex-direction: column; 257 box-shadow: 4px 0 12px rgba(0, 0, 0, 0.2); 258 } 259 260 /* Sidebar Visible */ 261 .sidebar.show { 262 left: 0; 263 } 264 265 /* Sidebar Title */ 266 .sidebar h2 { 267 font-size: 20px; 268 margin-bottom: 10px; 269 padding-left: 15px; 270 color: white; 271 } 272 273 /* Sidebar Links */ 274 .sidebar a { 275 display: block; 276 margin: 5px 0; 277 padding: 10px 15px; 278 font-size: 14px; 279 border-radius: 6px; 280 color: white; 281 text-decoration: none; 282 } 283 284 /* Content */ 285 .content { 286 margin: 10px; 287 border-radius: 12px; 288 } 289 290 /* Welcome Section */ 291 .welcome-container h1 { 292 font-size: 32px; 293 } 294 295 .welcome-container p { 296 font-size: 16px; 297 } 298 } 299 </style> 300 </head> 301 <body> 302 <button class="hamburger" onclick="toggleSidebar()">â° Menu</button> 303 304 <div class="sidebar" id="sidebar"> 305 <br /> 306 <br /> 307 <h2>Admin</h2> 308 <a onclick="loadCashRequestPage()">Cash Requests</a> 309 <a onclick="loadSeatStatus()">Seat Status</a> 310 <a onclick="loadseatChange()">Change seat</a> 311 <a onclick="loadRecentBookings()">Recent Bookings</a> 312 <a onclick="loadExpiringBookings()">Expiring Bookings</a> 313 <a onclick="loadregisteredUsers()">Registered Users</a> 314 <a onclick="loadpriceChange()">Price</a> 315 <a onclick="loadcustomPrice()">Custom Price</a> 316 <a onclick="loadDirectBooking()">Direct Booking</a> 317 <a onclick="loadCoupons()">Coupons</a> 318 <a onclick="loadInsights()">AI Insights</a> 319 <a onclick="logout()">Logout</a> 320 </div> 321 322 <div class="content"> 323 <!-- Top Navbar with Stats --> 324 <div class="top-navbar"> 325 <h3 style="margin: 0; font-weight: 700; color: #333"> 326 Admin Dashboard 327 </h3> 328 <div class="stats-container"> 329 <div class="stat-item"> 330 <i class="fas fa-chair"></i> 331 Total Seats: <span class="value">34</span> 332 </div> 333 <div class="stat-item"> 334 <i class="fas fa-user-check"></i> 335 Occupied: <span class="value" id="occupied-count">...</span> 336 </div> 337 <div class="stat-item"> 338 <i class="fas fa-check-circle"></i> 339 Available: <span class="value" id="available-count">...</span> 340 </div> 341 </div> 342 </div> 343 344 <div 345 id="mainContent" 346 style=" 347 flex: 1; 348 width: 100%; 349 position: relative; 350 overflow: hidden; 351 display: flex; 352 flex-direction: column; 353 " 354 > 355 <div class="welcome-container"> 356 <h1>Welcome Admin Ji</h1> 357 <p>Side panel mai option select kijiye</p> 358 </div> 359 </div> 360 </div> 361 362 <!-- Font Awesome for Icons --> 363 <link 364 rel="stylesheet" 365 href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" 366 /> 367 368
368<script> 369 // Fetch and update seat stats 370 async function updateSeatStats() { 371 try { 372 const res = await fetch( 373 "https://kanhabackend.onrender.com/api/bookings", 374 ); 375 if (!res.ok) throw new Error("Failed to fetch bookings"); 376 const bookings = await res.json(); 377 378 // Get today's date in YYYY-MM-DD format 379 const today = new Date(); 380 const year = today.getFullYear(); 381 const month = String(today.getMonth() + 1).padStart(2, "0"); 382 const day = String(today.getDate()).padStart(2, "0"); 383 const dateStr = `${year}-${month}-${day}`; 384 385 // Filter bookings for today and status 'paid' 386 // We count a seat as occupied if it has ANY paid booking for today (AM, PM, or FULL) 387 const todayBookings = bookings.filter( 388 (b) => b.date === dateStr && b.status === "paid", 389 ); 390 391 // Count unique occupied seats 392 const occupiedSeats = new Set(todayBookings.map((b) => b.seatId)); 393 const occupiedCount = occupiedSeats.size; 394 const totalSeats = 34; 395 const availableCount = totalSeats - occupiedCount; 396 397 document.getElementById("occupied-count").textContent = occupiedCount; 398 document.getElementById("available-count").textContent = 399 availableCount; 400 } catch (error) { 401 console.error("Error fetching seat stats:", error); 402 document.getElementById("occupied-count").textContent = "-"; 403 document.getElementById("available-count").textContent = "-"; 404 } 405 } 406 407 // Initial call and periodic refresh (every 30 seconds) 408 updateSeatStats(); 409 setInterval(updateSeatStats, 30000); 410 411 // â Protect admin page 412 const user = JSON.parse(localStorage.getItem("user")); 413 414 if (!user) { 415 // Not logged in 416 window.location.href = "login.html"; 417 } else if (user.role === "admin") { 418 // Admin allowed â do nothing 419 } else if (user.role === "incharge") { 420 // Incharge dashboard 421 window.location.href = "libincharge.html"; 422 } else { 423 // Any other role 424 window.location.href = "login.html"; 425 } 426 427 function toggleSidebar() { 428 document.getElementById("sidebar").classList.toggle("show"); 429 } 430 431 // Close sidebar after clicking any menu item (mobile only) 432 document.querySelectorAll(".sidebar a").forEach((link) => { 433 link.addEventListener("click", () => { 434 if (window.innerWidth <= 768) { 435 document.getElementById("sidebar").classList.remove("show"); 436 } 437 }); 438 }); 439 440 function loadSeatStatus() { 441 const iframe = document.createElement("iframe"); 442 iframe.src = "seatStatus.html"; 443 const mainContent = document.getElementById("mainContent"); 444 mainContent.innerHTML = ""; 445 mainContent.appendChild(iframe); 446 } 447 448 function loadCashRequestPage() { 449 const iframe = document.createElement("iframe"); 450 iframe.src = "cashRequest.html"; 451 const mainContent = document.getElementById("mainContent"); 452 mainContent.innerHTML = ""; 453 mainContent.appendChild(iframe); 454 } 455 456 function loadRecentBookings() { 457 const iframe = document.createElement("iframe"); 458 iframe.src = "recent-booking.html?v=1.0.2"; 459 const mainContent = document.getElementById("mainContent"); 460 mainContent.innerHTML = ""; 461 mainContent.appendChild(iframe); 462 } 463 464 function loadExpiringBookings() { 465 const iframe = document.createElement("iframe"); 466 iframe.src = "expiringToday.html?v=1.0.2"; 467 const mainContent = document.getElementById("mainContent"); 468 mainContent.innerHTML = ""; 469 mainContent.appendChild(iframe); 470 } 471 472 function loadregisteredUsers() { 473 const iframe = document.createElement("iframe"); 474 iframe.src = "registeredUsers.html"; 475 const mainContent = document.getElementById("mainContent"); 476 mainContent.innerHTML = ""; 477 mainContent.appendChild(iframe); 478 } 479 function loadpriceChange() { 480 const iframe = document.createElement("iframe"); 481 iframe.src = "pricechange.html"; 482 const mainContent = document.getElementById("mainContent"); 483 mainContent.innerHTML = ""; 484 mainContent.appendChild(iframe); 485 } 486 function loadcustomPrice() { 487 const iframe = document.createElement("iframe"); 488 iframe.src = "customPrice.html"; 489 const mainContent = document.getElementById("mainContent"); 490 mainContent.innerHTML = ""; 491 mainContent.appendChild(iframe); 492 } 493 function loadseatChange() { 494 const iframe = document.createElement("iframe"); 495 iframe.src = "seatChange.html"; 496 const mainContent = document.getElementById("mainContent"); 497 mainContent.innerHTML = ""; 498 mainContent.appendChild(iframe); 499 } 500 501 function loadCoupons() { 502 const iframe = document.createElement("iframe"); 503 iframe.src = "admin-coupons.html"; 504 const mainContent = document.getElementById("mainContent"); 505 mainContent.innerHTML = ""; 506 mainContent.appendChild(iframe); 507 } 508 509 function loadInsights() { 510 const iframe = document.createElement("iframe"); 511 iframe.src = "admin-insights.html"; 512 const mainContent = document.getElementById("mainContent"); 513 mainContent.innerHTML = ""; 514 mainContent.appendChild(iframe); 515 } 516 517 function loadDirectBooking() { 518 const iframe = document.createElement("iframe"); 519 iframe.src = "admin-direct-booking.html"; 520 const mainContent = document.getElementById("mainContent"); 521 mainContent.innerHTML = ""; 522 mainContent.appendChild(iframe); 523 } 524 525 function logout() { 526 localStorage.removeItem("user"); 527 window.location.href = "login.html"; 528 } 529 </script>
529 530 </body> 531</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.