diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php
index 3b07744..6e07e61 100644
--- a/app/Http/Controllers/AccountController.php
+++ b/app/Http/Controllers/AccountController.php
@@ -7,6 +7,7 @@
use Illuminate\Http\Request;
use \Illuminate\Validation\ValidationException;
use Inertia\Response;
+use NiftyCo\Attachments\Attachment;
class AccountController extends Controller
{
@@ -22,12 +23,17 @@ public function update(Request $request)
$request->validate([
'name' => 'required|string',
'email' => 'required|email:rfc,dns',
+ 'avatar' => ['nullable', 'mimes:jpg,jpeg,png', 'max:1024'],
]);
$user = auth()->user();
$user->fill($request->only('name'));
+ if ($request->hasFile('avatar')) {
+ $user->avatar = Attachment::fromFile($request->file('avatar'), folder: 'avatars');
+ }
+
if ($user->email !== $request->email) {
$user->fill([
'confirmed_at' => null,
diff --git a/app/Http/Controllers/DestroyAvatarController.php b/app/Http/Controllers/DestroyAvatarController.php
new file mode 100644
index 0000000..91ce3ad
--- /dev/null
+++ b/app/Http/Controllers/DestroyAvatarController.php
@@ -0,0 +1,31 @@
+user();
+
+ if (is_null($user->avatar)) {
+ return inertia()->location(route('account'));
+ }
+
+ $avatar = $user->avatar->toArray();
+
+ Storage::disk($avatar['disk'])->delete($avatar['name']);
+
+ $user->forceFill([
+ 'avatar' => null,
+ ])->save();
+
+ return inertia()->location(route('account'));
+ }
+}
diff --git a/app/Http/Resources/UserResource.php b/app/Http/Resources/UserResource.php
index fd4ce1d..7eb276f 100644
--- a/app/Http/Resources/UserResource.php
+++ b/app/Http/Resources/UserResource.php
@@ -17,7 +17,8 @@ public function toArray(Request $request): array
return [
'id' => $this->id,
'name' => $this->name,
- 'email' => $this->email
+ 'email' => $this->email,
+ 'avatar' => $this->avatar ? $this->avatar->url : 'https://ui-avatars.com/api/?background=a0a0a0&name=' . urlencode($this->name),
];
}
}
diff --git a/app/Models/User.php b/app/Models/User.php
index 3d79888..9046fd8 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -10,6 +10,7 @@
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Foundation\Auth\Access\Authorizable;
+use NiftyCo\Attachments\Casts\AsAttachment;
class User extends Model implements AuthenticatableContract, AuthorizableContract
{
@@ -27,6 +28,7 @@ protected function casts(): array
return [
'confirmed_at' => 'datetime',
'password' => 'hashed',
+ 'avatar' => AsAttachment::class,
];
}
diff --git a/composer.json b/composer.json
index 9772012..cf1d295 100644
--- a/composer.json
+++ b/composer.json
@@ -27,6 +27,7 @@
"require": {
"php": "^8.2",
"aniftyco/laravel-advanced-db-sessions": "dev-master",
+ "aniftyco/laravel-attachments": "dev-master",
"inertiajs/inertia-laravel": "^1.3",
"laravel/framework": "^11.9",
"laravel/tinker": "^2.9",
diff --git a/composer.lock b/composer.lock
index 6591ac4..fdd3e87 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "aa257b2cbc75b97f75d28e7190524b7d",
+ "content-hash": "703abdde1807c88599e65936a9032f2b",
"packages": [
{
"name": "aniftyco/laravel-advanced-db-sessions",
@@ -70,6 +70,68 @@
},
"time": "2024-10-10T00:22:52+00:00"
},
+ {
+ "name": "aniftyco/laravel-attachments",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/aniftyco/laravel-attachments.git",
+ "reference": "85f6145e4d05c982ea0275896e4a724563c0688d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/aniftyco/laravel-attachments/zipball/85f6145e4d05c982ea0275896e4a724563c0688d",
+ "reference": "85f6145e4d05c982ea0275896e4a724563c0688d",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "orchestra/testbench": "^9.5",
+ "pestphp/pest": "^3.3"
+ },
+ "default-branch": true,
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "NiftyCo\\Attachments\\ServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "NiftyCo\\Attachments\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "NiftyCo, LLC",
+ "homepage": "https://aniftyco.com"
+ },
+ {
+ "name": "Josh Manders",
+ "homepage": "https://x.com/joshmanders"
+ }
+ ],
+ "description": "Turn any field on your Eloquent models into attachments",
+ "homepage": "https://github.com/aniftyco/laravel-attachments",
+ "keywords": [
+ "attachments",
+ "eloquent",
+ "laravel"
+ ],
+ "support": {
+ "issues": "https://github.com/aniftyco/laravel-attachments/issues",
+ "source": "https://github.com/aniftyco/laravel-attachments/tree/master"
+ },
+ "time": "2024-10-08T00:24:02+00:00"
+ },
{
"name": "brick/math",
"version": "0.12.1",
@@ -9446,7 +9508,8 @@
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
- "aniftyco/laravel-advanced-db-sessions": 20
+ "aniftyco/laravel-advanced-db-sessions": 20,
+ "aniftyco/laravel-attachments": 20
},
"prefer-stable": true,
"prefer-lowest": false,
diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php
index 83dfd67..bef7ff1 100644
--- a/database/migrations/0001_01_01_000000_create_users_table.php
+++ b/database/migrations/0001_01_01_000000_create_users_table.php
@@ -22,6 +22,8 @@ public function up(): void
$table->string('role')->default(UserRole::CUSTOMER)->index();
+ $table->jsonb('avatar')->nullable();
+
$table->timestamp('confirmed_at')->nullable();
$table->timestamps();
$table->softDeletes();
diff --git a/resources/client/forms/UpdateAccountInformation.vue b/resources/client/forms/UpdateAccountInformation.vue
index c61821a..066b56d 100644
--- a/resources/client/forms/UpdateAccountInformation.vue
+++ b/resources/client/forms/UpdateAccountInformation.vue
@@ -1,24 +1,73 @@
@@ -28,6 +77,37 @@ const submit = () => {
Update your account information and email address.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ form.errors.avatar }}
+
+
diff --git a/resources/client/layouts/app.vue b/resources/client/layouts/app.vue
index 0343702..cf87a87 100644
--- a/resources/client/layouts/app.vue
+++ b/resources/client/layouts/app.vue
@@ -9,6 +9,7 @@ type PageProps = {
user: {
name: string;
email: string;
+ avatar?: string;
};
};
};
@@ -16,8 +17,6 @@ type PageProps = {
const { props } = usePage();
const showingNavigationDropdown = ref(false);
-const gravatar = 'https://gravatar.com/userimage/19287721/9cd577bdd3c1f36f600a246863a5f7bb.jpeg?size=256';
-
type Team = {
id: number;
name: string;
@@ -160,7 +159,11 @@ const signOut = () => {
type="button"
class="inline-flex items-center px-2 py-1.5 border border-transparent text-sm leading-4 font-medium rounded-md text-background-500 dark:text-background-400 bg-white dark:bg-background-800 hover:text-background-700 dark:hover:text-background-300 focus:outline-none focus:bg-background-100 dark:focus:bg-background-700 hover:bg-background-100 dark:hover:bg-background-700 active:bg-background-100 dark:active:bg-background-700 transition ease-in-out duration-150"
>
-
+
{{ props.auth.user.name }}
diff --git a/routes/web.php b/routes/web.php
index aa979c7..e1815e3 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -2,6 +2,7 @@
use App\Http\Controllers\AccountController;
use App\Http\Controllers\ConfirmPasswordController;
+use App\Http\Controllers\DestroyAvatarController;
use App\Http\Controllers\ForgotPasswordController;
use App\Http\Controllers\PasswordController;
use App\Http\Controllers\ResetPasswordController;
@@ -53,6 +54,8 @@
Route::delete('/account/sessions', [SessionsController::class, 'destroy'])->name('sessions.destroy');
+ Route::delete('/account/avatar', DestroyAvatarController::class)->name('avatar.destroy');
+
Route::get('/banner', function () {
session()->flash('flash', [
'banner' => [