2024-09-07 22:36:57 +00:00
<!-- user profile -->
2025-11-19 20:28:15 +00:00
< div class = " tm-profile-card mx-auto " >
< div class = " tm-profile-header " >
< div >
< p class = " tm-profile-eyebrow " > Account </ p >
< h2 class = " tm-profile-title " > Profile of < ? = htmlspecialchars ( $userDetails [ 0 ][ 'username' ]) ?> </h2>
< p class = " tm-profile-subtitle " > Update your personal details , avatar , and access rights in one streamlined view .</ p >
</ div >
</ div >
2024-09-07 22:36:57 +00:00
2025-11-19 20:28:15 +00:00
< form method = " POST " action = " <?= htmlspecialchars( $app_root ) ?>?page=profile " enctype = " multipart/form-data " class = " tm-profile-form " novalidate >
2025-04-16 10:11:51 +00:00
< ? php include CSRF_TOKEN_INCLUDE ; ?>
2025-11-19 20:28:15 +00:00
< div class = " row g-4 align-items-start " >
< div class = " col-lg-4 " >
< div class = " tm-profile-avatar card h-100 " >
2024-09-10 11:05:38 +00:00
< div class = " avatar-wrapper " >
2024-10-04 11:18:28 +00:00
< img class = " avatar-img " src = " <?= htmlspecialchars( $app_root ) . htmlspecialchars( $avatar ) ?> " alt = " avatar " />
2025-11-19 20:28:15 +00:00
</ div >
< div class = " avatar-btn-group " >
< label for = " avatar-upload " class = " btn btn-outline-primary w-100 " >
< i class = " fas fa-upload me-2 " ></ i > Upload new
2024-09-10 11:05:38 +00:00
</ label >
2024-09-09 12:20:21 +00:00
< input type = " file " id = " avatar-upload " name = " avatar_file " accept = " image/* " style = " display:none; " >
2024-09-09 12:54:32 +00:00
< ? php if ( $default_avatar ) { ?>
2025-11-19 20:28:15 +00:00
< button type = " button " class = " btn btn-outline-secondary w-100 " data - toggle = " modal " data - target = " #confirmDeleteModal " disabled >
2024-09-09 12:54:32 +00:00
< ? php } else { ?>
2025-11-19 20:28:15 +00:00
< button type = " button " class = " btn btn-outline-danger w-100 " data - toggle = " modal " data - target = " #confirmDeleteModal " >
2024-09-09 12:54:32 +00:00
< ? php } ?>
2025-11-19 20:28:15 +00:00
< i class = " fas fa-trash me-2 " ></ i > Remove avatar
2024-09-09 12:54:32 +00:00
</ button >
</ div >
2025-11-19 20:28:15 +00:00
< p class = " avatar-hint " > PNG , JPG up to 500 KB .</ p >
2024-09-07 22:36:57 +00:00
</ div >
2025-11-19 20:28:15 +00:00
</ div >
2024-09-07 22:36:57 +00:00
2025-11-19 20:28:15 +00:00
< div class = " col-lg-8 " >
< div class = " tm-profile-section " >
< h3 class = " tm-profile-section-title " > Personal info </ h3 >
< div class = " row g-3 " >
< div class = " col-md-6 " >
< label for = " name " class = " form-label " > Full name </ label >
< input class = " form-control " type = " text " name = " name " id = " name " value = " <?= htmlspecialchars( $userDetails[0] ['name'] ?? '') ?> " autofocus />
2024-09-08 10:48:21 +00:00
</ div >
2025-11-19 20:28:15 +00:00
< div class = " col-md-6 " >
< label for = " email " class = " form-label " > Email address </ label >
< input class = " form-control " type = " text " name = " email " id = " email " value = " <?= htmlspecialchars( $userDetails[0] ['email'] ?? '') ?> " />
2024-09-08 10:48:21 +00:00
</ div >
2024-09-07 22:36:57 +00:00
</ div >
2025-11-19 20:28:15 +00:00
</ div >
2024-09-08 10:48:21 +00:00
2025-11-19 20:28:15 +00:00
< div class = " tm-profile-section " >
< h3 class = " tm-profile-section-title " > Timezone </ h3 >
< label for = " timezone " class = " form-label " > Preferred timezone </ label >
< select class = " form-control " name = " timezone " id = " timezone " >
2024-09-13 10:04:15 +00:00
< ? php foreach ( $allTimezones as $timezone ) { ?>
2025-11-19 20:28:15 +00:00
< option value = " <?= htmlspecialchars( $timezone ) ?> " < ? = $timezone === $userTimezone ? 'selected' : '' ?> >
< ? = htmlspecialchars ( $timezone ) ?> (<?= htmlspecialchars(getUTCOffset($timezone)) ?>)
</ option >
2024-09-13 10:04:15 +00:00
< ? php } ?>
2025-11-19 20:28:15 +00:00
</ select >
</ div >
2024-09-13 10:04:15 +00:00
2025-11-19 20:28:15 +00:00
< div class = " tm-profile-section " >
< h3 class = " tm-profile-section-title " > Bio </ h3 >
< textarea class = " form-control " name = " bio " rows = " 6 " placeholder = " Share something about yourself, your role, or preferences. " >< ? = htmlspecialchars ( $userDetails [ 0 ][ 'bio' ] ? ? '' ) ?> </textarea>
</ div >
2024-09-07 22:36:57 +00:00
2025-11-19 20:28:15 +00:00
< div class = " tm-profile-section " >
< h3 class = " tm-profile-section-title " > Rights </ h3 >
< p class = " tm-profile-section-helper " > Toggle the permissions that should be associated with this user .</ p >
< div class = " tm-rights-grid " >
2024-09-11 19:51:46 +00:00
< ? php foreach ( $allRights as $right ) {
$isChecked = false ;
foreach ( $userRights as $userRight ) {
if ( $userRight [ 'right_id' ] === $right [ 'right_id' ]) {
$isChecked = true ;
break ;
}
} ?>
2025-11-19 20:28:15 +00:00
< div class = " form-check tm-right-item " >
< input class = " form-check-input " type = " checkbox " name = " rights[] " value = " <?= htmlspecialchars( $right['right_id'] ) ?> " id = " right_<?= htmlspecialchars( $right['right_id'] ) ?> " < ? = $isChecked ? 'checked' : '' ?> />
< label class = " form-check-label " for = " right_<?= htmlspecialchars( $right['right_id'] ) ?> " >< ? = htmlspecialchars ( $right [ 'right_name' ]) ?> </label>
2024-09-08 10:48:21 +00:00
</ div >
2025-11-19 20:28:15 +00:00
< ? php } ?>
2024-09-08 10:48:21 +00:00
</ div >
</ div >
2024-09-07 22:36:57 +00:00
2025-11-19 20:28:15 +00:00
< div class = " tm-profile-actions " >
< a href = " <?= htmlspecialchars( $app_root ) ?>?page=profile " class = " btn btn-light tm-contact-back " > Cancel </ a >
< button type = " submit " class = " btn btn-primary tm-contact-submit " > Save changes </ button >
</ div >
2024-09-08 10:48:21 +00:00
</ div >
2025-11-19 20:28:15 +00:00
</ div >
</ form >
<!-- avatar removal modal confirmation -->
< div class = " modal fade " id = " confirmDeleteModal " tabindex = " -1 " aria - labelledby = " confirmDeleteModalLabel " aria - hidden = " true " >
< div class = " modal-dialog " >
< div class = " modal-content " >
< div class = " modal-header " >
< h5 class = " modal-title " id = " confirmDeleteModalLabel " > Confirm Avatar Deletion </ h5 >
< button type = " button " class = " btn-close " data - dismiss = " modal " aria - label = " Close " ></ button >
</ div >
< div class = " modal-body text-center " >
< img class = " avatar-img " src = " <?= htmlspecialchars( $app_root ) . htmlspecialchars( $avatar ) ?> " alt = " avatar " />
< p class = " mt-3 mb-0 " > Are you sure you want to delete your avatar ? < br /> This action cannot be undone .</ p >
</ div >
< div class = " modal-footer " >
< button type = " button " class = " btn btn-secondary " data - dismiss = " modal " > Cancel </ button >
< form id = " remove-avatar-form " data - action = " remove-avatar " method = " POST " action = " <?= htmlspecialchars( $app_root ) ?>?page=profile&action=remove&item=avatar " >
2025-04-16 10:11:51 +00:00
< ? php include CSRF_TOKEN_INCLUDE ; ?>
2025-11-19 20:28:15 +00:00
< button type = " button " class = " btn btn-danger " id = " confirm-delete " > Delete Avatar </ button >
</ form >
</ div >
</ div >
</ div >
2024-09-07 22:36:57 +00:00
</ div >
2025-11-19 20:28:15 +00:00
2024-09-07 22:36:57 +00:00
</ div >
<!-- / user profile -->
2024-09-09 12:20:21 +00:00
< script >
2024-09-10 11:05:38 +00:00
// Preview the uploaded avatar
2024-09-09 12:20:21 +00:00
document . getElementById ( 'avatar-upload' ) . addEventListener ( 'change' , function ( event ) {
const reader = new FileReader ();
reader . onload = function () {
document . querySelector ( '.avatar-img' ) . src = reader . result ;
};
reader . readAsDataURL ( event . target . files [ 0 ]);
});
2024-09-09 12:54:32 +00:00
2024-09-10 11:05:38 +00:00
// Avatar file size and type control
2024-09-09 12:54:32 +00:00
document . getElementById ( 'avatar-upload' ) . addEventListener ( 'change' , function () {
2024-09-10 11:05:38 +00:00
const maxFileSize = 500 * 1024 ; // 500 KB in bytes
2024-10-04 11:18:28 +00:00
const currentAvatar = '<?= htmlspecialchars($app_root) . htmlspecialchars($avatar) ?>' ; // current avatar
2024-09-09 13:35:06 +00:00
const file = this . files [ 0 ];
if ( file ) {
// Check file size
if ( file . size > maxFileSize ) {
alert ( 'File size exceeds 500 KB. Please select a smaller file.' );
this . value = '' ; // Clear the file input
document . querySelector ( '.avatar-img' ) . src = currentAvatar ;
}
2024-09-09 12:54:32 +00:00
}
});
2024-09-10 11:05:38 +00:00
// Submitting the avatar deletion confirmation modal form
document . getElementById ( 'confirm-delete' ) . addEventListener ( 'click' , function ( event ) {
event . preventDefault (); // Prevent the outer form from submitting
2024-09-09 12:54:32 +00:00
document . getElementById ( 'remove-avatar-form' ) . submit ();
});
2024-09-10 11:05:38 +00:00
2024-09-13 10:04:15 +00:00
// Function to detect user's timezone and select it in the dropdown
function setTimezone () {
const userTimezone = Intl . DateTimeFormat () . resolvedOptions () . timeZone ;
const timezoneSelect = document . getElementById ( " timezone " );
timezoneSelect . className = 'form-control border border-danger' ;
// Loop through the options to find and select the user's timezone
for ( let i = 0 ; i < timezoneSelect . options . length ; i ++ ) {
if ( timezoneSelect . options [ i ] . value === userTimezone ) {
timezoneSelect . selectedIndex = i ;
break ;
}
}
}
// Run the function on page load
window . onload = function () {
const isTimezoneSet = < ? php echo json_encode ( $isTimezoneSet ); ?> ; // Pass PHP flag to JavaScript
// If timezone is not set, run setTimezone()
if ( ! isTimezoneSet ) {
setTimezone ();
}
};
2024-09-09 12:20:21 +00:00
</ script >