devsofttech_hms_ci4/app/Views/account/my_profile.php
DevSoftTech Server 5717763496 Add user-based sidebar auto-hide setting, movable from hospital default
- Create user_settings table to store individual user preferences
- UserSettings model for get/set/delete user setting values
- Home::myProfile loads user settings with hospital defaults fallback
- Home::myProfileSave persists user settings to DB
- my_profile.php adds Sidebar Auto-Hide Delay field (0-60 seconds)
- welcome_message.php checks user settings first, then hospital default
- Setting value 0 = auto-hide disabled; blank = use hospital default
- Extensible table design for future user settings (color theme, etc)
2026-04-28 13:47:46 +05:30

217 lines
10 KiB
PHP

<section class="section">
<div class="row g-3">
<div class="col-lg-7 col-md-9">
<div class="card">
<div class="card-header"><strong>My Profile</strong></div>
<div class="card-body">
<?= csrf_field() ?>
<?php
$loginId = trim((string) ($user->username ?? ''));
if ($loginId === '') {
$loginId = trim((string) ($user->email ?? 'User'));
}
$personName = trim((string) ($person_name ?? ''));
?>
<div class="mb-2">
<label class="form-label">Login ID</label>
<input type="text" class="form-control form-control-sm" value="<?= esc($loginId) ?>" readonly>
</div>
<div class="mb-2">
<label class="form-label">Person Name</label>
<input type="text" class="form-control form-control-sm" id="profile_person_name" maxlength="120" value="<?= esc($personName) ?>" placeholder="Enter person name">
</div>
<div class="mb-2">
<label class="form-label">User ID</label>
<input type="text" class="form-control form-control-sm" value="<?= esc((string) ($user->id ?? '')) ?>" readonly>
</div>
<div class="mb-2">
<label class="form-label">Email</label>
<input type="email" class="form-control form-control-sm" id="profile_email" maxlength="254" value="<?= esc((string) ($user->email ?? '')) ?>" placeholder="Enter email">
</div>
<div class="mb-3">
<label class="form-label">Phone No.</label>
<input type="text" class="form-control form-control-sm" id="profile_phone_no" maxlength="20" value="<?= esc((string) ($phone_no ?? '')) ?>" placeholder="Enter phone number">
</div>
<div class="border rounded p-2 mb-3">
<div class="small fw-semibold mb-2">Profile Photo</div>
<div class="d-flex align-items-center gap-3 flex-wrap">
<img id="profile_photo_preview"
src="<?= esc((string) ($profile_photo_url ?? base_url('assets/img/profile-img.jpg'))) ?>"
alt="Profile Photo"
class="rounded-circle border"
style="width:72px;height:72px;object-fit:cover;">
<div>
<input type="file" class="form-control form-control-sm" id="profile_photo" accept="image/jpeg,image/png,image/webp">
<div class="small text-muted mt-1">Allowed: JPG, PNG, WEBP. Max size: 2MB.</div>
</div>
</div>
</div>
<div class="border rounded p-2 mb-3 bg-light">
<div class="small fw-semibold mb-2">Change Password (Optional)</div>
<div class="mb-2">
<label class="form-label">New Password</label>
<input type="password" class="form-control form-control-sm" id="profile_password" autocomplete="new-password" placeholder="Minimum 8 characters">
</div>
<div>
<label class="form-label">Confirm Password</label>
<input type="password" class="form-control form-control-sm" id="profile_password_confirm" autocomplete="new-password" placeholder="Re-enter new password">
</div>
</div>
<div class="d-flex gap-2">
<button type="button" class="btn btn-primary btn-sm" id="btn_profile_save">Save Profile</button>
<button type="button" class="btn btn-outline-secondary btn-sm" id="btn_profile_reset_pwd">Clear Password</button>
</div>
<div class="small text-muted mt-2" id="profile_msg">Update your email, phone, and password here.</div>
</div>
</div>
<div class="card mt-3">
<div class="card-header"><strong>User Settings</strong></div>
<div class="card-body">
<div class="mb-3">
<label class="form-label">Sidebar Auto-Hide Delay (Seconds)</label>
<div class="input-group input-group-sm">
<input type="number" class="form-control" id="sidebar_auto_hide_seconds" min="0" max="60" step="1" value="<?= esc((string) ($sidebar_auto_hide_seconds ?? '7')) ?>" placeholder="0-60">
<span class="input-group-text"><small class="text-muted">Hospital default: <?= esc((string) hospital_setting_value('SIDEBAR_AUTO_HIDE_SECONDS', '7')) ?>s</small></span>
</div>
<div class="small text-muted mt-1">How many seconds before sidebar auto-hides. Enter 0 to disable auto-hide. Leave blank to use hospital default.</div>
</div>
<div class="small text-success" id="settings_msg" style="display:none;">Settings auto-saved.</div>
</div>
</div>
</div>
</div>
</section>
<script>
(function() {
function getCsrfPair() {
var input = document.querySelector('input[name="<?= csrf_token() ?>"]');
if (!input) {
return { name: '<?= csrf_token() ?>', value: '<?= csrf_hash() ?>' };
}
return { name: input.getAttribute('name'), value: input.value };
}
function updateCsrf(data) {
if (!data || !data.csrfName || !data.csrfHash) {
return;
}
var input = document.querySelector('input[name="' + data.csrfName + '"]');
if (input) {
input.value = data.csrfHash;
}
}
function setMsg(type, text) {
var $msg = $('#profile_msg');
$msg.removeClass('text-success text-danger text-muted');
if (type === 'ok') {
$msg.addClass('text-success');
} else if (type === 'err') {
$msg.addClass('text-danger');
} else {
$msg.addClass('text-muted');
}
$msg.text(text || '');
}
$('#btn_profile_reset_pwd').on('click', function() {
$('#profile_password,#profile_password_confirm').val('');
setMsg('normal', 'Password fields cleared.');
});
$('#profile_photo').on('change', function() {
var file = this.files && this.files[0] ? this.files[0] : null;
if (!file) {
return;
}
var allowed = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp'];
if (allowed.indexOf((file.type || '').toLowerCase()) < 0) {
$(this).val('');
setMsg('err', 'Profile photo must be JPG, PNG, or WEBP.');
return;
}
if ((file.size || 0) > 2 * 1024 * 1024) {
$(this).val('');
setMsg('err', 'Profile photo must be less than 2MB.');
return;
}
var blobUrl = URL.createObjectURL(file);
$('#profile_photo_preview').attr('src', blobUrl);
setMsg('normal', 'Photo selected. Click Save Profile to upload.');
});
$('#btn_profile_save').on('click', function() {
var payload = new window.FormData();
payload.append('person_name', ($('#profile_person_name').val() || '').trim());
payload.append('email', ($('#profile_email').val() || '').trim());
payload.append('phone_no', ($('#profile_phone_no').val() || '').trim());
payload.append('password', ($('#profile_password').val() || '').toString());
payload.append('password_confirm', ($('#profile_password_confirm').val() || '').toString());
payload.append('sidebar_auto_hide_seconds', ($('#sidebar_auto_hide_seconds').val() || '').trim());
var photoInput = document.getElementById('profile_photo');
if (photoInput && photoInput.files && photoInput.files[0]) {
payload.append('profile_photo', photoInput.files[0]);
}
var csrf = getCsrfPair();
payload.append(csrf.name, csrf.value);
var $btn = $(this);
$btn.prop('disabled', true).text('Saving...');
$.ajax({
url: '<?= base_url('my-profile/save') ?>',
method: 'POST',
data: payload,
processData: false,
contentType: false,
dataType: 'json'
}).done(function(data) {
updateCsrf(data);
$btn.prop('disabled', false).text('Save Profile');
if (parseInt(data.update || '0', 10) !== 1) {
setMsg('err', data.error_text || 'Unable to update profile');
return;
}
$('#profile_password,#profile_password_confirm').val('');
setMsg('ok', data.error_text || 'Profile updated successfully');
var displayName = (data.display_name || '').toString();
var loginId = (data.login_id || '').toString();
var userId = parseInt(data.user_id || '0', 10);
if (displayName) {
$('#header-user-title').text(displayName);
if (userId > 0) {
$('#header-user-with-id').text(displayName);
$('#header-user-id').text('User ID: ' + userId);
}
}
if (loginId) {
$('#header-user-login-id').text('Login ID: ' + loginId);
}
if (data.profile_photo_url) {
$('#profile_photo_preview').attr('src', data.profile_photo_url);
$('#header-user-avatar').attr('src', data.profile_photo_url);
$('#profile_photo').val('');
}
}).fail(function() {
$btn.prop('disabled', false).text('Save Profile');
setMsg('err', 'Unable to update profile');
});
});
})();
</script>