@@ -234,7 +234,7 @@ function validateHolidayFrontend() {
}
if (isHoliday) {
- $('
').appendTo('#appointmentDetailsModal .modal-body');
if (btnSave) btnSave.disabled = true;
} else {
if (btnSave) btnSave.disabled = false;
@@ -447,7 +447,7 @@ document.addEventListener('DOMContentLoaded', function() {
eventClick: function(info) {
if (info.event.extendedProps.type === 'appointment') {
var props = info.event.extendedProps;
- document.getElementById('modalTitle').innerText = 'Edit Appointment';
+ document.getElementById('modalTitle').innerText = '';
document.getElementById('apt_id').value = info.event.id;
$('#apt_patient_id').val(props.patient_id).trigger('change');
diff --git a/includes/pages/doctor_holidays.php b/includes/pages/doctor_holidays.php
index a91d808..1356d40 100644
--- a/includes/pages/doctor_holidays.php
+++ b/includes/pages/doctor_holidays.php
@@ -17,11 +17,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($action === 'create') {
$stmt = $db->prepare("INSERT INTO doctor_holidays (doctor_id, start_date, end_date, note) VALUES (?, ?, ?, ?)");
$stmt->execute([$doctor_id, $start_date, $end_date, $note]);
- $_SESSION['flash_message'] = "Holiday added successfully.";
+ $_SESSION['flash_message'] = __('holiday_added_successfully');
} else {
$stmt = $db->prepare("UPDATE doctor_holidays SET doctor_id = ?, start_date = ?, end_date = ?, note = ? WHERE id = ?");
$stmt->execute([$doctor_id, $start_date, $end_date, $note, $id]);
- $_SESSION['flash_message'] = "Holiday updated successfully.";
+ $_SESSION['flash_message'] = __('holiday_updated_successfully');
}
}
} elseif ($action === 'delete') {
@@ -29,7 +29,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($id) {
$stmt = $db->prepare("DELETE FROM doctor_holidays WHERE id = ?");
$stmt->execute([$id]);
- $_SESSION['flash_message'] = "Holiday deleted successfully.";
+ $_SESSION['flash_message'] = __('holiday_deleted_successfully');
}
}
// Redirect to avoid resubmission
@@ -70,7 +70,7 @@ $holidays = $db->query("SELECT dh.*, d.name_$lang as doctor_name FROM doctor_hol
@@ -111,7 +111,7 @@ $holidays = $db->query("SELECT dh.*, d.name_$lang as doctor_name FROM doctor_hol
@@ -74,7 +74,7 @@ $appointments = $stmt->fetchAll();
-
+
@@ -88,7 +88,7 @@ $appointments = $stmt->fetchAll();
-
+
@@ -104,7 +104,7 @@ $appointments = $stmt->fetchAll();
} elseif ($app['nurse_id']) {
echo htmlspecialchars($app['nurse_name']) . ' (' . __('nurse') . ')';
} else {
- echo '
Unassigned';
+ echo '
' . __('unassigned') . '';
}
?>
@@ -113,7 +113,7 @@ $appointments = $stmt->fetchAll();
- Reason:
+ :
@@ -121,7 +121,7 @@ $appointments = $stmt->fetchAll();
@@ -136,7 +136,7 @@ $appointments = $stmt->fetchAll();
@@ -147,21 +147,21 @@ $appointments = $stmt->fetchAll();
-
+
diff --git a/includes/pages/profile.php b/includes/pages/profile.php
new file mode 100644
index 0000000..879cff5
--- /dev/null
+++ b/includes/pages/profile.php
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 ? $user['avatar'] : 'assets/images/default-avatar.png'; ?>)
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/includes/pages/roles.php b/includes/pages/roles.php
index c5e7bef..4ef4b40 100644
--- a/includes/pages/roles.php
+++ b/includes/pages/roles.php
@@ -118,7 +118,11 @@ $available_permissions = [
- |
|
-
+
@@ -229,12 +235,12 @@ $roles = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
\ No newline at end of file
diff --git a/lang.php b/lang.php
index 63c9dc5..4aa87f9 100644
--- a/lang.php
+++ b/lang.php
@@ -193,8 +193,6 @@ $translations = [
'filter' => 'Filter',
'all_departments' => 'All Departments',
'total' => 'Total',
-
- // Dashboard & Common Missing Keys
'total_patients' => 'Total Patients',
'today_appointments' => 'Today\'s Appointments',
'today' => 'Today',
@@ -218,16 +216,97 @@ $translations = [
'reason' => 'Reason',
'new_visit' => 'New Visit',
'select' => 'Select',
+ 'select_doctor' => 'Select Doctor',
'issue_token' => 'Issue Token',
'select_service' => 'Select Service',
'print_bill' => 'Print Bill',
'close' => 'Close',
-
- // Login & Auth
+ 'print' => 'Print',
+ 'add_bill' => 'Add Bill',
+ 'patient_number' => 'File No.',
+ 'age' => 'Age',
+ 'policy_number' => 'Policy No.',
+ 'or' => 'or',
+ 'showing' => 'Showing',
+ 'of' => 'of',
+ 'add_holiday' => 'Add Holiday',
+ 'edit_holiday' => 'Edit Holiday',
+ 'start_date' => 'Start Date',
+ 'end_date' => 'End Date',
+ 'note' => 'Note',
+ 'delete_holiday' => 'Delete Holiday',
+ 'are_you_sure_delete_holiday' => 'Are you sure you want to delete this holiday?',
+ 'holiday_added_successfully' => 'Holiday added successfully.',
+ 'holiday_updated_successfully' => 'Holiday updated successfully.',
+ 'holiday_deleted_successfully' => 'Holiday deleted successfully.',
+ 'no_holidays_found' => 'No holidays found',
+ 'add_service' => 'Add Service',
+ 'edit_service' => 'Edit Service',
+ 'delete_service' => 'Delete Service',
+ 'service_added_successfully' => 'Service added successfully',
+ 'service_updated_successfully' => 'Service updated successfully',
+ 'service_deleted_successfully' => 'Service deleted successfully',
+ 'no_services_found' => 'No services found',
+ 'are_you_sure_delete_service' => 'Are you sure you want to delete this service?',
+ 'price' => 'Price',
+ 'search_by_name' => 'Search by name',
+ 'save_changes' => 'Save Changes',
+ 'add_city' => 'Add City',
+ 'edit_city' => 'Edit City',
+ 'delete_city' => 'Delete City',
+ 'no_cities_found' => 'No cities found',
+ 'are_you_sure_delete' => 'Are you sure you want to delete?',
+ 'action_cannot_be_undone' => 'This action cannot be undone.',
+ 'add_ad' => 'Add Ad',
+ 'edit_ad' => 'Edit Ad',
+ 'delete_ad' => 'Delete Ad',
+ 'ad_text_en' => 'Ad Text (English)',
+ 'ad_text_ar' => 'Ad Text (Arabic)',
+ 'no_ads_found' => 'No ads found',
+ 'scheduled' => 'Scheduled',
+ 'completed' => 'Completed',
+ 'cancelled' => 'Cancelled',
+ 'no_address_provided' => 'No address provided',
+ 'provider' => 'Provider',
+ 'unassigned' => 'Unassigned',
+ 'reason_label' => 'Reason',
+ 'complete' => 'Complete',
+ 'complete_home_visit' => 'Complete Home Visit',
+ 'notes_treatment' => 'Notes / Treatment',
+ 'create_bill' => 'Create Bill',
+ 'save_complete' => 'Save & Complete',
+ 'no_appointments_found' => 'No appointments found',
+ 'doctor_is_on_holiday_on_this_date' => 'Selected doctor is on holiday on this date.',
+ 'edit_appointment' => 'Edit Appointment',
+ 'appointment_details' => 'Appointment Details',
+ 'print_daily_list' => 'Print Daily List',
+ 'appointments_list' => 'Appointments List',
+ 'back' => 'Back',
+ 'no_appointments' => 'No appointments found',
+ 'printed_on' => 'Printed on',
'fill_all_fields' => 'Please fill in all fields',
'invalid_credentials' => 'Invalid email or password',
'login_to_continue' => 'Login to continue to your account',
'forgot_password' => 'Forgot Password?',
+ 'user_profile' => 'User Profile',
+ 'profile_picture' => 'Profile Picture',
+ 'edit_profile' => 'Edit Profile',
+ 'change_avatar' => 'Change Avatar',
+ 'choose_file' => 'Choose file',
+ 'allowed_file_types' => 'Allowed file types',
+ 'change_password' => 'Change Password',
+ 'leave_blank_to_keep_current' => 'Leave blank to keep current password',
+ 'new_password' => 'New Password',
+ 'confirm_password' => 'Confirm Password',
+ 'name_required' => 'Name is required',
+ 'email_required' => 'Email is required',
+ 'email_already_taken' => 'Email is already taken',
+ 'password_min_length' => 'Password must be at least 6 characters',
+ 'passwords_do_not_match' => 'Passwords do not match',
+ 'invalid_file_type' => 'Invalid file type. Only JPG, PNG and GIF are allowed.',
+ 'upload_failed' => 'File upload failed',
+ 'profile_updated_successfully' => 'Profile updated successfully',
+ 'error_updating_profile' => 'Error updating profile',
],
'ar' => [
'dashboard' => 'لوحة التحكم',
@@ -422,8 +501,6 @@ $translations = [
'filter' => 'تصفية',
'all_departments' => 'كل الأقسام',
'total' => 'الإجمالي',
-
- // Dashboard & Common Missing Keys - Arabic
'total_patients' => 'إجمالي المرضى',
'today_appointments' => 'مواعيد اليوم',
'today' => 'اليوم',
@@ -447,15 +524,96 @@ $translations = [
'reason' => 'السبب',
'new_visit' => 'زيارة جديدة',
'select' => 'اختر',
+ 'select_doctor' => 'اختر الطبيب',
'issue_token' => 'إصدار تذكرة',
'select_service' => 'اختر الخدمة',
'print_bill' => 'طباعة الفاتورة',
'close' => 'إغلاق',
-
- // Login & Auth
+ 'print' => 'طباعة',
+ 'add_bill' => 'إضافة فاتورة',
+ 'patient_number' => 'رقم الملف',
+ 'age' => 'العمر',
+ 'policy_number' => 'رقم البوليصة',
+ 'or' => 'أو',
+ 'showing' => 'عرض',
+ 'of' => 'من',
+ 'add_holiday' => 'إضافة إجازة',
+ 'edit_holiday' => 'تعديل إجازة',
+ 'start_date' => 'تاريخ البدء',
+ 'end_date' => 'تاريخ الانتهاء',
+ 'note' => 'ملاحظة',
+ 'delete_holiday' => 'حذف إجازة',
+ 'are_you_sure_delete_holiday' => 'هل أنت متأكد من حذف هذه الإجازة؟',
+ 'holiday_added_successfully' => 'تم إضافة الإجازة بنجاح.',
+ 'holiday_updated_successfully' => 'تم تحديث الإجازة بنجاح.',
+ 'holiday_deleted_successfully' => 'تم حذف الإجازة بنجاح.',
+ 'no_holidays_found' => 'لم يتم العثور على إجازات',
+ 'add_service' => 'إضافة خدمة',
+ 'edit_service' => 'تعديل خدمة',
+ 'delete_service' => 'حذف خدمة',
+ 'service_added_successfully' => 'تم إضافة الخدمة بنجاح',
+ 'service_updated_successfully' => 'تم تحديث الخدمة بنجاح',
+ 'service_deleted_successfully' => 'تم حذف الخدمة بنجاح',
+ 'no_services_found' => 'لم يتم العثور على خدمات',
+ 'are_you_sure_delete_service' => 'هل أنت متأكد من حذف هذه الخدمة؟',
+ 'price' => 'السعر',
+ 'search_by_name' => 'بحث بالاسم',
+ 'save_changes' => 'حفظ التغييرات',
+ 'add_city' => 'إضافة مدينة',
+ 'edit_city' => 'تعديل مدينة',
+ 'delete_city' => 'حذف مدينة',
+ 'no_cities_found' => 'لم يتم العثور على مدن',
+ 'are_you_sure_delete' => 'هل أنت متأكد من الحذف؟',
+ 'action_cannot_be_undone' => 'لا يمكن التراجع عن هذا الإجراء.',
+ 'add_ad' => 'إضافة إعلان',
+ 'edit_ad' => 'تعديل إعلان',
+ 'delete_ad' => 'حذف إعلان',
+ 'ad_text_en' => 'نص الإعلان (إنجليزي)',
+ 'ad_text_ar' => 'نص الإعلان (عربي)',
+ 'no_ads_found' => 'لا توجد إعلانات',
+ 'scheduled' => 'مجدولة',
+ 'completed' => 'مكتملة',
+ 'cancelled' => 'ملغاة',
+ 'no_address_provided' => 'لم يتم تقديم عنوان',
+ 'provider' => 'المقدم',
+ 'unassigned' => 'غير معين',
+ 'reason_label' => 'السبب',
+ 'complete' => 'إكمال',
+ 'complete_home_visit' => 'إكمال الزيارة المنزلية',
+ 'notes_treatment' => 'ملاحظات / العلاج',
+ 'create_bill' => 'إنشاء فاتورة',
+ 'save_complete' => 'حفظ وإكمال',
+ 'no_appointments_found' => 'لا توجد مواعيد',
+ 'doctor_is_on_holiday_on_this_date' => 'الطبيب المحدد في إجازة في هذا التاريخ.',
+ 'edit_appointment' => 'تعديل موعد',
+ 'appointment_details' => 'تفاصيل الموعد',
+ 'print_daily_list' => 'طباعة القائمة اليومية',
+ 'appointments_list' => 'قائمة المواعيد',
+ 'back' => 'رجوع',
+ 'no_appointments' => 'لم يتم العثور على مواعيد',
+ 'printed_on' => 'تم الطباعة في',
'fill_all_fields' => 'يرجى ملء جميع الحقول',
'invalid_credentials' => 'البريد الإلكتروني أو كلمة المرور غير صحيحة',
'login_to_continue' => 'قم بتسجيل الدخول للمتابعة',
'forgot_password' => 'هل نسيت كلمة المرور؟',
+ 'user_profile' => 'الملف الشخصي',
+ 'profile_picture' => 'الصورة الشخصية',
+ 'edit_profile' => 'تعديل الملف الشخصي',
+ 'change_avatar' => 'تغيير الصورة',
+ 'choose_file' => 'اختر ملف',
+ 'allowed_file_types' => 'أنواع الملفات المسموحة',
+ 'change_password' => 'تغيير كلمة المرور',
+ 'leave_blank_to_keep_current' => 'اتركه فارغاً للاحتفاظ بكلمة المرور الحالية',
+ 'new_password' => 'كلمة المرور الجديدة',
+ 'confirm_password' => 'تأكيد كلمة المرور',
+ 'name_required' => 'الاسم مطلوب',
+ 'email_required' => 'البريد الإلكتروني مطلوب',
+ 'email_already_taken' => 'البريد الإلكتروني مسجل مسبقاً',
+ 'password_min_length' => 'يجب أن تتكون كلمة المرور من 6 أحرف على الأقل',
+ 'passwords_do_not_match' => 'كلمات المرور غير متطابقة',
+ 'invalid_file_type' => 'نوع الملف غير صالح. مسموح فقط بـ JPG, PNG, GIF.',
+ 'upload_failed' => 'فشل تحميل الملف',
+ 'profile_updated_successfully' => 'تم تحديث الملف الشخصي بنجاح',
+ 'error_updating_profile' => 'خطأ في تحديث الملف الشخصي',
]
-];
\ No newline at end of file
+];
diff --git a/profile.php b/profile.php
new file mode 100644
index 0000000..cd1a79e
--- /dev/null
+++ b/profile.php
@@ -0,0 +1,99 @@
+prepare("SELECT id FROM users WHERE email = ? AND id != ?");
+ $stmt->execute([$email, $user['id']]);
+ if ($stmt->fetch()) {
+ $errors[] = __('email_already_taken');
+ }
+
+ if (!empty($password)) {
+ if (strlen($password) < 6) {
+ $errors[] = __('password_min_length');
+ }
+ if ($password !== $password_confirm) {
+ $errors[] = __('passwords_do_not_match');
+ }
+ }
+
+ // Handle avatar upload
+ $avatar_path = $user['avatar'];
+ if (isset($_FILES['avatar']) && $_FILES['avatar']['error'] === UPLOAD_ERR_OK) {
+ $file_tmp = $_FILES['avatar']['tmp_name'];
+ $file_name = $_FILES['avatar']['name'];
+ $file_ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
+ $allowed_exts = ['jpg', 'jpeg', 'png', 'gif'];
+
+ if (!in_array($file_ext, $allowed_exts)) {
+ $errors[] = __('invalid_file_type');
+ } else {
+ $upload_dir = 'assets/uploads/users/';
+ if (!is_dir($upload_dir)) {
+ mkdir($upload_dir, 0755, true);
+ }
+
+ $new_file_name = 'user_' . $user['id'] . '_' . time() . '.' . $file_ext;
+ $destination = $upload_dir . $new_file_name;
+
+ if (move_uploaded_file($file_tmp, $destination)) {
+ $avatar_path = $destination;
+ } else {
+ $errors[] = __('upload_failed');
+ }
+ }
+ }
+
+ if (empty($errors)) {
+ try {
+ $sql = "UPDATE users SET name = ?, email = ?, avatar = ?";
+ $params = [$name, $email, $avatar_path];
+
+ if (!empty($password)) {
+ $sql .= ", password = ?";
+ $params[] = password_hash($password, PASSWORD_DEFAULT);
+ }
+
+ $sql .= " WHERE id = ?";
+ $params[] = $user['id'];
+
+ $stmt = $db->prepare($sql);
+ $stmt->execute($params);
+
+ // Update session cache
+ unset($_SESSION['user_cache']);
+ $user = current_user(); // Refresh user data
+
+ $success_msg = __('profile_updated_successfully');
+ } catch (Exception $e) {
+ $errors[] = __('error_updating_profile') . ': ' . $e->getMessage();
+ }
+ }
+}
+
+require_once 'includes/layout/header.php';
+require_once 'includes/pages/profile.php';
+require_once 'includes/layout/footer.php';
diff --git a/test_api_appointments.php b/test_api_appointments.php
deleted file mode 100644
index 2f242d3..0000000
--- a/test_api_appointments.php
+++ /dev/null
@@ -1,5 +0,0 @@
- 'create',
- 'patient_id' => 2,
- 'doctor_id' => 1,
- 'nurse_id' => null,
- 'visit_type' => 'Clinic',
- 'address' => '',
- 'start_time' => '2026-03-25T10:00',
- 'reason' => 'Test API'
-];
-
-$ch = curl_init('http://localhost/api/appointments.php');
-curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-curl_setopt($ch, CURLOPT_POST, true);
-curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
-curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
-
-$response = curl_exec($ch);
-$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
-
-if ($response === false) {
- echo "Curl Error: " . curl_error($ch);
-} else {
- echo "HTTP Code: $http_code\n";
- echo "Response: $response\n";
-}
-curl_close($ch);
\ No newline at end of file
|