feature: add user assignments component
- add title, placeholder and subtitle in avatar component - add role collection in users dto - make show empty text on table by default
This commit is contained in:
parent
9443ac181c
commit
c8e950bb79
@ -4,9 +4,19 @@
|
||||
|
||||
namespace App\Data\Users;
|
||||
|
||||
use Spatie\LaravelData\Data;
|
||||
use App\Data\Ui\ManageRoles\RoleData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\{Data, DataCollection};
|
||||
|
||||
final class UserData extends Data
|
||||
{
|
||||
public function __construct(public string $name, public string $email) {}
|
||||
public function __construct(
|
||||
public string $name,
|
||||
public string $email,
|
||||
public bool $active = false,
|
||||
|
||||
/** @var DataCollection<int, RoleData>|null */
|
||||
#[DataCollectionOf(class: RoleData::class)]
|
||||
public ?DataCollection $roles = null,
|
||||
) {}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
use Illuminate\Support\{Arr, ServiceProvider};
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
|
||||
final class ScopeServiceProvider extends ServiceProvider
|
||||
final class DirectiveServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap services.
|
||||
@ -15,9 +15,19 @@ final class ScopeServiceProvider extends ServiceProvider
|
||||
public function boot(): void
|
||||
{
|
||||
$this->registerScopeDirective();
|
||||
$this->registerInitialsDirective();
|
||||
}
|
||||
|
||||
public function registerScopeDirective(): void
|
||||
private function registerInitialsDirective(): void
|
||||
{
|
||||
Blade::directive('initials', fn ($expression) => "<?php
|
||||
echo implode('', array_map(function(\$w) {
|
||||
return strtoupper(\$w[0] ?? '');
|
||||
}, explode(' ', $expression)));
|
||||
?>");
|
||||
}
|
||||
|
||||
private function registerScopeDirective(): void
|
||||
{
|
||||
/**
|
||||
* All credits from this blade directive goes to Konrad Kalemba.
|
||||
@ -23,7 +23,7 @@ public function __construct(
|
||||
public bool $withPagination = false,
|
||||
public array $rowDecoration = [],
|
||||
public array $cellDecoration = [],
|
||||
public bool $showEmptyText = false,
|
||||
public bool $showEmptyText = true,
|
||||
public string $emptyText = 'No records found.',
|
||||
public string $containerClass = 'relative overflow-x-auto rounded-2xl -pb-2',
|
||||
public bool $noHover = false,
|
||||
@ -173,6 +173,7 @@ public function render(): View|Closure|string
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@isset($rows)
|
||||
<tbody>
|
||||
@foreach($rows as $k => $row)
|
||||
<tr
|
||||
@ -230,7 +231,7 @@ public function render(): View|Closure|string
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
||||
@endisset
|
||||
@isset ($footer)
|
||||
<tfoot @class([
|
||||
"text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400",
|
||||
@ -241,7 +242,7 @@ public function render(): View|Closure|string
|
||||
@endisset
|
||||
</table>
|
||||
|
||||
@if(count($rows) === 0)
|
||||
@if(!$rows || count($rows) === 0)
|
||||
@if($showEmptyText)
|
||||
<div class="text-center py-8 text-gray-500 dark:text-gray-400">
|
||||
{{ $emptyText }}
|
||||
|
||||
@ -5,5 +5,5 @@
|
||||
return [
|
||||
App\Providers\AppServiceProvider::class,
|
||||
App\Providers\FortifyServiceProvider::class,
|
||||
App\Providers\ScopeServiceProvider::class,
|
||||
App\Providers\DirectiveServiceProvider::class,
|
||||
];
|
||||
|
||||
@ -85,11 +85,7 @@ public function mount(): void
|
||||
@php /** @var RoleData $role */ @endphp
|
||||
<div class="flex -space-x-3">
|
||||
@foreach($role->users as $user)
|
||||
<x-shared.avatar>
|
||||
<span class="text-xs font-bold text-center text-blue-800">
|
||||
{{implode('', array_map(fn($w) => strtoupper($w[0]), explode(' ', $user->name)))}}
|
||||
</span>
|
||||
</x-shared.avatar>
|
||||
<x-shared.avatar class="text-blue-800" :placeholder="$user->name" />
|
||||
@endforeach
|
||||
</div>
|
||||
@endscope
|
||||
|
||||
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
use App\Data\Ui\TableHeader;
|
||||
use App\Data\Users\UserData;
|
||||
use App\Data\Ui\ManageRoles\RoleData;
|
||||
use App\Data\Ui\ManageRoles\ServiceData;
|
||||
use App\Enums\RolesStatus;
|
||||
use Livewire\Component;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
new class extends Component {
|
||||
/** @var DataCollection<int, TableHeader> */
|
||||
#[DataCollectionOf(TableHeader::class)]
|
||||
public DataCollection $header;
|
||||
|
||||
/** @var DataCollection<int, UserData>|null */
|
||||
#[DataCollectionOf(UserData::class)]
|
||||
public ?DataCollection $users = null;
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->header = TableHeader::collect([
|
||||
new TableHeader('name', 'User'),
|
||||
new TableHeader('role.name', 'Role'),
|
||||
new TableHeader('role.service', 'Service Access'),
|
||||
new TableHeader('status', 'Status'),
|
||||
], DataCollection::class);
|
||||
|
||||
$this->users = UserData::collect([
|
||||
new UserData(
|
||||
name: 'Priya Rao',
|
||||
email: 'priya@example.com',
|
||||
active: true,
|
||||
roles: RoleData::collect([
|
||||
new RoleData(
|
||||
name: 'Super Admin',
|
||||
users: UserData::collect([], DataCollection::class),
|
||||
services: ServiceData::collect([
|
||||
new ServiceData(name: 'AWS Core'),
|
||||
new ServiceData(name: 'GitHub Enterprise'),
|
||||
], DataCollection::class),
|
||||
status: RolesStatus::Active,
|
||||
),
|
||||
new RoleData(
|
||||
name: 'HR Manager',
|
||||
users: UserData::collect([], DataCollection::class),
|
||||
services: ServiceData::collect([
|
||||
new ServiceData(name: 'Keka'),
|
||||
new ServiceData(name: 'Outlook'),
|
||||
], DataCollection::class),
|
||||
status: RolesStatus::Active,
|
||||
)
|
||||
], DataCollection::class)
|
||||
),
|
||||
|
||||
new UserData(
|
||||
name: 'Kushal Saha',
|
||||
email: 'kushal@example.com',
|
||||
active: true,
|
||||
roles: RoleData::collect([
|
||||
new RoleData(
|
||||
name: 'Backend Developer',
|
||||
users: UserData::collect([], DataCollection::class),
|
||||
services: ServiceData::collect([
|
||||
new ServiceData(name: 'Forge'),
|
||||
], DataCollection::class),
|
||||
status: RolesStatus::Active,
|
||||
)
|
||||
], DataCollection::class)
|
||||
),
|
||||
|
||||
new UserData(
|
||||
name: 'Alex Johnson',
|
||||
email: 'alex@example.com',
|
||||
active: false,
|
||||
roles: RoleData::collect([
|
||||
new RoleData(
|
||||
name: 'Guest Viewer',
|
||||
users: UserData::collect([], DataCollection::class),
|
||||
services: ServiceData::collect([
|
||||
new ServiceData(name: 'Analytics Dashboard'),
|
||||
], DataCollection::class),
|
||||
status: RolesStatus::Active,
|
||||
)
|
||||
], DataCollection::class)
|
||||
)
|
||||
], DataCollection::class);
|
||||
}
|
||||
};
|
||||
?>
|
||||
|
||||
<div>
|
||||
<x-shared.card title="User Assignments" icon="lucide-users" class="p-0">
|
||||
<x-slot:actions>
|
||||
<x-shared.button icon="lucide-plus">
|
||||
{{ __('Assign user') }}
|
||||
</x-shared.button>
|
||||
</x-slot:actions>
|
||||
|
||||
<x-table :headers="$header->toArray()" :rows="$users">
|
||||
@scope('cell_name', $row)
|
||||
<x-shared.avatar :placeholder="$row->name" :title="$row->name" :subtitle="$row->email" />
|
||||
@endscope
|
||||
@scope('cell_role.name', $row)
|
||||
<div class="flex space-x-2">
|
||||
@foreach ($row->roles as $role)
|
||||
<x-shared.badge>
|
||||
{{$role->name}}
|
||||
</x-shared.badge>
|
||||
@endforeach
|
||||
</div>
|
||||
@endscope
|
||||
|
||||
@scope('cell_role.service', $row)
|
||||
<div class="flex space-x-2 text-sm">
|
||||
@foreach ($row->roles as $role)
|
||||
@foreach($role->services as $service)
|
||||
{{$service->name}},
|
||||
@endforeach
|
||||
@endforeach
|
||||
</div>
|
||||
@endscope
|
||||
|
||||
@scope('cell_status', $row)
|
||||
@if($row->active)
|
||||
<x-shared.badge class="bg-lime-200 text-lime-800 font-bold">Active</x-shared.badge>
|
||||
@else
|
||||
<x-shared.badge class="bg-orange-200 text-orange-800 font-bold">Not Active</x-shared.badge>
|
||||
@endif
|
||||
@endscope
|
||||
|
||||
@scope('actions', $row)
|
||||
<x-shared.button icon="lucide-square-pen"/>
|
||||
@endscope
|
||||
</x-table>
|
||||
</x-shared.card>
|
||||
</div>
|
||||
@ -1,3 +1,18 @@
|
||||
<span {{$attributes->twMerge(['class' => 'bg-blue-300 w-8 h-8 border border-white rounded-full flex items-center justify-center'])}}>
|
||||
{{$slot}}
|
||||
@props(['placeholder', 'title', 'subtitle'])
|
||||
<div class="flex space-x-2 items-center">
|
||||
<span {{$attributes->twMerge(['class' => 'bg-blue-300 text-blue-800 w-8 h-8 border border-white rounded-full flex items-center justify-center'])}}>
|
||||
@isset($placeholder)
|
||||
@initials($placeholder)
|
||||
@endisset
|
||||
</span>
|
||||
<div class="flex flex-col">
|
||||
@isset($title)
|
||||
<p class="font-semibold">
|
||||
{{$title}}
|
||||
</p>
|
||||
@endisset
|
||||
@isset($subtitle)
|
||||
{{$subtitle}}
|
||||
@endisset
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -18,5 +18,6 @@ class extends Component {
|
||||
<livewire:dashboard.connected-services />
|
||||
<livewire:dashboard.roles.manager />
|
||||
<livewire:dashboard.roles.hr-permission />
|
||||
<livewire:dashboard.users.assignments />
|
||||
</div>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user