| Current Path : /home/users/unlimited/www/nigeria.codeskitter.site/student/ |
| Current File : /home/users/unlimited/www/nigeria.codeskitter.site/student/profile.php |
<?php
include '../includes/config.php';
if(!isset($_SESSION['user_id']) || $_SESSION['user_role'] != 'student') {
header("Location: ../login.php");
exit();
}
$user_id = $_SESSION['user_id'];
$success_message = '';
$error_message = '';
// Get current user data
$user_sql = "SELECT * FROM users WHERE id = ?";
$stmt = $conn->prepare($user_sql);
$stmt->bind_param("i", $user_id);
$stmt->execute();
$user = $stmt->get_result()->fetch_assoc();
// Handle form submission
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$name = trim($_POST['name']);
$email = trim($_POST['email']);
$phone = trim($_POST['phone']);
$institution = trim($_POST['institution']);
$current_course = trim($_POST['current_course']);
$location = trim($_POST['location']);
$bio = trim($_POST['bio']);
$date_of_birth = $_POST['date_of_birth'];
$gender = $_POST['gender'];
// Handle profile picture upload
$profile_picture = $user['profile_picture']; // Keep existing if no new upload
if(isset($_FILES['profile_picture']) && $_FILES['profile_picture']['error'] == 0) {
$upload_dir = '../assets/images/profiles/';
// Create directory if it doesn't exist
if (!file_exists($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
$file_name = $_FILES['profile_picture']['name'];
$file_tmp = $_FILES['profile_picture']['tmp_name'];
$file_size = $_FILES['profile_picture']['size'];
$file_type = $_FILES['profile_picture']['type'];
// Get file extension
$file_ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
// Allowed file types
$allowed_extensions = array('jpg', 'jpeg', 'png', 'gif', 'webp');
if (in_array($file_ext, $allowed_extensions)) {
// Validate file size (2MB max)
if ($file_size <= 2097152) {
// Generate unique filename
$new_file_name = 'profile_' . $user_id . '_' . time() . '.' . $file_ext;
$file_path = $upload_dir . $new_file_name;
// Move uploaded file
if (move_uploaded_file($file_tmp, $file_path)) {
// Delete old profile picture if exists
if (!empty($user['profile_picture']) && file_exists('../' . $user['profile_picture'])) {
unlink('../' . $user['profile_picture']);
}
$profile_picture = 'assets/images/profiles/' . $new_file_name;
} else {
$error_message = "Error uploading profile picture.";
}
} else {
$error_message = "Profile picture size must be less than 2MB.";
}
} else {
$error_message = "Invalid file type. Allowed: JPG, JPEG, PNG, GIF, WEBP";
}
}
// Update user data
$update_sql = "UPDATE users SET
name = ?, email = ?, phone = ?, institution = ?,
current_course = ?, location = ?, bio = ?,
profile_picture = ?, date_of_birth = ?, gender = ?
WHERE id = ?";
$stmt = $conn->prepare($update_sql);
$stmt->bind_param("ssssssssssi", $name, $email, $phone, $institution,
$current_course, $location, $bio, $profile_picture,
$date_of_birth, $gender, $user_id);
if($stmt->execute()) {
$_SESSION['user_name'] = $name; // Update session name
$success_message = "Profile updated successfully!";
// Refresh user data
$user_sql = "SELECT * FROM users WHERE id = ?";
$stmt = $conn->prepare($user_sql);
$stmt->bind_param("i", $user_id);
$stmt->execute();
$user = $stmt->get_result()->fetch_assoc();
} else {
$error_message = "Error updating profile: " . $conn->error;
}
}
// Calculate profile completion percentage
$completion_fields = [
'phone' => 15,
'institution' => 15,
'current_course' => 15,
'location' => 15,
'bio' => 15,
'profile_picture' => 15,
'date_of_birth' => 5,
'gender' => 5
];
$profile_completion = 0;
foreach($completion_fields as $field => $weight) {
if(!empty($user[$field])) {
$profile_completion += $weight;
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Profile - Student Dashboard</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css">
<link rel="stylesheet" href="../assets/css/style.css">
<style>
.profile-card {
border: none;
border-radius: 15px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
transition: transform 0.3s ease;
}
.profile-card:hover {
transform: translateY(-5px);
}
.profile-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 15px 15px 0 0;
padding: 2rem;
text-align: center;
}
.profile-picture {
width: 150px;
height: 150px;
border-radius: 50%;
object-fit: cover;
border: 5px solid white;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
margin: 0 auto 1rem;
display: block;
}
.profile-completion {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
color: white;
border-radius: 10px;
padding: 1rem;
margin-bottom: 1.5rem;
}
.completion-progress {
height: 10px;
background: rgba(255,255,255,0.3);
border-radius: 5px;
overflow: hidden;
}
.form-control:focus {
border-color: #667eea;
box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25);
}
.profile-section {
margin-bottom: 2rem;
padding: 1.5rem;
background: white;
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.section-title {
color: #2c3e50;
border-bottom: 2px solid #667eea;
padding-bottom: 0.5rem;
margin-bottom: 1.5rem;
font-weight: 600;
}
.btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
padding: 0.75rem 2rem;
font-weight: 600;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
.profile-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-top: 1.5rem;
}
.stat-card {
background: white;
padding: 1rem;
border-radius: 10px;
text-align: center;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
border-left: 4px solid #667eea;
}
.file-upload {
position: relative;
overflow: hidden;
display: inline-block;
}
.file-upload-btn {
background: #28a745;
color: white;
padding: 0.5rem 1rem;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease;
}
.file-upload-btn:hover {
background: #218838;
}
.file-upload input[type="file"] {
position: absolute;
left: 0;
top: 0;
opacity: 0;
cursor: pointer;
width: 100%;
height: 100%;
}
.missing-field {
background: #fff3cd;
border: 1px solid #ffeaa7;
border-radius: 5px;
padding: 0.5rem;
margin: 0.25rem 0;
font-size: 0.9rem;
}
</style>
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="../index.php">eLearning</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="dashboard.php">Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="my-courses.php">My Courses</a>
</li>
<li class="nav-item">
<a class="nav-link" href="progress.php">Progress</a>
</li>
<li class="nav-item">
<a class="nav-link" href="certificates.php">Certificates</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="profile.php">Profile</a>
</li>
</ul>
<ul class="navbar-nav">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown">
<i class="bi bi-person-circle"></i> <?php echo $_SESSION['user_name']; ?>
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="profile.php">Profile</a></li>
<li><a class="dropdown-item" href="settings.php">Settings</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item text-danger" href="../logout.php">Logout</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<div class="container-fluid py-4">
<div class="row">
<!-- Sidebar -->
<div class="col-lg-3 mb-4">
<div class="card profile-card">
<div class="card-body text-center">
<img src="<?php echo !empty($user['profile_picture']) ? '../' . $user['profile_picture'] : 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUwIiBoZWlnaHQ9IjE1MCIgdmlld0JveD0iMCAwIDE1MCAxNTAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxNTAiIGhlaWdodD0iMTUwIiBmaWxsPSIjN2Y4Y2E2Ii8+CjxwYXRoIGQ9Ik03NSA3N0M4Mi43MzE5IDc3IDg5IDcwLjczMTkgODkgNjNDODkgNTUuMjY4MSA4Mi43MzE5IDQ5IDc1IDQ5QzY3LjI2ODEgNDkgNjEgNTUuMjY4MSA2MSA2M0M2MSA3MC43MzE5IDY3LjI2ODEgNzcgNzUgNzdaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNNDggOTdDMzQgOTcgNDIgMTE1IDc1IDExNUMxMDggMTE1IDExNiA5NyAxMDIgOTdDOTYgOTcgOTAgMTAzIDc1IDEwM0M2MCAxMDMgNTQgOTcgNDggOTdaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K'; ?>"
alt="Profile Picture" class="profile-picture" id="profilePreview">
<h5><?php echo htmlspecialchars($user['name']); ?></h5>
<p class="text-muted">Student</p>
<div class="file-upload mb-3">
<label class="file-upload-btn">
<i class="bi bi-camera me-1"></i>Change Photo
<input type="file" name="profile_picture" id="profilePicture" accept="image/*">
</label>
</div>
<div class="profile-stats">
<div class="stat-card">
<h6 class="mb-1">Member Since</h6>
<small class="text-muted"><?php echo date('M Y', strtotime($user['created_at'])); ?></small>
</div>
<div class="stat-card">
<h6 class="mb-1">Last Updated</h6>
<small class="text-muted"><?php echo !empty($user['updated_at']) ? date('M j, Y', strtotime($user['updated_at'])) : 'Never'; ?></small>
</div>
</div>
</div>
</div>
<!-- Profile Completion -->
<div class="card profile-card mt-4">
<div class="card-body">
<h6 class="card-title">Profile Completion</h6>
<div class="completion-progress mb-2">
<div class="progress-bar bg-success" style="width: <?php echo $profile_completion; ?>%"></div>
</div>
<div class="d-flex justify-content-between align-items-center">
<small class="text-muted"><?php echo $profile_completion; ?>% Complete</small>
<small class="text-muted"><?php echo (100 - $profile_completion); ?>% to go</small>
</div>
<?php if($profile_completion < 100): ?>
<div class="mt-3">
<small class="text-muted d-block mb-2">Complete these fields:</small>
<?php if(empty($user['phone'])): ?>
<div class="missing-field">
<i class="bi bi-telephone me-2"></i>Phone Number
</div>
<?php endif; ?>
<?php if(empty($user['institution'])): ?>
<div class="missing-field">
<i class="bi bi-building me-2"></i>Institution
</div>
<?php endif; ?>
<?php if(empty($user['current_course'])): ?>
<div class="missing-field">
<i class="bi bi-book me-2"></i>Current Course
</div>
<?php endif; ?>
<?php if(empty($user['location'])): ?>
<div class="missing-field">
<i class="bi bi-geo-alt me-2"></i>Location
</div>
<?php endif; ?>
</div>
<?php else: ?>
<div class="text-center mt-3">
<i class="bi bi-check-circle-fill text-success fs-4"></i>
<p class="text-success mb-0 mt-2">Profile Complete!</p>
</div>
<?php endif; ?>
</div>
</div>
</div>
<!-- Main Content -->
<div class="col-lg-9">
<div class="card profile-card">
<div class="profile-header">
<h3><i class="bi bi-person-gear me-2"></i>My Profile</h3>
<p class="mb-0">Manage your personal information and preferences</p>
</div>
<div class="card-body">
<!-- Success/Error Messages -->
<?php if($success_message): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<i class="bi bi-check-circle me-2"></i><?php echo $success_message; ?>
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
<?php endif; ?>
<?php if($error_message): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<i class="bi bi-exclamation-triangle me-2"></i><?php echo $error_message; ?>
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
<?php endif; ?>
<form method="POST" enctype="multipart/form-data" id="profileForm">
<!-- Personal Information Section -->
<div class="profile-section">
<h4 class="section-title">
<i class="bi bi-person-vcard me-2"></i>Personal Information
</h4>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Full Name *</label>
<input type="text" class="form-control" name="name"
value="<?php echo htmlspecialchars($user['name']); ?>" required>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Email Address *</label>
<input type="email" class="form-control" name="email"
value="<?php echo htmlspecialchars($user['email']); ?>" required>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Phone Number</label>
<input type="tel" class="form-control" name="phone"
value="<?php echo htmlspecialchars($user['phone'] ?? ''); ?>"
placeholder="+254 712 345 678">
<small class="form-text text-muted">We'll never share your phone number.</small>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Date of Birth</label>
<input type="date" class="form-control" name="date_of_birth"
value="<?php echo $user['date_of_birth'] ?? ''; ?>">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Gender</label>
<select class="form-select" name="gender">
<option value="">Select Gender</option>
<option value="male" <?php echo ($user['gender'] ?? '') == 'male' ? 'selected' : ''; ?>>Male</option>
<option value="female" <?php echo ($user['gender'] ?? '') == 'female' ? 'selected' : ''; ?>>Female</option>
<option value="other" <?php echo ($user['gender'] ?? '') == 'other' ? 'selected' : ''; ?>>Other</option>
</select>
</div>
</div>
</div>
<!-- Education Information Section -->
<div class="profile-section">
<h4 class="section-title">
<i class="bi bi-mortarboard me-2"></i>Education Information
</h4>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Institution/University</label>
<input type="text" class="form-control" name="institution"
value="<?php echo htmlspecialchars($user['institution'] ?? ''); ?>"
placeholder="e.g., University of Nairobi">
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Current Course/Program</label>
<input type="text" class="form-control" name="current_course"
value="<?php echo htmlspecialchars($user['current_course'] ?? ''); ?>"
placeholder="e.g., Computer Science">
</div>
</div>
</div>
<!-- Location Information Section -->
<div class="profile-section">
<h4 class="section-title">
<i class="bi bi-geo-alt me-2"></i>Location Information
</h4>
<div class="row">
<div class="col-12 mb-3">
<label class="form-label">Location</label>
<input type="text" class="form-control" name="location"
value="<?php echo htmlspecialchars($user['location'] ?? ''); ?>"
placeholder="e.g., Nairobi, Kenya">
<small class="form-text text-muted">Your city and country</small>
</div>
</div>
</div>
<!-- Bio Section -->
<div class="profile-section">
<h4 class="section-title">
<i class="bi bi-file-text me-2"></i>About Me
</h4>
<div class="row">
<div class="col-12 mb-3">
<label class="form-label">Bio</label>
<textarea class="form-control" name="bio" rows="4"
placeholder="Tell us about yourself, your interests, and your goals..."><?php echo htmlspecialchars($user['bio'] ?? ''); ?></textarea>
<small class="form-text text-muted">Write a short description about yourself.</small>
</div>
</div>
</div>
<!-- Form Actions -->
<div class="row mt-4">
<div class="col-12">
<div class="d-flex justify-content-between">
<a href="dashboard.php" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left me-1"></i>Back to Dashboard
</a>
<button type="submit" class="btn btn-primary">
<i class="bi bi-check-circle me-1"></i>Update Profile
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Profile picture preview
const profilePictureInput = document.getElementById('profilePicture');
const profilePreview = document.getElementById('profilePreview');
profilePictureInput.addEventListener('change', function(e) {
const file = this.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
profilePreview.src = e.target.result;
};
reader.readAsDataURL(file);
}
});
// Form validation
const profileForm = document.getElementById('profileForm');
profileForm.addEventListener('submit', function(e) {
const email = document.querySelector('input[name="email"]').value;
const phone = document.querySelector('input[name="phone"]').value;
// Basic email validation
if (!isValidEmail(email)) {
e.preventDefault();
alert('Please enter a valid email address.');
return false;
}
// Phone validation (if provided)
if (phone && !isValidPhone(phone)) {
e.preventDefault();
alert('Please enter a valid phone number.');
return false;
}
});
function isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
function isValidPhone(phone) {
// Basic phone validation - adjust regex based on your needs
const phoneRegex = /^[\+]?[1-9][\d]{0,15}$/;
return phoneRegex.test(phone.replace(/\s/g, ''));
}
// Auto-save draft (optional feature)
let autoSaveTimeout;
const formInputs = profileForm.querySelectorAll('input, textarea, select');
formInputs.forEach(input => {
input.addEventListener('input', function() {
clearTimeout(autoSaveTimeout);
autoSaveTimeout = setTimeout(() => {
// You could implement auto-save functionality here
console.log('Form changed - ready for auto-save');
}, 2000);
});
});
// Show character count for bio
const bioTextarea = document.querySelector('textarea[name="bio"]');
if (bioTextarea) {
const charCount = document.createElement('small');
charCount.className = 'form-text text-muted text-end d-block';
charCount.textContent = `Characters: ${bioTextarea.value.length}/500`;
bioTextarea.parentNode.appendChild(charCount);
bioTextarea.addEventListener('input', function() {
charCount.textContent = `Characters: ${this.value.length}/500`;
if (this.value.length > 500) {
charCount.classList.add('text-danger');
} else {
charCount.classList.remove('text-danger');
}
});
}
// Add loading state to submit button
profileForm.addEventListener('submit', function() {
const submitBtn = this.querySelector('button[type="submit"]');
const originalText = submitBtn.innerHTML;
submitBtn.innerHTML = '<i class="bi bi-arrow-repeat spinner-border spinner-border-sm me-1"></i> Updating...';
submitBtn.disabled = true;
// Re-enable button after 5 seconds (in case of error)
setTimeout(() => {
submitBtn.innerHTML = originalText;
submitBtn.disabled = false;
}, 5000);
});
});
</script>
</body>
</html>