Skip to content

Commit 06d11f0

Browse files
committed
Add profile update with avatar upload support
Implemented profile update functionality, including validation and support for avatar image uploads using Spatie MediaLibrary. Updated the User model to register an 'avatars' media collection as a single file, adjusted the profile view to handle avatar previews, and added the corresponding route for profile updates.
1 parent ea43733 commit 06d11f0

File tree

4 files changed

+71
-20
lines changed

4 files changed

+71
-20
lines changed

app/Http/Controllers/ProfileController.php

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,43 @@ public function edit(string $id)
5353
*/
5454
public function update(Request $request, string $id)
5555
{
56-
return redirect()->route('profile.show')->with('success', 'Profile updated successfully.');
56+
$user = auth()->user();
57+
58+
// Validate input
59+
$validated = $request->validate([
60+
'name' => ['required', 'string', 'max:255'],
61+
'email' => ['required', 'email', 'max:255'],
62+
'password' => ['nullable', 'confirmed', 'min:8'],
63+
'avatar' => ['nullable', 'image', 'max:2048'],
64+
]);
65+
66+
// Update basic fields
67+
$user->name = $validated['name'];
68+
$user->email = $validated['email'];
69+
70+
// Update password only if provided
71+
if (!empty($validated['password'])) {
72+
$user->password = Hash::make($validated['password']);
73+
}
74+
75+
$user->save();
76+
77+
// Handle avatar upload
78+
if ($request->hasFile('avatar')) {
79+
80+
// Build the new filename:
81+
// example: "andrewbeechey_avatar.jpg"
82+
$uploadedFile = $request->file('avatar');
83+
$extension = $uploadedFile->getClientOriginalExtension();
84+
$fileName = $user->username . '_avatar.' . $extension;
85+
86+
// If using singleFile(), Spatie replaces automatically.
87+
$user->addMedia($uploadedFile)
88+
->usingFileName($fileName)
89+
->toMediaCollection('avatars');
90+
}
91+
92+
return back()->with('success', 'Profile updated successfully!');
5793
}
5894

5995
/**

app/Models/User.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
use Illuminate\Notifications\Notifiable;
1111
use Illuminate\Support\Str;
1212
use Spatie\Permission\Traits\HasRoles;
13+
use Spatie\MediaLibrary\HasMedia;
14+
use Spatie\MediaLibrary\InteractsWithMedia;
1315

14-
class User extends Authenticatable implements MustVerifyEmail
16+
class User extends Authenticatable implements MustVerifyEmail, HasMedia
1517
{
1618
/** @use HasFactory<\Database\Factories\UserFactory> */
17-
use HasFactory, Notifiable, HasRoles;
19+
use HasFactory, Notifiable, HasRoles, InteractsWithMedia;
1820

1921
/**
2022
* The attributes that are mass assignable.
@@ -62,6 +64,11 @@ public function initials(): string
6264
->implode('');
6365
}
6466

67+
public function registerMediaCollections(): void
68+
{
69+
$this->addMediaCollection('avatars')->singleFile();
70+
}
71+
6572

6673
public function dossier()
6774
{

resources/views/profile/index.blade.php

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,28 +31,35 @@
3131

3232
<div class="p-6 pt-0 space-y-6">
3333
<div class="flex justify-center mb-6">
34-
{{-- <div class="h-24 w-24 rounded-full bg-amber-400/20 border border-amber-400/40 flex items-center justify-center text-2xl font-bold text-amber-300" id="avatarFallback">CS</div> --}}
3534
<flux:file-upload wire:model="photo">
36-
<!-- Custom avatar uploader -->
37-
<div class="h-24 w-24
38-
relative flex items-center justify-center size-20 rounded-full transition-colors cursor-pointer
39-
border border-zinc-200 dark:border-white/10 hover:border-zinc-300 dark:hover:border-white/10
40-
bg-zinc-100 hover:bg-zinc-200 dark:bg-white/10 hover:dark:bg-white/15 in-data-dragging:dark:bg-white/15
41-
">
42-
<!-- Show the uploaded file if it exists -->
43-
{{-- @if ($photo)
44-
<img src="{{ $photo?->temporaryUrl() }}" class="size-full object-cover rounded-full" />
35+
<div
36+
class="relative flex items-center justify-center h-24 w-24 rounded-full transition-colors cursor-pointer
37+
border border-amber-400/40 hover:border-amber-400/60
38+
bg-amber-400/20 hover:bg-amber-400/30
39+
dark:border-amber-400/20 dark:hover:border-amber-400/40
40+
dark:bg-amber-400/10 dark:hover:bg-amber-400/20"
41+
>
42+
@if ($photo)
43+
<!-- Preview uploaded avatar -->
44+
<img src="{{ $photo->temporaryUrl() }}" class="h-full w-full object-cover rounded-full" />
4545
@else
46-
<!-- Show the default icon if no file is uploaded -->
47-
<flux:icon name="user" variant="solid" class="text-zinc-500 dark:text-zinc-400" />
48-
@endif --}}
46+
<!-- Your existing fallback -->
47+
<div class="h-full w-full flex items-center justify-center rounded-full text-2xl font-bold text-amber-300">
48+
CS
49+
</div>
50+
@endif
4951

5052
<!-- Corner upload icon -->
51-
<div class="absolute bottom-0 right-0 bg-white dark:bg-zinc-800 rounded-full">
52-
<flux:icon name="arrow-up-circle" variant="solid" class="text-zinc-500 dark:text-zinc-400" />
53+
<div
54+
class="absolute bottom-0 right-0 bg-white dark:bg-zinc-800 p-1 rounded-full shadow
55+
border border-zinc-200 dark:border-zinc-700"
56+
>
57+
<flux:icon name="arrow-up-circle" variant="solid" class="h-5 w-5 text-amber-500 dark:text-amber-400" />
5358
</div>
5459
</div>
55-
</flux:file-upload>
60+
</flux:file-upload>
61+
62+
5663
</div>
5764
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
5865
<!-- Full Name -->
@@ -143,7 +150,7 @@
143150
<p class="text-sm text-slate-400">Manage your account security and authentication</p>
144151
</div>
145152
<div class="p-6 space-y-6">
146-
<form method="POST" action="{{ route('profile.store') }}" enctype="multipart/form-data">
153+
<form method="POST" action="{{ route('profile.update') }}" enctype="multipart/form-data">
147154
@csrf
148155

149156
<div>

routes/web.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
Route::prefix('profile')->name('profile.')->middleware(['auth'])->group(function () {
5252

5353
Route::get('/', [ProfileController::class, 'index'])->name('index');
54+
Route::post('/', [ProfileController::class, 'update'])->name('update');
5455
});
5556

5657
// Org Services

0 commit comments

Comments
 (0)