# User Profile for Hospital Management App
## Controller
```php
// app/Http/Controllers/ProfileController.php
namespace App\Http\Controllers;
use App\Models\User;
use App\Models\Doctor;
use App\Models\Patient;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
class ProfileController extends Controller
/**
* Display the user's profile.
* @return \Illuminate\View\View
*/
public function show()
{
$user = Auth::user();
// Get role-specific data
if ($user->role === 'doctor') {
$roleData = Doctor::with('department')->where('user_id', $user->id)->first();
} elseif ($user->role === 'patient') {
$roleData = Patient::where('user_id', $user->id)->first();
} else {
$roleData = null;
return view('profile.show', compact('user', 'roleData'));
/**
* Show the form for editing the user's profile.
* @return \Illuminate\View\View
*/
public function edit()
$user = Auth::user();
// Get role-specific data
if ($user->role === 'doctor') {
$roleData = Doctor::where('user_id', $user->id)->first();
} elseif ($user->role === 'patient') {
$roleData = Patient::where('user_id', $user->id)->first();
} else {
$roleData = null;
return view('profile.edit', compact('user', 'roleData'));
/**
* Update the user's profile.
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function update(Request $request)
$user = Auth::user();
// Validate common fields
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users,email,'.$user->id,
'current_password' => 'nullable|required_with:password',
'password' => 'nullable|string|min:8|confirmed',
'profile_photo' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
]);
// Update password if provided
if ($request->filled('password')) {
if (!Hash::check($request->current_password, $user->password)) {
return back()->withErrors(['current_password' => 'The current password is incorrect.']);
$user->password = Hash::make($request->password);
// Update profile photo if provided
if ($request->hasFile('profile_photo')) {
// Delete old photo if exists
if ($user->role === 'doctor' && $user->doctor && $user->doctor->profile_photo) {
Storage::delete('public/profile_photos/' . $user->doctor->profile_photo);
// Store new photo
$fileName = time() . '_' . $request->file('profile_photo')->getClientOriginalName();
$request->file('profile_photo')->storeAs('public/profile_photos', $fileName);
// Update profile photo in the respective model
if ($user->role === 'doctor') {
$user->doctor->update(['profile_photo' => $fileName]);
// Update basic user information
$user->name = $request->name;
$user->email = $request->email;
$user->save();
// Update role-specific data
if ($user->role === 'doctor') {
$user->doctor->update([
'phone_number' => $request->phone_number,
'address' => $request->address,
'bio' => $request->bio,
]);
} elseif ($user->role === 'patient') {
$user->patient->update([
'phone_number' => $request->phone_number,
'address' => $request->address,
'blood_group' => $request->blood_group,
'allergies' => $request->allergies,
]);
}
return redirect()->route('profile.show')
->with('success', 'Profile updated successfully.');
```
## Routes
```php
// routes/web.php
// Add these routes to your existing routes within the auth middleware group
Route::middleware(['auth'])->group(function () {
// ... existing routes
// Profile Routes
Route::get('/profile', [ProfileController::class, 'show'])->name('profile.show');
Route::get('/profile/edit', [ProfileController::class, 'edit'])->name('profile.edit');
Route::put('/profile', [ProfileController::class, 'update'])->name('profile.update');
});
```
## Blade Views - Profile Show
```php
{{-- resources/views/profile/show.blade.php --}}
@extends('layouts.app')
@section('title', 'My Profile')
@section('page-title', 'My Profile')
@section('content')
<div class="container-fluid">
<div class="row">
<div class="col-md-4 mb-4">
<div class="card shadow">
<div class="card-body text-center">
@if($user->role === 'doctor' && $roleData && $roleData->profile_photo)
<img src="{{ asset('storage/profile_photos/' . $roleData->profile_photo) }}"
alt="Profile Photo"
class="rounded-circle img-fluid mb-3"
style="width: 150px; height: 150px; object-fit: cover;">
@else
<div class="rounded-circle bg-primary text-white d-flex align-items-center justify-content-
center mx-auto mb-3"
style="width: 150px; height: 150px; font-size: 3rem;">
{{ strtoupper(substr($user->name, 0, 1)) }}
</div>
@endif
<h3 class="fw-bold">{{ $user->name }}</h3>
<p class="text-muted">{{ ucfirst($user->role) }}</p>
@if($user->role === 'doctor' && $roleData)
<p class="mb-1"><span class="fw-bold">Specialization:</span> {{ $roleData->specialization
}}</p>
<p class="mb-1"><span class="fw-bold">Department:</span> {{ $roleData->department-
>name }}</p>
@endif
<div class="mt-3">
<a href="{{ route('profile.edit') }}" class="btn btn-primary">
<i class="bi bi-pencil-square me-1"></i> Edit Profile
</a>
</div>
</div>
</div>
</div>
<div class="col-md-8">
<div class="card shadow mb-4">
<div class="card-header bg-white">
<h5 class="card-title mb-0">Personal Information</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6 mb-3">
<h6 class="text-muted">Full Name</h6>
<p class="fw-bold">{{ $user->name }}</p>
</div>
<div class="col-md-6 mb-3">
<h6 class="text-muted">Email</h6>
<p class="fw-bold">{{ $user->email }}</p>
</div>
@if($roleData)
<div class="col-md-6 mb-3">
<h6 class="text-muted">Phone Number</h6>
<p class="fw-bold">{{ $roleData->phone_number }}</p>
</div>
<div class="col-md-6 mb-3">
<h6 class="text-muted">Address</h6>
<p class="fw-bold">{{ $roleData->address }}</p>
</div>
@endif
@if($user->role === 'patient' && $roleData)
<div class="col-md-6 mb-3">
<h6 class="text-muted">Date of Birth</h6>
<p class="fw-bold">{{ $roleData->date_of_birth->format('F d, Y') }}</p>
</div>
<div class="col-md-6 mb-3">
<h6 class="text-muted">Gender</h6>
<p class="fw-bold">{{ ucfirst($roleData->gender) }}</p>
</div>
<div class="col-md-6 mb-3">
<h6 class="text-muted">Blood Group</h6>
<p class="fw-bold">{{ $roleData->blood_group ?? 'Not specified' }}</p>
</div>
@endif
</div>
</div>
</div>
@if($user->role === 'doctor' && $roleData)
<div class="card shadow">
<div class="card-header bg-white">
<h5 class="card-title mb-0">Professional Information</h5>
</div>
<div class="card-body">
<h6 class="text-muted">Bio</h6>
<p>{{ $roleData->bio ?? 'No bio information available.' }}</p>
</div>
</div>
@endif
@if($user->role === 'patient' && $roleData)
<div class="card shadow">
<div class="card-header bg-white">
<h5 class="card-title mb-0">Medical Information</h5>
</div>
<div class="card-body">
<h6 class="text-muted">Allergies</h6>
<p>{{ $roleData->allergies ?? 'No allergies recorded.' }}</p>
</div>
</div>
@endif
</div>
</div>
</div>
@endsection
```
## Blade Views - Profile Edit
```php
{{-- resources/views/profile/edit.blade.php --}}
@extends('layouts.app')
@section('title', 'Edit Profile')
@section('page-title', 'Edit Profile')
@section('content')
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-md-10">
<div class="card shadow">
<div class="card-body">
<form action="{{ route('profile.update') }}" method="POST" enctype="multipart/form-data">
@csrf
@method('PUT')
<div class="row mb-4">
<div class="col-md-3 text-center">
<div class="mb-3">
@if($user->role === 'doctor' && $roleData && $roleData->profile_photo)
<img id="profile-preview" src="{{ asset('storage/profile_photos/' . $roleData-
>profile_photo) }}"
alt="Profile Photo"
class="rounded-circle img-fluid mb-3"
style="width: 150px; height: 150px; object-fit: cover;">
@else
<div id="profile-avatar" class="rounded-circle bg-primary text-white d-flex align-
items-center justify-content-center mx-auto mb-3"
style="width: 150px; height: 150px; font-size: 3rem;">
{{ strtoupper(substr($user->name, 0, 1)) }}
</div>
<img id="profile-preview" src="" alt="Profile Preview" class="rounded-circle img-
fluid mb-3 d-none"
style="width: 150px; height: 150px; object-fit: cover;">
@endif
<div class="mb-3">
<label for="profile_photo" class="btn btn-outline-primary btn-sm">
<i class="bi bi-camera me-1"></i> Change Photo
</label>
<input type="file" name="profile_photo" id="profile_photo" class="d-none"
onchange="previewImage(this)">
@error('profile_photo')
<div class="text-danger small mt-1">{{ $message }}</div>
@enderror
</div>
</div>
</div>
<div class="col-md-9">
<h4 class="mb-3">Personal Information</h4>
<div class="row mb-3">
<div class="col-md-6">
<label for="name" class="form-label">Full Name</label>
<input type="text" class="form-control @error('name') is-invalid @enderror"
id="name" name="name" value="{{ old('name', $user->name) }}" required>
@error('name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="col-md-6">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control @error('email') is-invalid @enderror"
id="email" name="email" value="{{ old('email', $user->email) }}" required>
@error('email')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
@if($roleData)
<div class="row mb-3">
<div class="col-md-6">
<label for="phone_number" class="form-label">Phone Number</label>
<input type="text" class="form-control @error('phone_number') is-invalid
@enderror" id="phone_number" name="phone_number" value="{{ old('phone_number', $roleData-
>phone_number) }}">
@error('phone_number')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="col-md-6">
<label for="address" class="form-label">Address</label>
<input type="text" class="form-control @error('address') is-invalid @enderror"
id="address" name="address" value="{{ old('address', $roleData->address) }}">
@error('address')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
@endif
@if($user->role === 'patient' && $roleData)
<div class="row mb-3">
<div class="col-md-6">
<label for="blood_group" class="form-label">Blood Group</label>
<select class="form-select @error('blood_group') is-invalid @enderror"
id="blood_group" name="blood_group">
<option value="">Select Blood Group</option>
@foreach(['A+', 'A-', 'B+', 'B-', 'AB+', 'AB-', 'O+', 'O-'] as $group)
<option value="{{ $group }}" {{ old('blood_group', $roleData->blood_group)
== $group ? 'selected' : '' }}>{{ $group }}</option>
@endforeach
</select>
@error('blood_group')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
<div class="mb-3">
<label for="allergies" class="form-label">Allergies</label>
<textarea class="form-control @error('allergies') is-invalid @enderror"
id="allergies" name="allergies" rows="3">{{ old('allergies', $roleData->allergies) }}</textarea>
@error('allergies')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
@endif
@if($user->role === 'doctor' && $roleData)
<div class="mb-3">
<label for="bio" class="form-label">Bio</label>
<textarea class="form-control @error('bio') is-invalid @enderror" id="bio"
name="bio" rows="4">{{ old('bio', $roleData->bio) }}</textarea>
@error('bio')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
@endif
</div>
</div>
<hr class="my-4">
<h4 class="mb-3">Change Password</h4>
<p class="text-muted small mb-3">Leave these fields empty if you don't want to change
your password.</p>
<div class="row mb-3">
<div class="col-md-4">
<label for="current_password" class="form-label">Current Password</label>
<input type="password" class="form-control @error('current_password') is-invalid
@enderror" id="current_password" name="current_password">
@error('current_password')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="col-md-4">
<label for="password" class="form-label">New Password</label>
<input type="password" class="form-control @error('password') is-invalid @enderror"
id="password" name="password">
@error('password')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="col-md-4">
<label for="password_confirmation" class="form-label">Confirm New
Password</label>
<input type="password" class="form-control" id="password_confirmation"
name="password_confirmation">
</div>
</div>
<div class="d-flex justify-content-between mt-4">
<a href="{{ route('profile.show') }}" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left me-1"></i> Cancel
</a>
<button type="submit" class="btn btn-primary">
<i class="bi bi-save me-1"></i> Save Changes
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@push('scripts')
<script>
function previewImage(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$('#profile-preview').attr('src', e.target.result).removeClass('d-none');
$('#profile-avatar').addClass('d-none');
reader.readAsDataURL(input.files[0]);
</script>
@endpush
@endsection
```
## Add CSS for Responsive Enhancements
```css
/* public/css/app.css - Add these styles */
/* Profile Responsive Adjustments */
@media (max-width: 768px) {
.profile-header {
flex-direction: column;
text-align: center;
.profile-avatar {
margin-bottom: 1rem;
/* Card Hover Effects */
.profile-card {
transition: transform 0.3s ease, box-shadow 0.3s ease;
.profile-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
/* Form Controls */
.form-control:focus, .form-select:focus {
border-color: #4a6fdc;
box-shadow: 0 0 0 0.25rem rgba(74, 111, 220, 0.25);
/* Custom Profile Photo Upload Button */
.photo-upload-btn {
position: relative;
overflow: hidden;
.photo-upload-btn input[type=file] {
position: absolute;
top: 0;
right: 0;
min-width: 100%;
min-height: 100%;
font-size: 100px;
text-align: right;
filter: alpha(opacity=0);
opacity: 0;
outline: none;
cursor: pointer;
display: block;
```
This code provides a complete solution for a responsive profile page in your Laravel hospital
management application. It includes:
- A ProfileController with methods to show, edit, and update user profiles
- Routes for accessing the profile functionality
- Responsive blade views for both displaying and editing the profile
- Support for different user roles (doctor, patient, admin)
- Profile photo upload and preview functionality
- Password change capability with validation
- CSS styles for enhanced responsiveness and visual appeal
The design uses Bootstrap 5 for the responsive grid and components, with additional custom CSS for
styling enhancements. The layout adapts to different screen sizes, ensuring a good user experience on
both desktop and mobile devices.