使用者列表改版 20250424
This commit is contained in:
parent
407f15c1ed
commit
97d2fdd3c9
42
app/Livewire/Admin/EditUserModal.php
Normal file
42
app/Livewire/Admin/EditUserModal.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Admin;
|
||||
|
||||
use LivewireUI\Modal\ModalComponent;
|
||||
use App\Models\User;
|
||||
|
||||
class EditUserModal extends ModalComponent
|
||||
{
|
||||
public $userId;
|
||||
public $name;
|
||||
public $email;
|
||||
|
||||
public function mount($userId)
|
||||
{
|
||||
$user = User::findOrFail($userId);
|
||||
$this->userId = $user->id;
|
||||
$this->name = $user->name;
|
||||
$this->email = $user->email;
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate([
|
||||
'name' => 'required',
|
||||
'email' => 'required|email',
|
||||
]);
|
||||
|
||||
User::find($this->userId)->update([
|
||||
'name' => $this->name,
|
||||
'email' => $this->email,
|
||||
]);
|
||||
|
||||
$this->closeModal();
|
||||
$this->dispatch('notify', '使用者更新成功');
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.admin.edit-user-modal');
|
||||
}
|
||||
}
|
148
app/Livewire/Admin/UserTable.php
Normal file
148
app/Livewire/Admin/UserTable.php
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Admin;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use PowerComponents\LivewirePowerGrid\Button;
|
||||
use PowerComponents\LivewirePowerGrid\Column;
|
||||
use PowerComponents\LivewirePowerGrid\Facades\Filter;
|
||||
use PowerComponents\LivewirePowerGrid\Facades\PowerGrid;
|
||||
use PowerComponents\LivewirePowerGrid\PowerGridFields;
|
||||
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
|
||||
use PowerComponents\LivewirePowerGrid\Traits\WithExport;
|
||||
use PowerComponents\LivewirePowerGrid\Components\SetUp\Exportable;
|
||||
use PowerComponents\LivewirePowerGrid\Facades\Rule;
|
||||
use Livewire\Attributes\On;
|
||||
|
||||
final class UserTable extends PowerGridComponent
|
||||
{
|
||||
use WithExport;
|
||||
|
||||
public string $tableName = 'user-table';
|
||||
|
||||
public bool $showFilters = false;
|
||||
|
||||
public bool $showEditModal = false;
|
||||
public $editingUserId;
|
||||
public $name;
|
||||
public $email;
|
||||
|
||||
public function boot(): void
|
||||
{
|
||||
config(['livewire-powergrid.filter' => 'outside']);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
|
||||
public function setUp(): array
|
||||
{
|
||||
$this->showCheckBox();
|
||||
|
||||
return [
|
||||
PowerGrid::exportable(fileName: 'my-export-file')
|
||||
->type(Exportable::TYPE_XLS, Exportable::TYPE_CSV),
|
||||
PowerGrid::header()
|
||||
//->showSoftDeletes()
|
||||
->showToggleColumns()
|
||||
->showSearchInput(),
|
||||
PowerGrid::footer()->showPerPage()->showRecordCount(),
|
||||
];
|
||||
}
|
||||
public function header(): array
|
||||
{
|
||||
return [
|
||||
Button::add('bulk-delete')
|
||||
->slot('Bulk delete (<span x-text="window.pgBulkActions.count(\'' . $this->tableName . '\')"></span>)')
|
||||
->icon('solid-trash',['id' => 'my-custom-icon-id', 'class' => 'font-bold'])
|
||||
->class('inline-flex items-center gap-1 px-3 py-1 rounded ')
|
||||
->dispatch('bulkDelete.' . $this->tableName, []),
|
||||
];
|
||||
}
|
||||
|
||||
public function datasource(): Builder
|
||||
{
|
||||
return User::query();
|
||||
}
|
||||
|
||||
public function relationSearch(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function fields(): PowerGridFields
|
||||
{
|
||||
return PowerGrid::fields()
|
||||
->add('id')
|
||||
->add('name')
|
||||
->add('email')
|
||||
->add('created_at_formatted', fn (User $model) => Carbon::parse($model->created_at)->format('d/m/Y H:i:s'));
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
Column::make('ID', 'id'),
|
||||
Column::make('名稱', 'name')->sortable()->searchable(),
|
||||
Column::make('Email', 'email')->sortable()->searchable(),
|
||||
Column::make('建立時間', 'created_at_formatted', 'created_at')->sortable(),
|
||||
Column::action('操作')
|
||||
];
|
||||
}
|
||||
|
||||
public function filters(): array
|
||||
{
|
||||
return [
|
||||
Filter::inputText('name')->placeholder('Dish Name'),
|
||||
Filter::inputText('email')->placeholder('Dish Email'),
|
||||
Filter::datetimepicker('created_at'),
|
||||
];
|
||||
}
|
||||
|
||||
public function actions(User $row): array
|
||||
{
|
||||
return [
|
||||
Button::add('edit')
|
||||
->slot('編輯')
|
||||
->icon('solid-pencil-square')
|
||||
->class('inline-flex items-center gap-1 px-3 py-1 rounded ')
|
||||
->openModal('admin.edit-user-modal', ['userId' => $row->id]),
|
||||
Button::add('delete')
|
||||
->slot('刪除')
|
||||
->icon('solid-trash')
|
||||
->class('inline-flex items-center gap-1 px-3 py-1 rounded ')
|
||||
->confirmPrompt('確定要刪除這位使用者嗎?|DELETE', 'DELETE') // 使用 'DELETE' 作為標識符
|
||||
->dispatch('delete-user', ['userId' => $row->id]),
|
||||
];
|
||||
}
|
||||
#[On('bulkDelete.{tableName}')]
|
||||
public function bulkDelete(): void
|
||||
{
|
||||
$this->js('alert(window.pgBulkActions.get(\'' . $this->tableName . '\'))');
|
||||
if($this->checkboxValues){
|
||||
User::destroy($this->checkboxValues);
|
||||
$this->js('window.pgBulkActions.clearAll()'); // clear the count on the interface.
|
||||
}
|
||||
}
|
||||
|
||||
#[\Livewire\Attributes\On('delete-user')]
|
||||
public function deleteUser($userId): void
|
||||
{
|
||||
User::findOrFail($userId)->delete();
|
||||
|
||||
$this->dispatch('notify', '刪除成功');
|
||||
}
|
||||
|
||||
/* public function actionRules($row): array
|
||||
{
|
||||
return [
|
||||
// Hide button edit for ID 1
|
||||
Rule::button('edit')
|
||||
->when(fn($row) => $row->id === 1)
|
||||
->hide(),
|
||||
];
|
||||
} */
|
||||
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Admin;
|
||||
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
use App\Models\User;
|
||||
use Spatie\Permission\Models\Role;
|
||||
|
||||
class Users extends Component
|
||||
{
|
||||
use WithPagination;
|
||||
|
||||
|
||||
public $search = '';
|
||||
public $name = '';
|
||||
public bool $showCreateModal = false;
|
||||
public ?int $editingUserId = null;
|
||||
public string $sortField = 'id';
|
||||
public string $sortDirection = 'asc';
|
||||
public $roles = []; // 所有權限清單
|
||||
public $selectedRoles = []; // 表單中選到的權限
|
||||
|
||||
protected $rules = [
|
||||
'name' => 'required|string|max:255',
|
||||
];
|
||||
|
||||
protected $paginationTheme = 'tailwind';
|
||||
|
||||
public function getUsersProperty()
|
||||
{
|
||||
return User::where('name', 'like', "%{$this->search}%")
|
||||
->orderBy($this->sortField, $this->sortDirection)
|
||||
->paginate(10);
|
||||
}
|
||||
|
||||
public function sortBy($field)
|
||||
{
|
||||
if ($this->sortField === $field) {
|
||||
$this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc';
|
||||
} else {
|
||||
$this->sortField = $field;
|
||||
$this->sortDirection = 'asc';
|
||||
}
|
||||
}
|
||||
public function mount()
|
||||
{
|
||||
$this->roles = Role::all();
|
||||
}
|
||||
|
||||
public function openCreateModal()
|
||||
{
|
||||
$this->resetFields();
|
||||
$this->showCreateModal = true;
|
||||
}
|
||||
|
||||
public function openEditModal($id)
|
||||
{
|
||||
$user = User::findOrFail($id);
|
||||
$this->editingUserId = $user->id;
|
||||
$this->name = $user->name;
|
||||
$this->selectedRoles = $user->roles()->pluck('id')->toArray();
|
||||
$this->showCreateModal = true;
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
if ($this->editingRoleId) {
|
||||
$role = User::findOrFail($this->editingRoleId);
|
||||
$role->update(['name' => $this->name]);
|
||||
$role->syncRolses($this->selectedRoles);
|
||||
session()->flash('message', '使用者已更新');
|
||||
} else {
|
||||
$role = User::create(['name' => $this->name]);
|
||||
$role->syncRolses($this->selectedRoles);
|
||||
session()->flash('message', '使用者已新增');
|
||||
}
|
||||
|
||||
$this->resetFields();
|
||||
$this->showCreateModal = false;
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
User::findOrFail($id)->delete();
|
||||
session()->flash('message', '使用者已刪除');
|
||||
}
|
||||
|
||||
public function resetFields()
|
||||
{
|
||||
$this->name = '';
|
||||
$this->selectedRoles = [];
|
||||
$this->editingUserId = null;
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.admin.users', [
|
||||
'users' => $this->users,
|
||||
])->layout('layouts.admin');
|
||||
}
|
||||
}
|
16
resources/views/livewire/admin/edit-user-modal.blade.php
Normal file
16
resources/views/livewire/admin/edit-user-modal.blade.php
Normal file
@ -0,0 +1,16 @@
|
||||
<div class="p-6 space-y-4">
|
||||
<h2 class="text-xl font-semibold">編輯使用者</h2>
|
||||
|
||||
<div>
|
||||
<x-wireui:input label="名稱" wire:model.defer="name" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<x-wireui:input label="Email" type="email" wire:model.defer="email" />
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end gap-2 mt-4">
|
||||
<x-wireui:button flat label="取消" wire:click="closeModal" />
|
||||
<x-wireui:button primary label="儲存" wire:click="save" />
|
||||
</div>
|
||||
</div>
|
@ -1,65 +1,20 @@
|
||||
<div class="space-y-4">
|
||||
<div class="flex justify-between items-center">
|
||||
<h2 class="text-xl font-bold">{{ __('users.list') }}</h2>
|
||||
<x-button primary label="{{__('users.CreateNewRole')}}" wire:click="openCreateModal" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<x-input wire:model.debounce.300ms="search" placeholder="搜尋使用者名稱..." class="w-64" />
|
||||
</div>
|
||||
|
||||
|
||||
<x-table divider="thin" has_shadow="true" celled="true">
|
||||
<x-slot name="header">
|
||||
<th class="cursor-pointer" wire:click="sortBy('id')">{{__('users.no')}}</th>
|
||||
<th class="cursor-pointer" wire:click="sortBy('name')">{{__('users.name')}}</th>
|
||||
<th>{{__('users.action')}}</th>
|
||||
</x-slot>
|
||||
@forelse ($users as $user)
|
||||
<tr>
|
||||
<td>{{ $user->id }}</td>
|
||||
<td>{{ $user->name }}</td>
|
||||
<td class="space-x-2">
|
||||
@can('role-edit')
|
||||
<x-button flat label="{{ __('users.edit') }}" color="yellow" icon="pencil-square" wire:click="openEditModal({{ $user->id }})" />
|
||||
@endcan
|
||||
@can('role-delete')
|
||||
<x-button flat label="{{ __('users.delete') }}" color="red" icon="trash" wire:click="delete({{ $user->id }})" />
|
||||
@endcan
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="3">{{ __('No users found.') }}</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</x-table>
|
||||
<x-layouts.admin>
|
||||
<x-slot name="header">
|
||||
使用者管理
|
||||
</x-slot>
|
||||
|
||||
<div class="mt-4">
|
||||
{!! $users->links('pagination::tailwind') !!}
|
||||
</div>
|
||||
|
||||
@if ($showCreateModal)
|
||||
<x-modal-card title="{{ $editingUserId ? '編輯使用者' : '新增使用者' }}" blur wire:model.defer="showCreateModal">
|
||||
<div class="space-y-4">
|
||||
<x-input label="使用者名稱" wire:model.defer="name" />
|
||||
|
||||
<x-select
|
||||
label="角色"
|
||||
wire:model.defer="selectedRoles"
|
||||
placeholder="選擇角色"
|
||||
option-label="label"
|
||||
option-value="value"
|
||||
:options="$roles->map(fn($p) => ['value' => $p->id, 'label' => $p->name])->toArray()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<x-slot name="footer">
|
||||
<div class="flex justify-center gap-2">
|
||||
<x-button primary label="{{__('users.cancel')}}" x-on:click="$dispatch('close')" />
|
||||
<x-button primary label="{{__('users.submit')}}" wire:click="save" />
|
||||
</div>
|
||||
</x-slot>
|
||||
</x-modal-card>
|
||||
@if (session()->has('message'))
|
||||
<x-wireui:notifications />
|
||||
<script>
|
||||
window.$wireui.notify({
|
||||
title: '提示',
|
||||
description: '{{ session('message') }}',
|
||||
icon: 'success'
|
||||
});
|
||||
</script>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- 單一 Livewire 元件,內含資料表與 Modal --}}
|
||||
<livewire:admin.user-table />
|
||||
</x-layouts.admin>
|
@ -4,7 +4,7 @@ use Illuminate\Support\Facades\Route;
|
||||
|
||||
use App\Livewire\Admin\Dashboard as AdminDashboard;
|
||||
use App\Livewire\Admin\Roles;
|
||||
use App\Livewire\Admin\Users;
|
||||
use App\Livewire\Admin\UserTable;
|
||||
|
||||
Route::view('/', 'welcome');
|
||||
|
||||
@ -19,7 +19,11 @@ Route::view('profile', 'profile')
|
||||
require __DIR__.'/auth.php';
|
||||
|
||||
Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function () {
|
||||
Route::get('/users', function () {
|
||||
return view('livewire.admin.users');
|
||||
})->name('users');
|
||||
Route::get('/dashboard', AdminDashboard::class)->name('dashboard');
|
||||
Route::get('/roles', Roles::class)->name('roles');
|
||||
Route::get('/users', Users::class)->name('users');
|
||||
//Route::get('/users', Users::class)->name('users');
|
||||
Route::get('/users-table', UserTable::class)->name('users-table');
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user