diff --git a/assets/css/custom.css b/assets/css/custom.css
new file mode 100644
index 0000000..674ef3e
--- /dev/null
+++ b/assets/css/custom.css
@@ -0,0 +1,124 @@
+/* assets/css/custom.css */
+
+body {
+ font-family: 'Poppins', sans-serif;
+ background-color: #F8F9FA;
+ color: #212529;
+}
+
+.sidebar {
+ background-color: #2c3e50;
+ height: 100vh;
+ position: sticky;
+ top: 0;
+}
+
+.sidebar .nav-link {
+ color: rgba(255, 255, 255, 0.7);
+ border-radius: 0.5rem;
+ margin-bottom: 0.5rem;
+}
+
+.sidebar .nav-link:hover {
+ color: #ffffff;
+ background-color: rgba(255, 255, 255, 0.1);
+}
+
+.sidebar .nav-link.active {
+ color: #ffffff;
+ background-color: #4A90E2;
+}
+
+.sidebar .nav-link .bi {
+ font-size: 1.2rem;
+}
+
+.sidebar hr {
+ border-color: rgba(255, 255, 255, 0.2);
+}
+
+.main-content {
+ background-color: #F8F9FA;
+}
+
+.btn-primary-custom {
+ background-color: #4A90E2;
+ border-color: #4A90E2;
+ color: #ffffff;
+ padding: 0.75rem 1.25rem;
+ border-radius: 0.5rem;
+ font-weight: 600;
+ transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out;
+}
+
+.btn-primary-custom:hover {
+ background-color: #357ABD;
+ border-color: #357ABD;
+ color: #ffffff;
+}
+
+.card {
+ border: none;
+ border-radius: 0.5rem;
+ box-shadow: 0 0.15rem 1.75rem 0 rgba(58, 59, 69, 0.15) !important;
+}
+
+.card .card-header {
+ background-color: #fff;
+ border-bottom: 1px solid #e3e6f0;
+ padding: 1rem 1.25rem;
+}
+
+.card .card-body {
+ padding: 1.5rem;
+}
+
+.border-left-primary {
+ border-left: 0.25rem solid #4A90E2 !important;
+}
+
+.text-primary {
+ color: #4A90E2 !important;
+}
+
+.border-left-success {
+ border-left: 0.25rem solid #1cc88a !important;
+}
+
+.text-success {
+ color: #1cc88a !important;
+}
+
+.border-left-info {
+ border-left: 0.25rem solid #36b9cc !important;
+}
+
+.text-info {
+ color: #36b9cc !important;
+}
+
+.text-gray-300 {
+ color: #dddfeb !important;
+}
+
+.text-gray-800 {
+ color: #5a5c69 !important;
+}
+
+.font-weight-bold {
+ font-weight: 700 !important;
+}
+
+.text-xs {
+ font-size: .7rem;
+}
+
+.form-control, .form-select {
+ border-radius: 0.5rem;
+ padding: 0.75rem 1rem;
+}
+
+.form-control:focus, .form-select:focus {
+ box-shadow: 0 0 0 0.25rem rgba(74, 144, 226, 0.25);
+ border-color: #4A90E2;
+}
diff --git a/auth.php b/auth.php
new file mode 100644
index 0000000..8739b2d
--- /dev/null
+++ b/auth.php
@@ -0,0 +1,17 @@
+
\ No newline at end of file
diff --git a/billing.php b/billing.php
new file mode 100644
index 0000000..fea00f0
--- /dev/null
+++ b/billing.php
@@ -0,0 +1,144 @@
+prepare("UPDATE patients SET payment_status = 'paid' WHERE id = ?");
+ $stmt->execute([$patient_id_to_update]);
+ // Redirect to avoid form resubmission
+ header("Location: billing.php");
+ exit;
+ } catch (PDOException $e) {
+ // Log error
+ }
+ }
+}
+
+// Fetch unpaid patients
+try {
+ $pdo = db();
+ $stmt = $pdo->prepare("SELECT p.*, u.username as doctor_name FROM patients p JOIN users u ON p.doctor_id = u.id WHERE p.status = 'Completed' AND p.payment_status = 'unpaid' ORDER BY p.updated_at DESC");
+ $stmt->execute();
+ $unpaid_patients = $stmt->fetchAll(PDO::FETCH_ASSOC);
+} catch (PDOException $e) {
+ $unpaid_patients = [];
+ // Log error
+}
+
+?>
+
+
+
+
+
+ Billing Management
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Patient Name
+ Doctor
+ Service Rendered
+ Cost
+ Action
+
+
+
+
+
+
+ Dr.
+
+ $
+
+
+ Invoice
+
+
+
+
+
+ No pending payments.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/db/config.php b/db/config.php
index b92662e..80b585f 100644
--- a/db/config.php
+++ b/db/config.php
@@ -1,17 +1,36 @@
PDO::ERRMODE_EXCEPTION,
- PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
- ]);
- }
- return $pdo;
+ static $pdo;
+ if ($pdo) {
+ return $pdo;
+ }
+
+ $host = getenv('DB_HOST') ?: '127.0.0.1';
+ $port = getenv('DB_PORT') ?: '3306';
+ $dbname = getenv('DB_NAME') ?: 'app_35705';
+ $user = getenv('DB_USER') ?: 'app_35705';
+ $pass = getenv('DB_PASS') ?: 'cdc156d8-b1ec-4426-86fb-b1e546c1a442';
+ $charset = 'utf8mb4';
+
+ $dsn = "mysql:host=$host;port=$port;dbname=$dbname;charset=$charset";
+ $options = [
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
+ PDO::ATTR_EMULATE_PREPARES => false,
+ ];
+
+ try {
+ $pdo = new PDO($dsn, $user, $pass, $options);
+ return $pdo;
+ } catch (PDOException $e) {
+ // In a real app, you'd log this error and show a generic message
+ throw new PDOException($e->getMessage(), (int)$e->getCode());
+ }
}
+?>
diff --git a/doctor_dashboard.php b/doctor_dashboard.php
new file mode 100644
index 0000000..84f1158
--- /dev/null
+++ b/doctor_dashboard.php
@@ -0,0 +1,248 @@
+prepare("SELECT p.* FROM patients p JOIN users u ON p.doctor_id = u.id WHERE u.id = ? AND DATE(p.created_at) = CURDATE() ORDER BY p.created_at DESC");
+ $stmt->execute([$doctor_id]);
+ $patients = $stmt->fetchAll(PDO::FETCH_ASSOC);
+} catch (PDOException $e) {
+ $patients = [];
+ // In a real app, you'd want to log this error
+}
+
+// Fetch doctor's details from users table
+try {
+ $pdo = db();
+ $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
+ $stmt->execute([$doctor_id]);
+ $doctor = $stmt->fetch(PDO::FETCH_ASSOC);
+} catch (PDOException $e) {
+ $doctor = null;
+}
+
+?>
+
+
+
+
+
+ Doctor's Dashboard
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Patient ID
+ Name
+ Status
+ Action
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No patients assigned for today.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Start Consultation';
+ case 'In Progress':
+ return ''; // Form is shown in a separate row
+ case 'Completed':
+ return ' Completed ';
+ default:
+ return '';
+ }
+}
+?>
\ No newline at end of file
diff --git a/index.php b/index.php
index 7205f3d..bf4a762 100644
--- a/index.php
+++ b/index.php
@@ -1,150 +1,6 @@
-
-
-
-
-
- New Style
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Analyzing your requirements and generating your website…
-
- Loading…
-
-
= ($_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) ?>
-
-
-
- Page updated: = htmlspecialchars($now) ?> (UTC)
-
-
-
+// This is the main entry point of the application.
+// It will redirect the user to the login page.
+header("Location: login.php");
+exit;
+?>
\ No newline at end of file
diff --git a/invoice.php b/invoice.php
new file mode 100644
index 0000000..1b7832a
--- /dev/null
+++ b/invoice.php
@@ -0,0 +1,115 @@
+prepare("
+ SELECT p.*, u.username as doctor_name
+ FROM patients p
+ JOIN users u ON p.doctor_id = u.id
+ WHERE p.id = ? AND p.status = 'Completed'
+ ORDER BY p.updated_at DESC
+ LIMIT 1
+ ");
+ $stmt->execute([$patient_id]);
+ $visit = $stmt->fetch(PDO::FETCH_ASSOC);
+} catch (PDOException $e) {
+ $visit = null;
+ // Log error
+}
+
+if (!$visit) {
+ die("No completed visit found for this patient or an error occurred.");
+}
+
+?>
+
+
+
+
+
+ Invoice -
+
+
+
+
+
+
+
+
+
+
+
+
+
Invoice #: INV-
+
Date:
+
Status:
+
+
+
+
+
Consultation Details:
+
Consulting Doctor: Dr.
+
+
+
+
+
+ Service Rendered
+ Cost
+
+
+
+
+
+ $
+
+
+
+
+
+
Total: $
+
+
+
Print Invoice
+
Back to Billing
+
+
+
+
+
diff --git a/login.php b/login.php
new file mode 100644
index 0000000..0511510
--- /dev/null
+++ b/login.php
@@ -0,0 +1,120 @@
+prepare("SELECT * FROM `users` WHERE `username` = ?");
+ $stmt->execute([$username]);
+ $user = $stmt->fetch();
+
+ if ($user && password_verify($password, $user['password'])) {
+ $_SESSION['user_id'] = $user['id'];
+ $_SESSION['username'] = $user['username'];
+ $_SESSION['role'] = $user['role'];
+
+ // Redirect based on role
+ if ($user['role'] === 'doctor') {
+ header("Location: doctor_dashboard.php");
+ } else {
+ header("Location: reception.php");
+ }
+ exit;
+ } else {
+ $error = 'Invalid username or password.';
+ }
+ } catch (PDOException $e) {
+ $error = 'Database error. Please try again later.';
+ }
+ }
+}
+?>
+
+
+
+
+
+ Login - Clinic Management
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Username
+
+
+
+ Password
+
+
+ Login
+
+
+
+ Default Logins: reception/password, doctor/password
+
+
+
+
+
+
diff --git a/logout.php b/logout.php
new file mode 100644
index 0000000..2d2c92f
--- /dev/null
+++ b/logout.php
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/patient_profile.php b/patient_profile.php
new file mode 100644
index 0000000..a801c78
--- /dev/null
+++ b/patient_profile.php
@@ -0,0 +1,162 @@
+prepare("SELECT * FROM patients WHERE id = ?");
+$stmt->execute([$patient_id]);
+$patient = $stmt->fetch(PDO::FETCH_ASSOC);
+
+if (!$patient) {
+ die("Patient not found.");
+}
+
+// Now, fetch all visits for this patient using their patient_id
+$history_stmt = db()->prepare(
+ "SELECT p.*, d.username as doctor_name
+ FROM patients p
+ LEFT JOIN users d ON p.doctor_id = d.id
+ WHERE p.patient_id = ?
+ ORDER BY p.created_at DESC"
+);
+$history_stmt->execute([$patient['patient_id']]);
+$visit_history = $history_stmt->fetchAll(PDO::FETCH_ASSOC);
+
+?>
+
+
+
+
+
+ Patient Profile - = htmlspecialchars($patient['patient_name']) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Patient Profile
+
+ Back to Dashboard
+
+
+
+
+
+
+
+
+
+
Phone: = htmlspecialchars($patient['phone_number']) ?>
+
+
+
Address: = htmlspecialchars($patient['address']) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Visit Date
+ Assigned Doctor
+ Status
+ Consultation Notes
+
+
+
+
+
+ No visit history found.
+
+
+
+
+ = date("d M, Y h:i A", strtotime($visit['created_at'])) ?>
+ = htmlspecialchars($visit['doctor_name'] ?? 'N/A') ?>
+
+
+ = $status ?>
+
+ = nl2br(htmlspecialchars($visit['notes'] ?? 'No notes added.')) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/patient_register.php b/patient_register.php
new file mode 100644
index 0000000..7ee3c6e
--- /dev/null
+++ b/patient_register.php
@@ -0,0 +1,152 @@
+query("SELECT id, username FROM users WHERE role = 'doctor' ORDER BY username");
+ $doctors = $stmt->fetchAll(PDO::FETCH_ASSOC);
+} catch (PDOException $e) {
+ $error = "Database error: " . $e->getMessage();
+}
+
+if ($_SERVER["REQUEST_METHOD"] == "POST") {
+ $patient_name = trim($_POST['patient_name']);
+ $phone_number = trim($_POST['phone_number']);
+ $address = trim($_POST['address']);
+ $doctor_id = $_POST['doctor_id'];
+
+ if (empty($patient_name) || empty($doctor_id)) {
+ $error = "Patient name and assigned doctor are required.";
+ } else {
+ try {
+ // Generate a unique patient ID
+ $prefix = 'PT';
+ $stmt = $pdo->query("SELECT MAX(id) FROM patients");
+ $last_id = $stmt->fetchColumn();
+ $next_id = ($last_id) ? $last_id + 1 : 1;
+ $patient_id = $prefix . str_pad($next_id, 6, '0', STR_PAD_LEFT);
+
+ // Set initial status
+ $status = 'Pending';
+ $total_fee = 20.00; // Example fee
+
+ $sql = "INSERT INTO patients (patient_id, patient_name, phone_number, address, doctor_id, status, total_fee) VALUES (?, ?, ?, ?, ?, ?, ?)";
+ $stmt = $pdo->prepare($sql);
+
+ if ($stmt->execute([$patient_id, $patient_name, $phone_number, $address, $doctor_id, $status, $total_fee])) {
+ $_SESSION['message'] = "Patient registered successfully! Patient ID: $patient_id";
+ header("Location: reception.php");
+ exit();
+ } else {
+ $error = "Failed to register patient.";
+ }
+ } catch (PDOException $e) {
+ $error = "Database error: " . $e->getMessage();
+ }
+ }
+}
+?>
+
+
+
+
+
+ Register Patient - Hospital Management
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/reception.php b/reception.php
new file mode 100644
index 0000000..13b4474
--- /dev/null
+++ b/reception.php
@@ -0,0 +1,201 @@
+query("SELECT count(id) FROM patients WHERE DATE(created_at) = CURDATE()")->fetchColumn();
+$total_patients = $pdo->query("SELECT count(id) FROM patients")->fetchColumn();
+$total_revenue = $pdo->query("SELECT SUM(total_fee) FROM patients WHERE status = 'Completed'")->fetchColumn();
+
+?>
+
+
+
+
+
+ Reception Dashboard - Hospital Management
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Receptionist Dashboard
+
+
+ Register New Patient
+
+
+
+
+
+
+
+
+
+
+
+ Patients Registered (Today)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Search
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Patient ID
+ Patient Name
+ Phone Number
+ Assigned Doctor
+ Status
+ Date
+
+
+
+ prepare($sql);
+ $stmt->execute($params);
+
+ if ($stmt->rowCount() > 0) {
+ while ($row = $stmt->fetch()) {
+ echo "";
+ echo "" . htmlspecialchars($row['patient_name']) . " ";
+ echo "" . htmlspecialchars($row['phone_number']) . " ";
+ echo "" . htmlspecialchars($row['doctor_name'] ?? 'N/A') . " ";
+ echo "" . htmlspecialchars($row['status']) . " ";
+ echo "" . date("Y-m-d H:i", strtotime($row['created_at'])) . " ";
+ echo " ";
+ }
+ } else {
+ echo 'No patients found. ';
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/update_patient_status.php b/update_patient_status.php
new file mode 100644
index 0000000..a74b189
--- /dev/null
+++ b/update_patient_status.php
@@ -0,0 +1,75 @@
+ false, 'message' => 'Invalid request'];
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ $patient_id = $_POST['patient_id'] ?? null;
+ $status = $_POST['status'] ?? null;
+ $notes = $_POST['notes'] ?? null;
+ $service_rendered = $_POST['service_rendered'] ?? null;
+ $cost = $_POST['cost'] ?? null;
+
+ if ($patient_id && $status) {
+ try {
+ $pdo = db();
+ $sql = "UPDATE patients SET status = ?";
+ $params = [$status];
+
+ if ($notes !== null) {
+ $sql .= ", notes = ?";
+ $params[] = $notes;
+ }
+
+ if ($service_rendered !== null) {
+ $sql .= ", service_rendered = ?";
+ $params[] = $service_rendered;
+ }
+
+ if ($cost !== null) {
+ $sql .= ", cost = ?";
+ $params[] = $cost;
+ }
+
+ // When completing, set payment_status to unpaid
+ if ($status === 'Completed') {
+ $sql .= ", payment_status = 'unpaid'";
+ }
+
+ $sql .= " WHERE id = ?";
+ $params[] = $patient_id;
+
+ $stmt = $pdo->prepare($sql);
+
+ if ($stmt->execute($params)) {
+ $response['success'] = true;
+ $response['message'] = 'Patient status updated successfully.';
+ $response['status_class'] = get_status_badge_class($status);
+ } else {
+ $response['message'] = 'Failed to update patient status.';
+ }
+ } catch (PDOException $e) {
+ $response['message'] = 'Database error: ' . $e->getMessage();
+ }
+ } else {
+ $response['message'] = 'Missing patient ID or status.';
+ }
+}
+
+echo json_encode($response);
+
+function get_status_badge_class($status) {
+ switch ($status) {
+ case 'Pending':
+ return 'warning';
+ case 'In Progress':
+ return 'info';
+ case 'Completed':
+ return 'success';
+ default:
+ return 'secondary';
+ }
+}
+?>
\ No newline at end of file