General Ward
+ + + 12 Active Staff + +Seamless Collaboration
+Select a colleague or channel from the sidebar to start sharing clinical updates and patient data securely.
+ +diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..970a2ee --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,169 @@ +:root { + --primary: #3b82f6; + --primary-hover: #2563eb; + --secondary: #64748b; + --success: #10b981; + --danger: #ef4444; + --warning: #f59e0b; + --background: #f8fafc; + --surface: #ffffff; + --border: #e2e8f0; + --text-main: #0f172a; + --text-muted: #64748b; + --shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); +} + +body { + font-family: 'Inter', system-ui, -apple-system, sans-serif; + color: var(--text-main); + background-color: var(--background); +} + +/* Scrollbar */ +::-webkit-scrollbar { + width: 6px; +} +::-webkit-scrollbar-track { + background: transparent; +} +::-webkit-scrollbar-thumb { + background: #cbd5e1; + border-radius: 10px; +} +::-webkit-scrollbar-thumb:hover { + background: #94a3b8; +} + +/* Login Components */ +.login-card { + background: var(--surface); + border-radius: 16px; + border: 1px solid var(--border); + box-shadow: var(--shadow-lg); +} + +.hospital-logo { + display: flex; + align-items: center; + color: var(--primary); +} + +.logo-icon { + background: rgba(59, 130, 246, 0.1); + color: var(--primary); + padding: 10px; + border-radius: 12px; +} + +.form-control { + border-radius: 10px; + border: 1px solid var(--border); + padding: 10px 14px; + font-size: 14px; + transition: all 0.2s; +} + +.form-control:focus { + border-color: var(--primary); + box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.1); +} + +.btn-primary { + background-color: var(--primary); + border-color: var(--primary); + border-radius: 10px; + padding: 10px 20px; + transition: all 0.2s; +} + +.btn-primary:hover { + background-color: var(--primary-hover); + border-color: var(--primary-hover); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2); +} + +/* Dashboard Layout */ +.dashboard-layout { + display: flex; + height: 100vh; + overflow: hidden; +} + +.sidebar { + width: 280px; + background: #f1f5f9; + border-right: 1px solid var(--border); + flex-shrink: 0; +} + +.main-content { + flex-grow: 1; + background: var(--surface); +} + +.main-header { + height: 72px; +} + +.sidebar-header { + height: 72px; +} + +.list-group-item { + border: none; + background: transparent; + color: var(--text-muted); + font-size: 14px; + margin-bottom: 2px; +} + +.list-group-item:hover { + background: rgba(0, 0, 0, 0.03); + color: var(--text-main); +} + +.list-group-item.active { + background: var(--primary) !important; + color: white !important; +} + +/* Roles */ +.role-badge { + padding: 2px 8px; + border-radius: 6px; + font-size: 10px; + font-weight: 600; + text-transform: uppercase; +} + +.role-doctor { background: #e0f2fe; color: #0369a1; } +.role-nurse { background: #f0fdf4; color: #15803d; } +.role-admin_staff { background: #fef2f2; color: #b91c1c; } + +/* Utilities */ +.no-caret::after { + display: none; +} + +.demo-btn { + font-size: 12px !important; + font-weight: 500; + border-radius: 8px; +} + +.demo-btn:hover { + background-color: #f8fafc !important; + border-color: #cbd5e1 !important; +} + +.uppercase { + text-transform: uppercase; +} + +@media (max-width: 768px) { + .sidebar { + display: none; + } +} diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..8029235 --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,60 @@ +document.addEventListener('DOMContentLoaded', function() { + const loginForm = document.getElementById('loginForm'); + const loginAlert = document.getElementById('loginAlert'); + const demoBtns = document.querySelectorAll('.demo-btn'); + + // Handle Demo Buttons + demoBtns.forEach(btn => { + btn.addEventListener('click', function() { + const email = this.getAttribute('data-email'); + const pass = this.getAttribute('data-pass'); + + const emailInput = document.getElementById('email'); + const passInput = document.getElementById('password'); + + if (emailInput && passInput) { + emailInput.value = email; + passInput.value = pass; + // Auto submit + loginForm.dispatchEvent(new Event('submit')); + } + }); + }); + + if (loginForm) { + loginForm.addEventListener('submit', function(e) { + e.preventDefault(); + + const formData = new FormData(loginForm); + formData.append('action', 'login'); + + const submitBtn = loginForm.querySelector('button[type="submit"]'); + const originalText = submitBtn.innerText; + submitBtn.disabled = true; + submitBtn.innerHTML = 'Authenticating...'; + + fetch('auth.php', { + method: 'POST', + body: formData + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + window.location.reload(); + } else { + loginAlert.innerText = data.error; + loginAlert.classList.remove('d-none'); + submitBtn.disabled = false; + submitBtn.innerText = originalText; + } + }) + .catch(error => { + console.error('Error:', error); + loginAlert.innerText = 'Clinical gateway error. Please try again.'; + loginAlert.classList.remove('d-none'); + submitBtn.disabled = false; + submitBtn.innerText = originalText; + }); + }); + } +}); \ No newline at end of file diff --git a/auth.php b/auth.php new file mode 100644 index 0000000..372a818 --- /dev/null +++ b/auth.php @@ -0,0 +1,60 @@ +prepare("SELECT * FROM users WHERE email = ?"); + $stmt->execute([$email]); + $user = $stmt->fetch(); + + if ($user && password_verify($password, $user['password'])) { + $_SESSION['user_id'] = $user['id']; + $_SESSION['hospital_id'] = $user['hospital_id']; + $_SESSION['user_name'] = $user['name']; + $_SESSION['user_role'] = $user['role']; + + // Set online status + $update = db()->prepare("UPDATE users SET online_status = 1 WHERE id = ?"); + $update->execute([$user['id']]); + + return ['success' => true, 'user' => $user]; + } else { + return ['success' => false, 'error' => 'Invalid email or password.']; + } + } catch (PDOException $e) { + return ['success' => false, 'error' => 'System error. Please try again later.']; + } +} + +function logout() { + if (isset($_SESSION['user_id'])) { + try { + $update = db()->prepare("UPDATE users SET online_status = 0 WHERE id = ?"); + $update->execute([$_SESSION['user_id']]); + } catch (PDOException $e) { + // Log error but continue logout + } + } + session_destroy(); + header("Location: index.php"); + exit; +} + +// Handle POST requests +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + header('Content-Type: application/json'); + $action = $_POST['action'] ?? ''; + + if ($action === 'login') { + $email = trim($_POST['email'] ?? ''); + $password = $_POST['password'] ?? ''; + $result = login($email, $password); + echo json_encode($result); + exit; + } +} + +if (isset($_GET['action']) && $_GET['action'] === 'logout') { + logout(); +} \ No newline at end of file diff --git a/db/schema.sql b/db/schema.sql new file mode 100644 index 0000000..825a3be --- /dev/null +++ b/db/schema.sql @@ -0,0 +1,21 @@ +-- Hospital Internal Chat Schema +CREATE TABLE IF NOT EXISTS users ( + id INT AUTO_INCREMENT PRIMARY KEY, + hospital_id VARCHAR(50) NOT NULL UNIQUE, + email VARCHAR(100) NOT NULL UNIQUE, + password VARCHAR(255) NOT NULL, + name VARCHAR(100) NOT NULL, + role ENUM('doctor', 'nurse', 'admin_staff', 'technician', 'pharmacist') NOT NULL, + department VARCHAR(100), + online_status BOOLEAN DEFAULT FALSE, + last_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- Seed data for testing (password is 'password' for all) +INSERT IGNORE INTO users (hospital_id, email, password, name, role, department) VALUES +('DOC001', 'sarah.mitchell@medlink.com', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'Dr. Sarah Mitchell', 'doctor', 'Cardiology'), +('NUR002', 'james.wilson@medlink.com', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'James Wilson, RN', 'nurse', 'Emergency'), +('ADM003', 'elena.rodriguez@medlink.com', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'Elena Rodriguez', 'admin_staff', 'Operations'), +('LAB004', 'david.chen@medlink.com', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'David Chen', 'technician', 'Pathology'), +('PHM005', 'anita.gupta@medlink.com', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'Dr. Anita Gupta', 'pharmacist', 'Pharmacy'); \ No newline at end of file diff --git a/index.php b/index.php index 7205f3d..204e5f1 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,170 @@ - +
- - -= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.
-This page will update automatically as the plan is implemented.
-Runtime: PHP = htmlspecialchars($phpVersion) ?> — UTC = htmlspecialchars($now) ?>
Sign in with your clinical credentials.
+ + + + + +Select a colleague or channel from the sidebar to start sharing clinical updates and patient data securely.
+ +