Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>PharmaCare Dashboard - Pharmacy Management System</title> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| :root { | |
| --primary-color: #2c7a7b; | |
| --primary-dark: #2a6e6f; | |
| --secondary-color: #48bb78; | |
| --danger-color: #f56565; | |
| --warning-color: #ed8936; | |
| --info-color: #4299e1; | |
| --dark-bg: #1a202c; | |
| --light-bg: #f7fafc; | |
| --card-bg: #ffffff; | |
| --text-primary: #2d3748; | |
| --text-secondary: #718096; | |
| --border-color: #e2e8f0; | |
| --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.12); | |
| --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1); | |
| --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| min-height: 100vh; | |
| color: var(--text-primary); | |
| } | |
| .dashboard-container { | |
| display: flex; | |
| min-height: 100vh; | |
| background: var(--light-bg); | |
| } | |
| /* Sidebar */ | |
| .sidebar { | |
| width: 260px; | |
| background: var(--dark-bg); | |
| color: white; | |
| transition: var(--transition); | |
| position: fixed; | |
| height: 100vh; | |
| z-index: 1000; | |
| overflow-y: auto; | |
| } | |
| .sidebar.collapsed { | |
| width: 70px; | |
| } | |
| .sidebar-header { | |
| padding: 1.5rem; | |
| background: rgba(0, 0, 0, 0.2); | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| } | |
| .logo { | |
| display: flex; | |
| align-items: center; | |
| gap: 0.75rem; | |
| font-size: 1.25rem; | |
| font-weight: bold; | |
| } | |
| .logo i { | |
| font-size: 1.5rem; | |
| color: var(--secondary-color); | |
| } | |
| .sidebar.collapsed .logo span { | |
| display: none; | |
| } | |
| .toggle-btn { | |
| background: none; | |
| border: none; | |
| color: white; | |
| font-size: 1.25rem; | |
| cursor: pointer; | |
| transition: var(--transition); | |
| } | |
| .toggle-btn:hover { | |
| color: var(--secondary-color); | |
| } | |
| .nav-menu { | |
| padding: 1rem 0; | |
| } | |
| .nav-item { | |
| display: flex; | |
| align-items: center; | |
| padding: 0.875rem 1.5rem; | |
| color: rgba(255, 255, 255, 0.8); | |
| text-decoration: none; | |
| transition: var(--transition); | |
| position: relative; | |
| } | |
| .nav-item:hover { | |
| background: rgba(255, 255, 255, 0.1); | |
| color: white; | |
| } | |
| .nav-item.active { | |
| background: var(--primary-color); | |
| color: white; | |
| } | |
| .nav-item.active::before { | |
| content: ''; | |
| position: absolute; | |
| left: 0; | |
| top: 0; | |
| bottom: 0; | |
| width: 4px; | |
| background: var(--secondary-color); | |
| } | |
| .nav-item i { | |
| width: 24px; | |
| margin-right: 1rem; | |
| } | |
| .sidebar.collapsed .nav-item span { | |
| display: none; | |
| } | |
| .sidebar.collapsed .nav-item i { | |
| margin-right: 0; | |
| } | |
| /* Main Content */ | |
| .main-content { | |
| flex: 1; | |
| margin-left: 260px; | |
| transition: var(--transition); | |
| background: var(--light-bg); | |
| } | |
| .main-content.expanded { | |
| margin-left: 70px; | |
| } | |
| /* Top Header */ | |
| .top-header { | |
| background: white; | |
| padding: 1rem 2rem; | |
| box-shadow: var(--shadow-sm); | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| position: sticky; | |
| top: 0; | |
| z-index: 100; | |
| } | |
| .header-left { | |
| display: flex; | |
| align-items: center; | |
| gap: 2rem; | |
| } | |
| .search-bar { | |
| position: relative; | |
| width: 300px; | |
| } | |
| .search-bar input { | |
| width: 100%; | |
| padding: 0.625rem 2.5rem 0.625rem 1rem; | |
| border: 1px solid var(--border-color); | |
| border-radius: 8px; | |
| font-size: 0.875rem; | |
| transition: var(--transition); | |
| } | |
| .search-bar input:focus { | |
| outline: none; | |
| border-color: var(--primary-color); | |
| box-shadow: 0 0 0 3px rgba(44, 122, 123, 0.1); | |
| } | |
| .search-bar i { | |
| position: absolute; | |
| right: 1rem; | |
| top: 50%; | |
| transform: translateY(-50%); | |
| color: var(--text-secondary); | |
| } | |
| .header-right { | |
| display: flex; | |
| align-items: center; | |
| gap: 1.5rem; | |
| } | |
| .notification-btn { | |
| position: relative; | |
| background: none; | |
| border: none; | |
| font-size: 1.25rem; | |
| color: var(--text-secondary); | |
| cursor: pointer; | |
| transition: var(--transition); | |
| } | |
| .notification-btn:hover { | |
| color: var(--primary-color); | |
| } | |
| .notification-badge { | |
| position: absolute; | |
| top: -5px; | |
| right: -5px; | |
| background: var(--danger-color); | |
| color: white; | |
| font-size: 0.625rem; | |
| padding: 2px 6px; | |
| border-radius: 10px; | |
| } | |
| .user-profile { | |
| display: flex; | |
| align-items: center; | |
| gap: 0.75rem; | |
| cursor: pointer; | |
| padding: 0.5rem; | |
| border-radius: 8px; | |
| transition: var(--transition); | |
| } | |
| .user-profile:hover { | |
| background: var(--light-bg); | |
| } | |
| .user-avatar { | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 50%; | |
| background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| font-weight: bold; | |
| } | |
| .user-info { | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .user-name { | |
| font-size: 0.875rem; | |
| font-weight: 600; | |
| color: var(--text-primary); | |
| } | |
| .user-role { | |
| font-size: 0.75rem; | |
| color: var(--text-secondary); | |
| } | |
| /* Dashboard Content */ | |
| .dashboard-content { | |
| padding: 2rem; | |
| } | |
| .page-title { | |
| font-size: 1.75rem; | |
| font-weight: 700; | |
| color: var(--text-primary); | |
| margin-bottom: 0.5rem; | |
| } | |
| .page-subtitle { | |
| color: var(--text-secondary); | |
| margin-bottom: 2rem; | |
| } | |
| /* Stats Grid */ | |
| .stats-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); | |
| gap: 1.5rem; | |
| margin-bottom: 2rem; | |
| } | |
| .stat-card { | |
| background: white; | |
| padding: 1.5rem; | |
| border-radius: 12px; | |
| box-shadow: var(--shadow-sm); | |
| transition: var(--transition); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .stat-card:hover { | |
| transform: translateY(-4px); | |
| box-shadow: var(--shadow-lg); | |
| } | |
| .stat-card::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 4px; | |
| background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); | |
| } | |
| .stat-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 1rem; | |
| } | |
| .stat-icon { | |
| width: 48px; | |
| height: 48px; | |
| border-radius: 12px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 1.5rem; | |
| } | |
| .stat-icon.primary { | |
| background: rgba(44, 122, 123, 0.1); | |
| color: var(--primary-color); | |
| } | |
| .stat-icon.success { | |
| background: rgba(72, 187, 120, 0.1); | |
| color: var(--secondary-color); | |
| } | |
| .stat-icon.warning { | |
| background: rgba(237, 137, 54, 0.1); | |
| color: var(--warning-color); | |
| } | |
| .stat-icon.danger { | |
| background: rgba(245, 101, 101, 0.1); | |
| color: var(--danger-color); | |
| } | |
| .stat-value { | |
| font-size: 2rem; | |
| font-weight: 700; | |
| color: var(--text-primary); | |
| margin-bottom: 0.25rem; | |
| } | |
| .stat-label { | |
| color: var(--text-secondary); | |
| font-size: 0.875rem; | |
| } | |
| .stat-change { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.25rem; | |
| font-size: 0.75rem; | |
| padding: 0.25rem 0.5rem; | |
| border-radius: 4px; | |
| margin-top: 0.5rem; | |
| } | |
| .stat-change.positive { | |
| background: rgba(72, 187, 120, 0.1); | |
| color: var(--secondary-color); | |
| } | |
| .stat-change.negative { | |
| background: rgba(245, 101, 101, 0.1); | |
| color: var(--danger-color); | |
| } | |
| /* Charts Section */ | |
| .charts-row { | |
| display: grid; | |
| grid-template-columns: 2fr 1fr; | |
| gap: 1.5rem; | |
| margin-bottom: 2rem; | |
| } | |
| .chart-card { | |
| background: white; | |
| padding: 1.5rem; | |
| border-radius: 12px; | |
| box-shadow: var(--shadow-sm); | |
| } | |
| .chart-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 1.5rem; | |
| } | |
| .chart-title { | |
| font-size: 1.125rem; | |
| font-weight: 600; | |
| color: var(--text-primary); | |
| } | |
| .chart-options { | |
| display: flex; | |
| gap: 0.5rem; | |
| } | |
| .chart-option-btn { | |
| padding: 0.375rem 0.75rem; | |
| border: 1px solid var(--border-color); | |
| background: white; | |
| border-radius: 6px; | |
| font-size: 0.75rem; | |
| cursor: pointer; | |
| transition: var(--transition); | |
| } | |
| .chart-option-btn:hover { | |
| background: var(--light-bg); | |
| } | |
| .chart-option-btn.active { | |
| background: var(--primary-color); | |
| color: white; | |
| border-color: var(--primary-color); | |
| } | |
| /* Inventory Table */ | |
| .inventory-section { | |
| background: white; | |
| padding: 1.5rem; | |
| border-radius: 12px; | |
| box-shadow: var(--shadow-sm); | |
| margin-bottom: 2rem; | |
| } | |
| .section-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 1.5rem; | |
| } | |
| .section-title { | |
| font-size: 1.125rem; | |
| font-weight: 600; | |
| color: var(--text-primary); | |
| } | |
| .action-buttons { | |
| display: flex; | |
| gap: 0.75rem; | |
| } | |
| .btn { | |
| padding: 0.5rem 1rem; | |
| border: none; | |
| border-radius: 6px; | |
| font-size: 0.875rem; | |
| cursor: pointer; | |
| transition: var(--transition); | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| } | |
| .btn-primary { | |
| background: var(--primary-color); | |
| color: white; | |
| } | |
| .btn-primary:hover { | |
| background: var(--primary-dark); | |
| } | |
| .btn-secondary { | |
| background: var(--light-bg); | |
| color: var(--text-primary); | |
| border: 1px solid var(--border-color); | |
| } | |
| .btn-secondary:hover { | |
| background: var(--border-color); | |
| } | |
| .table-container { | |
| overflow-x: auto; | |
| } | |
| table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| } | |
| th { | |
| text-align: left; | |
| padding: 0.75rem; | |
| background: var(--light-bg); | |
| font-size: 0.75rem; | |
| font-weight: 600; | |
| color: var(--text-secondary); | |
| text-transform: uppercase; | |
| letter-spacing: 0.5px; | |
| } | |
| td { | |
| padding: 0.75rem; | |
| border-top: 1px solid var(--border-color); | |
| font-size: 0.875rem; | |
| } | |
| tr:hover { | |
| background: var(--light-bg); | |
| } | |
| .stock-badge { | |
| display: inline-flex; | |
| align-items: center; | |
| padding: 0.25rem 0.5rem; | |
| border-radius: 4px; | |
| font-size: 0.75rem; | |
| font-weight: 600; | |
| } | |
| .stock-badge.in-stock { | |
| background: rgba(72, 187, 120, 0.1); | |
| color: var(--secondary-color); | |
| } | |
| .stock-badge.low-stock { | |
| background: rgba(237, 137, 54, 0.1); | |
| color: var(--warning-color); | |
| } | |
| .stock-badge.out-stock { | |
| background: rgba(245, 101, 101, 0.1); | |
| color: var(--danger-color); | |
| } | |
| /* Recent Transactions */ | |
| .transactions-list { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 1rem; | |
| } | |
| .transaction-item { | |
| display: flex; | |
| align-items: center; | |
| gap: 1rem; | |
| padding: 0.75rem; | |
| background: var(--light-bg); | |
| border-radius: 8px; | |
| transition: var(--transition); | |
| } | |
| .transaction-item:hover { | |
| background: var(--border-color); | |
| } | |
| .transaction-icon { | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 8px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 1.25rem; | |
| } | |
| .transaction-icon.success { | |
| background: rgba(72, 187, 120, 0.1); | |
| color: var(--secondary-color); | |
| } | |
| .transaction-icon.pending { | |
| background: rgba(237, 137, 54, 0.1); | |
| color: var(--warning-color); | |
| } | |
| .transaction-details { | |
| flex: 1; | |
| } | |
| .transaction-title { | |
| font-size: 0.875rem; | |
| font-weight: 600; | |
| color: var(--text-primary); | |
| } | |
| .transaction-time { | |
| font-size: 0.75rem; | |
| color: var(--text-secondary); | |
| } | |
| .transaction-amount { | |
| font-weight: 600; | |
| color: var(--text-primary); | |
| } | |
| /* Canvas Chart */ | |
| #salesChart { | |
| max-height: 300px; | |
| } | |
| /* Low Stock Alert */ | |
| .alert-banner { | |
| background: linear-gradient(135deg, var(--warning-color), #f6ad55); | |
| color: white; | |
| padding: 1rem 1.5rem; | |
| border-radius: 8px; | |
| margin-bottom: 2rem; | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| animation: slideIn 0.5s ease; | |
| } | |
| .alert-content { | |
| display: flex; | |
| align-items: center; | |
| gap: 1rem; | |
| } | |
| .alert-icon { | |
| font-size: 1.5rem; | |
| } | |
| .alert-text { | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .alert-title { | |
| font-weight: 600; | |
| margin-bottom: 0.25rem; | |
| } | |
| .alert-message { | |
| font-size: 0.875rem; | |
| opacity: 0.9; | |
| } | |
| .alert-close { | |
| background: rgba(255, 255, 255, 0.2); | |
| border: none; | |
| color: white; | |
| padding: 0.5rem; | |
| border-radius: 4px; | |
| cursor: pointer; | |
| transition: var(--transition); | |
| } | |
| .alert-close:hover { | |
| background: rgba(255, 255, 255, 0.3); | |
| } | |
| /* Modal */ | |
| .modal { | |
| display: none; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: rgba(0, 0, 0, 0.5); | |
| z-index: 2000; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .modal.active { | |
| display: flex; | |
| } | |
| .modal-content { | |
| background: white; | |
| padding: 2rem; | |
| border-radius: 12px; | |
| width: 90%; | |
| max-width: 500px; | |
| animation: slideIn 0.3s ease; | |
| } | |
| .modal-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 1.5rem; | |
| } | |
| .modal-title { | |
| font-size: 1.25rem; | |
| font-weight: 600; | |
| color: var(--text-primary); | |
| } | |
| .modal-close { | |
| background: none; | |
| border: none; | |
| font-size: 1.5rem; | |
| color: var(--text-secondary); | |
| cursor: pointer; | |
| } | |
| .form-group { | |
| margin-bottom: 1rem; | |
| } | |
| .form-group label { | |
| display: block; | |
| margin-bottom: 0.5rem; | |
| font-size: 0.875rem; | |
| font-weight: 500; | |
| color: var(--text-primary); | |
| } | |
| .form-group input, | |
| .form-group select { | |
| width: 100%; | |
| padding: 0.625rem; | |
| border: 1px solid var(--border-color); | |
| border-radius: 6px; | |
| font-size: 0.875rem; | |
| transition: var(--transition); | |
| } | |
| .form-group input:focus, | |
| .form-group select:focus { | |
| outline: none; | |
| border-color: var(--primary-color); | |
| box-shadow: 0 0 0 3px rgba(44, 122, 123, 0.1); | |
| } | |
| .modal-footer { | |
| display: flex; | |
| justify-content: flex-end; | |
| gap: 0.75rem; | |
| margin-top: 1.5rem; | |
| } | |
| /* Animations */ | |
| @keyframes slideIn { | |
| from { | |
| transform: translateY(-20px); | |
| opacity: 0; | |
| } | |
| to { | |
| transform: translateY(0); | |
| opacity: 1; | |
| } | |
| } | |
| @keyframes pulse { | |
| 0%, | |
| 100% { | |
| transform: scale(1); | |
| } | |
| 50% { | |
| transform: scale(1.05); | |
| } | |
| } | |
| /* Responsive Design */ | |
| @media (max-width: 1024px) { | |
| .charts-row { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| @media (max-width: 768px) { | |
| .sidebar { | |
| transform: translateX(-100%); | |
| } | |
| .sidebar.active { | |
| transform: translateX(0); | |
| } | |
| .main-content { | |
| margin-left: 0; | |
| } | |
| .stats-grid { | |
| grid-template-columns: 1fr; | |
| } | |
| .search-bar { | |
| display: none; | |
| } | |
| .user-info { | |
| display: none; | |
| } | |
| .dashboard-content { | |
| padding: 1rem; | |
| } | |
| } | |
| /* Loading Spinner */ | |
| .spinner { | |
| width: 40px; | |
| height: 40px; | |
| border: 4px solid var(--border-color); | |
| border-top-color: var(--primary-color); | |
| border-radius: 50%; | |
| animation: spin 1s linear infinite; | |
| } | |
| @keyframes spin { | |
| to { | |
| transform: rotate(360deg); | |
| } | |
| } | |
| /* Tooltip */ | |
| .tooltip { | |
| position: relative; | |
| } | |
| .tooltip::after { | |
| content: attr(data-tooltip); | |
| position: absolute; | |
| bottom: 125%; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| background: var(--dark-bg); | |
| color: white; | |
| padding: 0.5rem 0.75rem; | |
| border-radius: 6px; | |
| font-size: 0.75rem; | |
| white-space: nowrap; | |
| opacity: 0; | |
| pointer-events: none; | |
| transition: opacity 0.3s; | |
| } | |
| .tooltip:hover::after { | |
| opacity: 1; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="dashboard-container"> | |
| <!-- Sidebar --> | |
| <aside class="sidebar" id="sidebar"> | |
| <div class="sidebar-header"> | |
| <div class="logo"> | |
| <i class="fas fa-pills"></i> | |
| <span>PharmaCare</span> | |
| </div> | |
| <button class="toggle-btn" onclick="toggleSidebar()"> | |
| <i class="fas fa-bars"></i> | |
| </button> | |
| </div> | |
| <nav class="nav-menu"> | |
| <a href="#" class="nav-item active" onclick="setActiveNav(this)"> | |
| <i class="fas fa-tachometer-alt"></i> | |
| <span>Dashboard</span> | |
| </a> | |
| <a href="#" class="nav-item" onclick="setActiveNav(this)"> | |
| <i class="fas fa-capsules"></i> | |
| <span>Inventory</span> | |
| </a> | |
| <a href="#" class="nav-item" onclick="setActiveNav(this)"> | |
| <i class="fas fa-shopping-cart"></i> | |
| <span>Sales</span> | |
| </a> | |
| <a href="#" class="nav-item" onclick="setActiveNav(this)"> | |
| <i class="fas fa-users"></i> | |
| <span>Customers</span> | |
| </a> | |
| <a href="#" class="nav-item" onclick="setActiveNav(this)"> | |
| <i class="fas fa-file-medical"></i> | |
| <span>Prescriptions</span> | |
| </a> | |
| <a href="#" class="nav-item" onclick="setActiveNav(this)"> | |
| <i class="fas fa-chart-line"></i> | |
| <span>Reports</span> | |
| </a> | |
| <a href="#" class="nav-item" onclick="setActiveNav(this)"> | |
| <i class="fas fa-user-md"></i> | |
| <span>Staff</span> | |
| </a> | |
| <a href="#" class="nav-item" onclick="setActiveNav(this)"> | |
| <i class="fas fa-cog"></i> | |
| <span>Settings</span> | |
| </a> | |
| </nav> | |
| </aside> | |
| <!-- Main Content --> | |
| <main class="main-content" id="mainContent"> | |
| <!-- Top Header --> | |
| <header class="top-header"> | |
| <div class="header-left"> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" | |
| style="color: var(--primary-color); text-decoration: none; font-weight: 600;"> | |
| Built with anycoder | |
| </a> | |
| <div class="search-bar"> | |
| <input type="text" placeholder="Search medications, customers..." onkeyup="handleSearch(event)"> | |
| <i class="fas fa-search"></i> | |
| </div> | |
| </div> | |
| <div class="header-right"> | |
| <button class="notification-btn tooltip" data-tooltip="Notifications" onclick="showNotifications()"> | |
| <i class="fas fa-bell"></i> | |
| <span class="notification-badge">3</span> | |
| </button> | |
| <div class="user-profile"> | |
| <div class="user-avatar">JD</div> | |
| <div class="user-info"> | |
| <span class="user-name">Dr. John Doe</span> | |
| <span class="user-role">Pharmacy Manager</span> | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Dashboard Content --> | |
| <div class="dashboard-content"> | |
| <h1 class="page-title">Pharmacy Dashboard</h1> | |
| <p class="page-subtitle">Welcome back! Here's what's happening at your pharmacy today.</p> | |
| <!-- Alert Banner --> | |
| <div class="alert-banner" id="alertBanner"> | |
| <div class="alert-content"> | |
| <i class="fas fa-exclamation-triangle alert-icon"></i> | |
| <div class="alert-text"> | |
| <span class="alert-title">Low Stock Alert</span> | |
| <span class="alert-message">5 medications are running low on inventory. Reorder recommended.</span> | |
| </div> | |
| </div> | |
| <button class="alert-close" onclick="closeAlert()"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <!-- Stats Grid --> | |
| <div class="stats-grid"> | |
| <div class="stat-card"> | |
| <div class="stat-header"> | |
| <div> | |
| <div class="stat-value" id="revenueValue">$124,563</div> | |
| <div class="stat-label">Total Revenue</div> | |
| <span class="stat-change positive"> | |
| <i class="fas fa-arrow-up"></i> 12.5% | |
| </span> | |
| </div> | |
| <div class="stat-icon success"> | |
| <i class="fas fa-dollar-sign"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-header"> | |
| <div> | |
| <div class="stat-value" id="patientsValue">1,842</div> | |
| <div class="stat-label">Total Patients</div> | |
| <span class="stat-change positive"> | |
| <i class="fas fa-arrow-up"></i> 8.2% | |
| </span> | |
| </div> | |
| <div class="stat-icon primary"> | |
| <i class="fas fa-users"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-header"> | |
| <div> | |
| <div class="stat-value" id="prescriptionsValue">523</div> | |
| <div class="stat-label">Prescriptions Today</div> | |
| <span class="stat-change negative"> | |
| <i class="fas fa-arrow-down"></i> 3.1% | |
| </span> | |
| </div> | |
| <div class="stat-icon warning"> | |
| <i class="fas fa-file-prescription"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-header"> | |
| <div> | |
| <div class="stat-value" id="stockValue">2,456</div> | |
| <div class="stat-label">Medicine Stock</div> | |
| <span class="stat-change positive"> | |
| <i class="fas fa-arrow-up"></i> 15.3% | |
| </span> | |
| </div> | |
| <div class="stat-icon danger"> | |
| <i class="fas fa-pills"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-header"> | |
| <div> | |
| <div class="stat-value" id="accountBalance">$45,230</div> | |
| <div class="stat-label">Account Balance</div> | |
| <span class="stat-change positive"> | |
| <i class="fas fa-arrow-up"></i> 5.7% | |
| </span> | |
| </div> | |
| <div class="stat-icon info"> | |
| <i class="fas fa-wallet"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-header"> | |
| <div> | |
| <div class="stat-value" id="profitMargin">23.5%</div> | |
| <div class="stat-label">Profit Margin</div> | |
| <span class="stat-change positive"> | |
| <i class="fas fa-arrow-up"></i> 2.1% | |
| </span> | |
| </div> | |
| <div class="stat-icon success"> | |
| <i class="fas fa-chart-pie"></i> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Charts Row --> | |
| <div class="charts-row"> | |
| <div class="chart-card"> | |
| <div class="chart-header"> | |
| <h3 class="chart-title">Sales Overview</h3> | |
| <div class="chart-options"> | |
| <button class="chart-option-btn active" onclick="changeChartView(this, 'week')">Week</button> | |
| <button class="chart-option-btn" onclick="changeChartView(this, 'month')">Month</button> | |
| <button class="chart-option-btn" onclick="changeChartView(this, 'year')">Year</button> | |
| </div> | |
| </div> | |
| <canvas id="salesChart"></canvas> | |
| </div> | |
| <div class="chart-card"> | |
| <div class="chart-header"> | |
| <h3 class="chart-title">Recent Transactions</h3> | |
| </div> | |
| <div class="transactions-list" id="transactionsList"> | |
| <div class="transaction-item"> | |
| <div class="transaction-icon success"> | |
| <i class="fas fa-check"></i> | |
| </div> | |
| <div class="transaction-details"> | |
| <div class="transaction-title">Purchase #1024</div> | |
| <div class="transaction-time">2 hours ago</div> | |
| </div> | |
| <div class="transaction-amount">$156.00</div> | |
| </div> | |
| <div class="transaction-item"> | |
| <div class="transaction-icon pending"> | |
| <i class="fas fa-clock"></i> | |
| </div> | |
| <div class="transaction-details"> | |
| <div class="transaction-title">Prescription #1023</div> | |
| <div class="transaction-time">4 hours ago</div> | |
| </div> | |
| <div class="transaction-amount">$89.50</div> | |
| </div> | |
| <div class="transaction-item"> | |
| <div class="transaction-icon success"> | |
| <i class="fas fa-check"></i> | |
| </div> | |
| <div class="transaction-details"> | |
| <div class="transaction-title">Purchase #1022</div> | |
| <div class="transaction-time">6 hours ago</div> | |
| </div> | |
| <div class="transaction-amount">$234.75</div> | |
| </div> | |
| <div class="transaction-item"> | |
| <div class="transaction-icon success"> | |
| <i class="fas fa-check"></i> | |
| </div> | |
| <div class="transaction-details"> | |
| <div class="transaction-title">Purchase #1021</div> | |
| <div class="transaction-time">8 hours ago</div> | |
| </div> | |
| <div class="transaction-amount">$67.25</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Inventory Table --> | |
| <div class="inventory-section"> | |
| <div class="section-header"> | |
| <h3 class="section-title">Medicine Inventory</h3> | |
| <div class="action-buttons"> | |
| <button class="btn btn-secondary" onclick="filterInventory()"> | |
| <i class="fas fa-filter"></i> Filter | |
| </button> | |
| <button class="btn btn-primary" onclick="openAddMedicineModal()"> | |
| <i class="fas fa-plus"></i> Add Medicine | |
| </button> | |
| </div> | |
| </div> | |
| <div class="table-container"> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Medicine Name</th> | |
| <th>Category</th> | |
| <th>Stock</th> | |
| <th>Price</th> | |
| <th>Expiry Date</th> | |
| <th>Status</th> | |
| <th>Actions</th> | |
| </tr> | |
| </thead> | |
| <tbody id="inventoryTableBody"> | |
| <tr> | |
| <td><strong>Amoxicillin</strong></td> | |
| <td>Antibiotics</td> | |
| <td>245</td> | |
| <td>$15.99</td> | |
| <td>2024-12-31</td> | |
| <td><span class="stock-badge in-stock">In Stock</span></td> | |
| <td> | |
| <button class="btn btn-secondary" style="padding: 0.25rem 0.5rem; font-size: 0.75rem;" onclick="editMedicine(this)"> | |
| <i class="fas fa-edit"></i> | |
| </button> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td><strong>Paracetamol</strong></td> | |
| <td>Pain Relief</td> | |
| <td>89</td> | |
| <td>$8.50</td> | |
| <td>2024-10-15</td> | |
| <td><span class="stock-badge low-stock">Low Stock</span></td> | |
| <td> | |
| <button class="btn btn-secondary" style="padding: 0.25rem 0.5rem; font-size: 0.75rem;" onclick="editMedicine(this)"> | |
| <i class="fas fa-edit"></i> | |
| </button> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td><strong>Ibuprofen</strong></td> | |
| <td>Pain Relief</td> | |
| <td>156</td> | |
| <td>$12.75</td> | |
| <td>2025-01-20</td> | |
| <td><span class="stock-badge in-stock">In Stock</span></td> | |
| <td> | |
| <button class="btn btn-secondary" style="padding: 0.25rem 0.5rem; font-size: 0.75rem;" onclick="editMedicine(this)"> | |
| <i class="fas fa-edit"></i> | |
| </button> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td><strong>Omeprazole</strong></td> | |
| <td>GI Medications</td> | |
| <td>0</td> | |
| <td>$22.00</td> | |
| <td>2024-08-30</td> | |
| <td><span class="stock-badge out-stock">Out of Stock</span></td> | |
| <td> | |
| <button class="btn btn-secondary" style="padding: 0.25rem 0.5rem; font-size: 0.75rem;" onclick="editMedicine(this)"> | |
| <i class="fas fa-edit"></i> | |
| </button> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td><strong>Metformin</strong></td> | |
| <td>Diabetes</td> | |
| <td>342</td> | |
| <td>$18.99</td> | |
| <td>2025-03-15</td> | |
| <td><span class="stock-badge in-stock">In Stock</span></td> | |
| <td> | |
| <button class="btn btn-secondary" style="padding: 0.25rem 0.5rem; font-size: 0.75rem;" onclick="editMedicine(this)"> | |
| <i class="fas fa-edit"></i> | |
| </button> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <!-- Add/Edit Medicine Modal --> | |
| <div class="modal" id="medicineModal"> | |
| <div class="modal-content"> | |
| <div class="modal-header"> | |
| <h3 class="modal-title" id="modalTitle">Add New Medicine</h3> | |
| <button class="modal-close" onclick="closeMedicineModal()"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <form id="medicineForm" onsubmit="saveMedicine(event)"> | |
| <div class="form-group"> | |
| <label for="medicineName">Medicine Name</label> | |
| <input type="text" id="medicineName" name="medicineName" required> | |
| </div> | |
| <div class="form-group"> | |
| <label for="category">Category</label> | |
| <select id="category" name="category" required> | |
| <option value="">Select Category</option> | |
| <option value="Antibiotics">Antibiotics</option> | |
| <option value="Pain Relief">Pain Relief</option> | |
| <option value="GI Medications">GI Medications</option> | |
| <option value="Diabetes">Diabetes</option> | |
| <option value="Cardiovascular">Cardiovascular</option> | |
| <option value="Vitamins">Vitamins</option> | |
| </select> | |
| </div> | |
| <div class="form-group"> | |
| <label for="stock">Stock Quantity</label> | |
| <input type="number" id="stock" name="stock" min="0" required> | |
| </div> | |
| <div class="form-group"> | |
| <label for="price">Price ($)</label> | |
| <input type="number" id="price" name="price" min="0" step="0.01" required> | |
| </div> | |
| <div class="form-group"> | |
| <label for="expiryDate">Expiry Date</label> | |
| <input type="date" id="expiryDate" name="expiryDate" required> | |
| </div> | |
| <div class="modal-footer"> | |
| <button type="button" class="btn btn-secondary" onclick="closeMedicineModal()">Cancel</button> | |
| <button type="submit" class="btn btn-primary">Save Medicine</button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| <script> | |
| // Sidebar toggle | |
| function toggleSidebar() { | |
| const sidebar = document.getElementById('sidebar'); | |
| const mainContent = document.getElementById('mainContent'); | |
| sidebar.classList.toggle('collapsed'); | |
| mainContent.classList.toggle('expanded'); | |
| } | |
| // Set active navigation | |
| function setActiveNav(element) { | |
| const navItems = document.querySelectorAll('.nav-item'); | |
| navItems.forEach(item => item.classList.remove('active')); | |
| element.classList.add('active'); | |
| } | |
| // Search functionality | |
| function handleSearch(event) { | |
| const searchTerm = event.target.value.toLowerCase(); | |
| console.log('Searching for:', searchTerm); | |
| // Implement search logic here | |
| } | |
| // Show notifications | |
| function showNotifications() { | |
| console.log('Showing notifications'); | |
| // Implement notification logic here | |
| } | |
| // Close alert banner | |
| function closeAlert() { | |
| const alertBanner = document.getElementById('alertBanner'); | |
| alertBanner.style.display = 'none'; | |
| } | |
| // Change chart view | |
| function changeChartView(element, view) { | |
| const buttons = document.querySelectorAll('.chart-option-btn'); | |
| buttons.forEach(btn => btn.classList.remove('active')); | |
| element.classList.add('active'); | |
| console.log('Chart view changed to:', view); | |
| // Implement chart view change logic here | |
| } | |
| // Filter inventory | |
| function filterInventory() { | |
| console.log('Filtering inventory'); | |
| // Implement filter logic here | |
| } | |
| // Open add medicine modal | |
| function openAddMedicineModal() { | |
| const modal = document.getElementById('medicineModal'); | |
| const modalTitle = document.getElementById('modalTitle'); | |
| modalTitle.textContent = 'Add New Medicine'; | |
| modal.classList.add('active'); | |
| } | |
| // Edit medicine | |
| function editMedicine(button) { | |
| const modal = document.getElementById('medicineModal'); | |
| const modalTitle = document.getElementById('modalTitle'); | |
| modalTitle.textContent = 'Edit Medicine'; | |
| modal.classList.add('active'); | |
| // Populate form with existing data | |
| console.log('Editing medicine'); | |
| } | |
| // Close medicine modal | |
| function closeMedicineModal() { | |
| const modal = document.getElementById('medicineModal'); | |
| modal.classList.remove('active'); | |
| } | |
| // Save medicine | |
| function saveMedicine(event) { | |
| event.preventDefault(); | |
| const formData = new FormData(event.target); | |
| const medicineData = Object.fromEntries(formData); | |
| console.log('Saving medicine:', medicineData); | |
| // Implement save logic here | |
| closeMedicineModal(); | |
| } | |
| // Initialize chart | |
| document.addEventListener('DOMContentLoaded', function () { | |
| const ctx = document.getElementById('salesChart').getContext('2d'); | |
| const salesChart = new Chart(ctx, { | |
| type: 'line', | |
| data: { | |
| labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], | |
| datasets: [{ | |
| label: 'Sales ($)', | |
| data: [1200, 1900, 1500, 2500, 2200, 3000, 2800], | |
| backgroundColor: 'rgba(44, 122, 123, 0.2)', | |
| borderColor: '#2c7a7b', | |
| borderWidth: 2, | |
| tension: 0.4, | |
| fill: true | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| plugins: { | |
| legend: { | |
| display: false | |
| } | |
| }, | |
| scales: { | |
| y: { | |
| beginAtZero: true, | |
| grid: { | |
| color: 'rgba(0, 0, 0, 0.05)' | |
| } | |
| }, | |
| x: { | |
| grid: { | |
| display: false | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| }); | |
| // Chart.js | |
| class Chart { | |
| constructor(ctx, config) { | |
| this.ctx = ctx; | |
| this.config = config; | |
| this.draw(); | |
| } | |
| draw() { | |
| const canvas = this.ctx.canvas; | |
| const width = canvas.width = canvas.offsetWidth; | |
| const height = canvas.height = canvas.offsetHeight; | |
| // Clear canvas | |
| this.ctx.clearRect(0, 0, width, height); | |
| // Draw chart based on config | |
| if (this.config.type === 'line') { | |
| this.drawLineChart(); | |
| } | |
| } | |
| drawLineChart() { | |
| const { data, options } = this.config; | |
| const { labels, datasets } = data; | |
| const { y: yAxis, x: xAxis } = options.scales; | |
| const padding = 40; | |
| const chartWidth = this.ctx.canvas.width - padding * 2; | |
| const chartHeight = this.ctx.canvas.height - padding * 2; | |
| // Draw axes | |
| this.ctx.strokeStyle = '#e2e8f0'; | |
| this.ctx.lineWidth = 1; | |
| this.ctx.beginPath(); | |
| this.ctx.moveTo(padding, padding); | |
| this.ctx.lineTo(padding, this.ctx.canvas.height - padding); | |
| this.ctx.lineTo(this.ctx.canvas.width - padding, this.ctx.canvas.height - padding); | |
| this.ctx.stroke(); | |
| // Draw data points and lines | |
| const dataset = datasets[0]; | |
| const maxValue = Math.max(...dataset.data); | |
| const minValue = 0; | |
| const valueRange = maxValue - minValue; | |
| const xStep = chartWidth / (labels.length - 1); | |
| const yStep = chartHeight / valueRange; | |
| // Draw line | |
| this.ctx.strokeStyle = dataset.borderColor; | |
| this.ctx.lineWidth = dataset.borderWidth; | |
| this.ctx.beginPath(); | |
| dataset.data.forEach((value, index) => { | |
| const x = padding + index * xStep; | |
| const y = this.ctx.canvas.height - padding - ((value - minValue) / |