user profile
This commit is contained in:
parent
5e776c9e2b
commit
6387f7c226
BIN
assets/uploads/users/user_1_1774149432.jpg
Normal file
BIN
assets/uploads/users/user_1_1774149432.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
1
db/migrations/20260322_add_avatar_to_users.sql
Normal file
1
db/migrations/20260322_add_avatar_to_users.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE users ADD COLUMN avatar VARCHAR(255) DEFAULT NULL;
|
||||
@ -269,18 +269,21 @@ $site_favicon = !empty($site_settings['company_favicon']) ? $site_settings['comp
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#topNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="topNav">
|
||||
<div class="ms-auto d-flex align-items-center">
|
||||
<div class="collapse navbar-collapse justify-content-end" id="topNav">
|
||||
<div class="d-flex align-items-center">
|
||||
<a href="?lang=<?php echo get_lang_code(); ?>" class="btn btn-outline-secondary btn-sm me-3">
|
||||
<i class="bi bi-translate"></i> <?php echo get_lang_name(); ?>
|
||||
</a>
|
||||
<div class="dropdown">
|
||||
<a class="nav-link dropdown-toggle d-flex align-items-center" href="#" role="button" data-bs-dropdown="dropdown">
|
||||
<img src="https://ui-avatars.com/api/?name=<?php echo urlencode($current_user['name']); ?>&background=0056b3&color=fff" class="rounded-circle me-2" width="32" height="32">
|
||||
<a class="nav-link dropdown-toggle d-flex align-items-center" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<?php
|
||||
$user_avatar = !empty($current_user['avatar']) ? $current_user['avatar'] : "https://ui-avatars.com/api/?name=" . urlencode($current_user['name']) . "&background=0056b3&color=fff";
|
||||
?>
|
||||
<img src="<?php echo htmlspecialchars($user_avatar); ?>" class="rounded-circle me-2" width="32" height="32" style="object-fit: cover;">
|
||||
<span><?php echo htmlspecialchars($current_user['name']); ?></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow border-0">
|
||||
<li><a class="dropdown-item" href="#"><i class="bi bi-person me-2"></i> <?php echo __('profile'); ?> (<?php echo htmlspecialchars($current_user['role_slug']); ?>)</a></li>
|
||||
<li><a class="dropdown-item" href="profile.php"><i class="bi bi-person me-2"></i> <?php echo __('profile'); ?> (<?php echo htmlspecialchars($current_user['role_slug']); ?>)</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item text-danger" href="logout.php"><i class="bi bi-box-arrow-right me-2"></i> <?php echo __('logout'); ?></a></li>
|
||||
</ul>
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<h3 class="fw-bold text-secondary"><?php echo __('appointments'); ?></h3>
|
||||
<div>
|
||||
<button class="btn btn-outline-secondary shadow-sm me-2" onclick="printAppointments()">
|
||||
<i class="bi bi-printer me-1"></i> Print Daily List
|
||||
<i class="bi bi-printer me-1"></i> <?php echo __('print_daily_list'); ?>
|
||||
</button>
|
||||
<button class="btn btn-primary shadow-sm" onclick="showCreateModal()">
|
||||
<i class="bi bi-calendar-plus me-1"></i> <?php echo __('book_appointment'); ?>
|
||||
@ -19,7 +19,7 @@
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label small text-muted"><?php echo __('doctor'); ?> (Filter)</label>
|
||||
<label class="form-label small text-muted"><?php echo __('doctor'); ?> (<?php echo __('filter'); ?>)</label>
|
||||
<select id="doctorFilter" class="form-select bg-light">
|
||||
<option value=""><?php echo __('all'); ?> <?php echo __('doctors'); ?></option>
|
||||
<?php foreach ($all_doctors as $d): ?>
|
||||
@ -31,19 +31,19 @@
|
||||
<div class="d-flex align-items-end h-100 pb-1 flex-wrap">
|
||||
<div class="d-flex align-items-center me-3 mb-2">
|
||||
<div class="badge bg-primary me-2" style="width: 15px; height: 15px; border-radius: 50%;"> </div>
|
||||
<small class="text-muted">Scheduled</small>
|
||||
<small class="text-muted"><?php echo __('scheduled'); ?></small>
|
||||
</div>
|
||||
<div class="d-flex align-items-center me-3 mb-2">
|
||||
<div class="badge bg-success me-2" style="width: 15px; height: 15px; border-radius: 50%;"> </div>
|
||||
<small class="text-muted">Completed</small>
|
||||
<small class="text-muted"><?php echo __('completed'); ?></small>
|
||||
</div>
|
||||
<div class="d-flex align-items-center me-3 mb-2">
|
||||
<div class="badge bg-danger me-2" style="width: 15px; height: 15px; border-radius: 50%;"> </div>
|
||||
<small class="text-muted">Cancelled</small>
|
||||
<small class="text-muted"><?php echo __('cancelled'); ?></small>
|
||||
</div>
|
||||
<div class="d-flex align-items-center me-3 mb-2">
|
||||
<div class="badge me-2" style="width: 15px; height: 15px; border-radius: 50%; background-color: #fd7e14;"> </div>
|
||||
<small class="text-muted">Home Visit</small>
|
||||
<small class="text-muted"><?php echo __('home_visits'); ?></small>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<div class="badge bg-warning me-2" style="width: 15px; height: 15px; border-radius: 50%;"> </div>
|
||||
@ -66,7 +66,7 @@
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header border-0 pb-0">
|
||||
<h5 class="modal-title fw-bold text-secondary" id="modalTitle">Appointment Details</h5>
|
||||
<h5 class="modal-title fw-bold text-secondary" id="modalTitle"><?php echo __('appointment_details'); ?></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body pt-3">
|
||||
@ -89,10 +89,10 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small text-muted">Provider Type</label>
|
||||
<label class="form-label small text-muted"><?php echo __('provider'); ?></label>
|
||||
<select id="apt_provider_type" class="form-select" onchange="toggleProviderField()">
|
||||
<option value="Doctor">Doctor</option>
|
||||
<option value="Nurse">Nurse</option>
|
||||
<option value="Doctor"><?php echo __('doctor'); ?></option>
|
||||
<option value="Nurse"><?php echo __('nurse'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@ -105,7 +105,7 @@
|
||||
<div class="mb-3" id="div_doctor">
|
||||
<label class="form-label small text-muted"><?php echo __('doctor'); ?></label>
|
||||
<select id="apt_doctor_id" class="form-select select2-modal-apt">
|
||||
<option value="">Select Doctor</option>
|
||||
<option value=""><?php echo __('select_doctor'); ?></option>
|
||||
<?php foreach ($all_doctors as $d): ?>
|
||||
<option value="<?php echo $d['id']; ?>"><?php echo htmlspecialchars($d['name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
@ -130,9 +130,9 @@
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label small text-muted"><?php echo __('status'); ?></label>
|
||||
<select id="apt_status" class="form-select">
|
||||
<option value="Scheduled">Scheduled</option>
|
||||
<option value="Completed">Completed</option>
|
||||
<option value="Cancelled">Cancelled</option>
|
||||
<option value="Scheduled"><?php echo __('scheduled'); ?></option>
|
||||
<option value="Completed"><?php echo __('completed'); ?></option>
|
||||
<option value="Cancelled"><?php echo __('cancelled'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@ -234,7 +234,7 @@ function validateHolidayFrontend() {
|
||||
}
|
||||
|
||||
if (isHoliday) {
|
||||
$('<div id="holidayWarning" class="alert alert-warning mt-3 mb-0 small"><i class="bi bi-exclamation-triangle"></i> Selected doctor is on holiday on this date.</div>').appendTo('#appointmentDetailsModal .modal-body');
|
||||
$('<div id="holidayWarning" class="alert alert-warning mt-3 mb-0 small"><i class="bi bi-exclamation-triangle"></i> <?php echo __('doctor_is_on_holiday_on_this_date'); ?></div>').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 = '<?php echo __('edit_appointment'); ?>';
|
||||
document.getElementById('apt_id').value = info.event.id;
|
||||
$('#apt_patient_id').val(props.patient_id).trigger('change');
|
||||
|
||||
|
||||
@ -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
|
||||
<tr>
|
||||
<td colspan="5" class="text-center py-4 text-muted">
|
||||
<i class="bi bi-calendar-x display-6 d-block mb-2"></i>
|
||||
No holidays found.
|
||||
<?php echo __('no_holidays_found'); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
@ -111,7 +111,7 @@ $holidays = $db->query("SELECT dh.*, d.name_$lang as doctor_name FROM doctor_hol
|
||||
<div class="mb-3">
|
||||
<label class="form-label small text-muted"><?php echo __('doctor'); ?></label>
|
||||
<select name="doctor_id" id="doctorId" class="form-select" required>
|
||||
<option value="">Select Doctor</option>
|
||||
<option value=""><?php echo __('select') . ' ' . __('doctor'); ?></option>
|
||||
<?php foreach ($doctors as $d): ?>
|
||||
<option value="<?php echo $d['id']; ?>"><?php echo htmlspecialchars($d['name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
@ -171,7 +171,7 @@ function showEditModal(data) {
|
||||
}
|
||||
|
||||
function deleteHoliday(id) {
|
||||
if (confirm('Are you sure you want to delete this holiday?')) {
|
||||
if (confirm('<?php echo __('are_you_sure_delete_holiday'); ?>')) {
|
||||
document.getElementById('deleteId').value = id;
|
||||
document.getElementById('deleteForm').submit();
|
||||
}
|
||||
|
||||
@ -52,9 +52,9 @@ $appointments = $stmt->fetchAll();
|
||||
<label class="form-label small text-muted"><?php echo __('status'); ?></label>
|
||||
<select name="status" class="form-select" onchange="this.form.submit()">
|
||||
<option value=""><?php echo __('all'); ?></option>
|
||||
<option value="Scheduled" <?php echo $search_status === 'Scheduled' ? 'selected' : ''; ?>>Scheduled</option>
|
||||
<option value="Completed" <?php echo $search_status === 'Completed' ? 'selected' : ''; ?>>Completed</option>
|
||||
<option value="Cancelled" <?php echo $search_status === 'Cancelled' ? 'selected' : ''; ?>>Cancelled</option>
|
||||
<option value="Scheduled" <?php echo $search_status === 'Scheduled' ? 'selected' : ''; ?>><?php echo __('scheduled'); ?></option>
|
||||
<option value="Completed" <?php echo $search_status === 'Completed' ? 'selected' : ''; ?>><?php echo __('completed'); ?></option>
|
||||
<option value="Cancelled" <?php echo $search_status === 'Cancelled' ? 'selected' : ''; ?>><?php echo __('cancelled'); ?></option>
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
@ -74,7 +74,7 @@ $appointments = $stmt->fetchAll();
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<span class="badge <?php echo $app['status'] === 'Completed' ? 'bg-success' : ($app['status'] === 'Cancelled' ? 'bg-danger' : 'bg-primary'); ?>">
|
||||
<?php echo $app['status']; ?>
|
||||
<?php echo __(strtolower($app['status'])); ?>
|
||||
</span>
|
||||
<small class="text-muted fw-bold">
|
||||
<?php echo date('H:i', strtotime($app['start_time'])); ?>
|
||||
@ -88,7 +88,7 @@ $appointments = $stmt->fetchAll();
|
||||
|
||||
<div class="mb-3 p-2 bg-light rounded small">
|
||||
<i class="bi bi-geo-alt text-danger me-1"></i>
|
||||
<?php echo nl2br(htmlspecialchars($app['address'] ?? 'No address provided')); ?>
|
||||
<?php echo nl2br(htmlspecialchars($app['address'] ?? __('no_address_provided'))); ?>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
@ -104,7 +104,7 @@ $appointments = $stmt->fetchAll();
|
||||
} elseif ($app['nurse_id']) {
|
||||
echo htmlspecialchars($app['nurse_name']) . ' (' . __('nurse') . ')';
|
||||
} else {
|
||||
echo '<span class="text-danger">Unassigned</span>';
|
||||
echo '<span class="text-danger">' . __('unassigned') . '</span>';
|
||||
}
|
||||
?>
|
||||
</span>
|
||||
@ -113,7 +113,7 @@ $appointments = $stmt->fetchAll();
|
||||
|
||||
<?php if ($app['reason']): ?>
|
||||
<p class="small text-muted mb-0">
|
||||
<strong>Reason:</strong> <?php echo htmlspecialchars($app['reason']); ?>
|
||||
<strong><?php echo __('reason_label'); ?>:</strong> <?php echo htmlspecialchars($app['reason']); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@ -121,7 +121,7 @@ $appointments = $stmt->fetchAll();
|
||||
<!-- Actions -->
|
||||
<?php if ($app['status'] === 'Scheduled'): ?>
|
||||
<button class="btn btn-sm btn-outline-success" onclick="completeHomeVisit(<?php echo $app['id']; ?>, <?php echo $app['patient_id']; ?>, <?php echo $app['doctor_id'] ?: 'null'; ?>, <?php echo $app['nurse_id'] ?: 'null'; ?>)">
|
||||
<i class="bi bi-check2-circle"></i> Complete
|
||||
<i class="bi bi-check2-circle"></i> <?php echo __('complete'); ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@ -136,7 +136,7 @@ $appointments = $stmt->fetchAll();
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Complete Home Visit</h5>
|
||||
<h5 class="modal-title"><?php echo __('complete_home_visit'); ?></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@ -147,21 +147,21 @@ $appointments = $stmt->fetchAll();
|
||||
<input type="hidden" id="chv_nurse_id" name="nurse_id">
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Notes / Treatment</label>
|
||||
<label class="form-label"><?php echo __('notes_treatment'); ?></label>
|
||||
<textarea class="form-control" id="chv_treatment_plan" name="treatment_plan" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-check mb-3">
|
||||
<input class="form-check-input" type="checkbox" id="chv_create_bill" checked>
|
||||
<label class="form-check-label" for="chv_create_bill">
|
||||
Create Bill?
|
||||
<?php echo __('create_bill'); ?>?
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary" onclick="submitHomeVisitCompletion()">Save & Complete</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo __('close'); ?></button>
|
||||
<button type="button" class="btn btn-primary" onclick="submitHomeVisitCompletion()"><?php echo __('save_complete'); ?></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
94
includes/pages/profile.php
Normal file
94
includes/pages/profile.php
Normal file
@ -0,0 +1,94 @@
|
||||
<div class="container-fluid">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3 mb-0 text-gray-800"><?php echo __('user_profile'); ?></h1>
|
||||
</div>
|
||||
|
||||
<?php if (isset($errors) && !empty($errors)): ?>
|
||||
<div class="alert alert-danger">
|
||||
<ul>
|
||||
<?php foreach ($errors as $error): ?>
|
||||
<li><?php echo htmlspecialchars($error); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($success_msg)): ?>
|
||||
<div class="alert alert-success">
|
||||
<?php echo htmlspecialchars($success_msg); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header py-3">
|
||||
<h6 class="m-0 font-weight-bold text-primary"><?php echo __('profile_picture'); ?></h6>
|
||||
</div>
|
||||
<div class="card-body text-center">
|
||||
<img src="<?php echo !empty($user['avatar']) ? $user['avatar'] : 'assets/images/default-avatar.png'; ?>"
|
||||
class="img-profile rounded-circle mb-3"
|
||||
style="width: 150px; height: 150px; object-fit: cover;"
|
||||
alt="Profile Picture">
|
||||
<p class="text-muted mb-1"><?php echo htmlspecialchars($user['name']); ?></p>
|
||||
<p class="text-muted small"><?php echo htmlspecialchars($user['email']); ?></p>
|
||||
<p class="badge badge-primary"><?php echo htmlspecialchars($user['role_slug']); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header py-3">
|
||||
<h6 class="m-0 font-weight-bold text-primary"><?php echo __('edit_profile'); ?></h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label for="name"><?php echo __('name'); ?></label>
|
||||
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($user['name']); ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="email"><?php echo __('email'); ?></label>
|
||||
<input type="email" class="form-control" id="email" name="email" value="<?php echo htmlspecialchars($user['email']); ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="avatar"><?php echo __('change_avatar'); ?></label>
|
||||
<div class="custom-file">
|
||||
<input type="file" class="custom-file-input" id="avatar" name="avatar" accept="image/*">
|
||||
<label class="custom-file-label" for="avatar"><?php echo __('choose_file'); ?></label>
|
||||
</div>
|
||||
<small class="form-text text-muted"><?php echo __('allowed_file_types'); ?>: jpg, jpeg, png, gif</small>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<h6 class="mb-3 font-weight-bold text-gray-800"><?php echo __('change_password'); ?> <small class="text-muted font-weight-normal">(<?php echo __('leave_blank_to_keep_current'); ?>)</small></h6>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="password"><?php echo __('new_password'); ?></label>
|
||||
<input type="password" class="form-control" id="password" name="password" minlength="6">
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="password_confirm"><?php echo __('confirm_password'); ?></label>
|
||||
<input type="password" class="form-control" id="password_confirm" name="password_confirm" minlength="6">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary btn-block"><?php echo __('save_changes'); ?></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Show file name in custom file input
|
||||
$(".custom-file-input").on("change", function() {
|
||||
var fileName = $(this).val().split("\\").pop();
|
||||
$(this).next(".custom-file-label").addClass("selected").html(fileName);
|
||||
});
|
||||
</script>
|
||||
@ -118,7 +118,11 @@ $available_permissions = [
|
||||
</td>
|
||||
<td>
|
||||
<?php if ($role['slug'] !== 'admin'): ?>
|
||||
<button class="btn btn-sm btn-outline-primary" onclick='editPermissions(<?php echo json_encode($role); ?>)'>
|
||||
<button class="btn btn-sm btn-outline-primary"
|
||||
data-id="<?php echo $role['id']; ?>"
|
||||
data-name="<?php echo htmlspecialchars($role['name']); ?>"
|
||||
data-permissions='<?php echo htmlspecialchars($role['permissions'], ENT_QUOTES, 'UTF-8'); ?>'
|
||||
onclick="editPermissions(this)">
|
||||
<i class="bi bi-shield-lock"></i> <?php echo __('permissions'); ?>
|
||||
</button>
|
||||
<?php else: ?>
|
||||
@ -218,9 +222,9 @@ $available_permissions = [
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function editPermissions(role) {
|
||||
document.getElementById('permRoleId').value = role.id;
|
||||
document.getElementById('permRoleName').innerText = role.name;
|
||||
function editPermissions(btn) {
|
||||
document.getElementById('permRoleId').value = btn.dataset.id;
|
||||
document.getElementById('permRoleName').innerText = btn.dataset.name;
|
||||
|
||||
// Reset all checkboxes
|
||||
document.querySelectorAll('.perm-check').forEach(c => c.checked = false);
|
||||
@ -228,7 +232,7 @@ function editPermissions(role) {
|
||||
// Check active permissions
|
||||
let perms = [];
|
||||
try {
|
||||
perms = JSON.parse(role.permissions);
|
||||
perms = JSON.parse(btn.dataset.permissions);
|
||||
} catch(e) {
|
||||
perms = [];
|
||||
}
|
||||
|
||||
@ -102,7 +102,13 @@ $roles = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
</td>
|
||||
<td><?php echo date('Y-m-d', strtotime($user['created_at'])); ?></td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-outline-primary me-1" onclick="editUser(<?php echo htmlspecialchars(json_encode($user)); ?>)">
|
||||
<button class="btn btn-sm btn-outline-primary me-1"
|
||||
data-id="<?php echo $user['id']; ?>"
|
||||
data-name="<?php echo htmlspecialchars($user['name']); ?>"
|
||||
data-email="<?php echo htmlspecialchars($user['email']); ?>"
|
||||
data-role="<?php echo $user['role_id']; ?>"
|
||||
data-active="<?php echo $user['active']; ?>"
|
||||
onclick="editUser(this)">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<?php if ($user['id'] != $_SESSION['user_id']): ?>
|
||||
@ -229,12 +235,12 @@ $roles = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function editUser(user) {
|
||||
document.getElementById('editUserId').value = user.id;
|
||||
document.getElementById('editUserName').value = user.name;
|
||||
document.getElementById('editUserEmail').value = user.email;
|
||||
document.getElementById('editUserRole').value = user.role_id;
|
||||
document.getElementById('editUserActive').checked = user.active == 1;
|
||||
function editUser(btn) {
|
||||
document.getElementById('editUserId').value = btn.dataset.id;
|
||||
document.getElementById('editUserName').value = btn.dataset.name;
|
||||
document.getElementById('editUserEmail').value = btn.dataset.email;
|
||||
document.getElementById('editUserRole').value = btn.dataset.role;
|
||||
document.getElementById('editUserActive').checked = btn.dataset.active == 1;
|
||||
|
||||
new bootstrap.Modal(document.getElementById('editUserModal')).show();
|
||||
}
|
||||
|
||||
174
lang.php
174
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' => 'خطأ في تحديث الملف الشخصي',
|
||||
]
|
||||
];
|
||||
99
profile.php
Normal file
99
profile.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
require_once 'includes/auth.php';
|
||||
require_once 'helpers.php';
|
||||
|
||||
check_auth();
|
||||
|
||||
$user = current_user();
|
||||
$page_title = __('user_profile');
|
||||
|
||||
// Handle form submission
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$name = $_POST['name'] ?? '';
|
||||
$email = $_POST['email'] ?? '';
|
||||
$password = $_POST['password'] ?? '';
|
||||
$password_confirm = $_POST['password_confirm'] ?? '';
|
||||
|
||||
$errors = [];
|
||||
|
||||
if (empty($name)) {
|
||||
$errors[] = __('name_required');
|
||||
}
|
||||
|
||||
if (empty($email)) {
|
||||
$errors[] = __('email_required');
|
||||
}
|
||||
|
||||
// Check if email is taken by another user
|
||||
$stmt = $db->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';
|
||||
@ -1,5 +0,0 @@
|
||||
<?php
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
$_GET['start'] = '2026-03-15';
|
||||
$_GET['end'] = '2026-03-22';
|
||||
require_once 'api/appointments.php';
|
||||
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
$data = [
|
||||
'action' => '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);
|
||||
Loading…
x
Reference in New Issue
Block a user