Skip to content

Commit e835fee

Browse files
authored
Merge pull request #564 from code16/implement-profile-picture
User Profile Picture support 🎉
2 parents 40e90c0 + d1d01dd commit e835fee

File tree

6 files changed

+32
-3
lines changed

6 files changed

+32
-3
lines changed

demo/app/Providers/DemoSharpServiceProvider.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ protected function configureSharp(SharpConfigBuilder $config): void
2828
->setAuthCustomGuard('web')
2929
->setLoginAttributes('email', 'password')
3030
->setUserDisplayAttribute('name')
31+
->setUserAvatarAttribute(fn () => auth()->user()->avatar?->thumbnail(200))
3132
->enable2faCustom(Demo2faNotificationHandler::class)
3233
->enableLoginRateLimiting(maxAttempts: 3)
3334
->suggestRememberMeOnLoginForm()

docs/guide/authentication.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ class SharpServiceProvider extends SharpAppServiceProvider
1414
$config
1515
->setLoginAttributes('login', 'pwd')
1616
->setUserDisplayAttribute('last_name')
17+
->setUserAvatarAttribute('avatar_url')
1718
// [...]
1819
}
1920
}
2021
```
2122

22-
The `setUserDisplayAttribute()` is useful to display the user's name in the Sharp UI. Default is `name`.
23+
- The `setUserDisplayAttribute()` is useful to display the user's name in the Sharp UI. Default is `name`.
24+
- The `setUserAvatarAttribute()` is useful to display the user's avatar in the Sharp UI. By default, a user icon is displayed instead.
2325

2426
## Login form
2527

resources/js/Layouts/Layout.vue

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,13 @@ export function useMenuBoundaryElement() {
215215
size="lg"
216216
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
217217
>
218-
<span class="inline-flex items-center justify-center size-8 bg-secondary rounded-lg">
219-
<CircleUser class="h-5 w-5" />
218+
<span class="inline-flex items-center justify-center size-8 bg-secondary rounded-lg overflow-hidden">
219+
<template v-if="auth().user.avatar">
220+
<img class="size-full aspect-1/1 object-cover" :src="auth().user.avatar" :alt="auth().user.name">
221+
</template>
222+
<template v-else>
223+
<CircleUser class="size-5" />
224+
</template>
220225
</span>
221226
<div class="grid flex-1 text-left text-sm leading-tight">
222227
<span class="truncate font-semibold"> {{ auth().user.name }}</span>

resources/js/types/generated.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,7 @@ export type ShowTextFieldData = {
859859
export type UserData = {
860860
name: string | null;
861861
email: string | null;
862+
avatar: string | null;
862863
};
863864
export type UserMenuData = {
864865
items: Array<MenuItemData>;

src/Config/SharpConfigBuilder.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Code16\Sharp\Utils\Entities\SharpEntityResolver;
1616
use Code16\Sharp\Utils\Filters\GlobalRequiredFilter;
1717
use Code16\Sharp\Utils\Menu\SharpMenu;
18+
use Illuminate\Contracts\Auth\Authenticatable;
1819
use Illuminate\Contracts\Auth\PasswordBroker;
1920
use Illuminate\Contracts\View\View;
2021
use Illuminate\Foundation\Vite;
@@ -61,6 +62,7 @@ class SharpConfigBuilder
6162
'logout_page_url' => null,
6263
'display_attribute' => 'name',
6364
'login_attribute' => 'email',
65+
'avatar_attribute' => null,
6466
'password_attribute' => 'password',
6567
'impersonate' => [
6668
'enabled' => false,
@@ -414,6 +416,17 @@ public function setUserDisplayAttribute(string $displayAttribute): self
414416
return $this;
415417
}
416418

419+
/**
420+
* @param (string|Closure(Authenticatable $user): string) $avatarAttribute
421+
* @return $this
422+
*/
423+
public function setUserAvatarAttribute(string|Closure $avatarAttribute): self
424+
{
425+
$this->config['auth']['avatar_attribute'] = $avatarAttribute;
426+
427+
return $this;
428+
}
429+
417430
public function setAuthCustomGuard(?string $guardName): self
418431
{
419432
$this->config['auth']['guard'] = $guardName;

src/Data/UserData.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Code16\Sharp\Data;
44

5+
use Closure;
56
use Illuminate\Contracts\Auth\Authenticatable;
67

78
/**
@@ -12,13 +13,19 @@ final class UserData extends Data
1213
public function __construct(
1314
public ?string $name,
1415
public ?string $email,
16+
public ?string $avatar,
1517
) {}
1618

1719
public static function from(Authenticatable $user): self
1820
{
1921
return new self(
2022
name: $user->{sharp()->config()->get('auth.display_attribute')} ?? null,
2123
email: $user->{sharp()->config()->get('auth.login_attribute')} ?? null,
24+
avatar: match (true) {
25+
is_string(sharp()->config()->get('auth.avatar_attribute')) => $user->{sharp()->config()->get('auth.avatar_attribute')},
26+
sharp()->config()->get('auth.avatar_attribute') instanceof Closure => sharp()->config()->get('auth.avatar_attribute')($user),
27+
default => null,
28+
},
2229
);
2330
}
2431
}

0 commit comments

Comments
 (0)