歌手列表 20250425
This commit is contained in:
parent
382a8b4efb
commit
d7240465af
@ -4,8 +4,82 @@ namespace App\Livewire\Admin;
|
|||||||
|
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
|
use App\Models\Artist;
|
||||||
|
use App\Models\ArtistCategory;
|
||||||
|
|
||||||
class ArtistForm extends Component
|
class ArtistForm extends Component
|
||||||
{
|
{
|
||||||
|
protected $listeners = ['openCreateArtistModal','openEditArtistModal', 'deleteArtist','bulkDeleteArtist'];
|
||||||
|
|
||||||
|
public bool $showCreateModal = false;
|
||||||
|
public ?int $artistId = null;
|
||||||
|
public $name;
|
||||||
|
public $artistCategory = []; // 所有類別清單
|
||||||
|
public $selectedCategory = []; // 表單中選到的權限
|
||||||
|
|
||||||
|
protected $rules = [
|
||||||
|
'name' => 'required|string|max:255',
|
||||||
|
'selectedCategory' => 'required|array',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
$this->artistCategory = ArtistCategory::all();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function openCreateArtistModal()
|
||||||
|
{
|
||||||
|
$this->resetFields();
|
||||||
|
$this->showCreateModal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function openEditArtistModal($id)
|
||||||
|
{
|
||||||
|
$artist = Artist::findOrFail($id);
|
||||||
|
$this->artistId = $artist->id;
|
||||||
|
$this->name = $artist->name;
|
||||||
|
$this->selectedCategory = $artist->category_id;
|
||||||
|
$this->showCreateModal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$this->validate();
|
||||||
|
|
||||||
|
if ($this->artistId) {
|
||||||
|
$role = Artist::findOrFail($this->artistId);
|
||||||
|
$role->update([
|
||||||
|
'category_id' => $this->selectedCategory,
|
||||||
|
'name' => $this->name,
|
||||||
|
]);
|
||||||
|
|
||||||
|
session()->flash('message', '使用者已更新');
|
||||||
|
} else {
|
||||||
|
$role = Artist::create([
|
||||||
|
'category_id' => $this->selectedCategory,
|
||||||
|
'name' => $this->name,
|
||||||
|
]);
|
||||||
|
|
||||||
|
session()->flash('message', '使用者已新增');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->resetFields();
|
||||||
|
$this->showCreateModal = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteArtist($id)
|
||||||
|
{
|
||||||
|
Artist::findOrFail($id)->delete();
|
||||||
|
session()->flash('message', '使用者已刪除');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resetFields()
|
||||||
|
{
|
||||||
|
$this->name = '';
|
||||||
|
$this->selectedCategory = [];
|
||||||
|
$this->artistId = null;
|
||||||
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
return view('livewire.admin.artist-form');
|
return view('livewire.admin.artist-form');
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Livewire\Admin;
|
namespace App\Livewire\Admin;
|
||||||
|
|
||||||
use App\Models\Artist;
|
use App\Models\Artist;
|
||||||
|
use App\Models\ArtistCategory;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use PowerComponents\LivewirePowerGrid\Button;
|
use PowerComponents\LivewirePowerGrid\Button;
|
||||||
@ -20,6 +21,9 @@ final class ArtistTable extends PowerGridComponent
|
|||||||
{
|
{
|
||||||
public string $tableName = 'artist-table';
|
public string $tableName = 'artist-table';
|
||||||
|
|
||||||
|
//public bool $deferLoading = true;
|
||||||
|
//public string $loadingComponent = 'components.power-grid-loading';
|
||||||
|
|
||||||
public bool $showFilters = false;
|
public bool $showFilters = false;
|
||||||
|
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
@ -29,15 +33,17 @@ final class ArtistTable extends PowerGridComponent
|
|||||||
|
|
||||||
public function setUp(): array
|
public function setUp(): array
|
||||||
{
|
{
|
||||||
$this->showCheckBox();
|
//$this->showCheckBox();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
PowerGrid::exportable(fileName: 'artist-file')
|
//PowerGrid::exportable(fileName: 'artist-file')
|
||||||
->type(Exportable::TYPE_XLS, Exportable::TYPE_CSV),
|
// ->type(Exportable::TYPE_XLS, Exportable::TYPE_CSV),
|
||||||
PowerGrid::header()
|
PowerGrid::header()
|
||||||
->showSoftDeletes()
|
->withoutLoading()
|
||||||
->showToggleColumns()
|
->showToggleColumns()
|
||||||
->showSearchInput(),
|
//->showSoftDeletes()
|
||||||
|
//->showSearchInput()
|
||||||
|
,
|
||||||
PowerGrid::footer()
|
PowerGrid::footer()
|
||||||
->showPerPage()
|
->showPerPage()
|
||||||
->showRecordCount(),
|
->showRecordCount(),
|
||||||
@ -46,48 +52,51 @@ final class ArtistTable extends PowerGridComponent
|
|||||||
public function header(): array
|
public function header(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
Button::add('bulk-delete')
|
/* Button::add('bulk-delete')
|
||||||
->slot('Bulk delete (<span x-text="window.pgBulkActions.count(\'' . $this->tableName . '\')"></span>)')
|
->slot('Bulk delete (<span x-text="window.pgBulkActions.count(\'' . $this->tableName . '\')"></span>)')
|
||||||
->icon('solid-trash',['id' => 'my-custom-icon-id', 'class' => 'font-bold'])
|
->icon('solid-trash',['id' => 'my-custom-icon-id', 'class' => 'font-bold'])
|
||||||
->class('inline-flex items-center gap-1 px-3 py-1 rounded ')
|
->class('inline-flex items-center gap-1 px-3 py-1 rounded ')
|
||||||
->dispatch('bulkDelete.' . $this->tableName, []),
|
->dispat ch('bulkDelete.' . $this->tableName, []),*/
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function datasource(): Builder
|
public function datasource(): Builder
|
||||||
{
|
{
|
||||||
return Artist::query();
|
return Artist::query()->with('category');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function relationSearch(): array
|
public function relationSearch(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [
|
||||||
|
'category' => ['name'],
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fields(): PowerGridFields
|
public function fields(): PowerGridFields
|
||||||
{
|
{
|
||||||
return PowerGrid::fields()
|
return PowerGrid::fields()
|
||||||
->add('id')
|
->add('id')
|
||||||
->add('category_id')
|
->add('category_name', fn (Artist $model) => optional($model->category)->name)
|
||||||
->add('name')
|
->add('name')
|
||||||
->add('simplified')
|
->add('simplified')
|
||||||
->add('phonetic_abbr')
|
->add('phonetic_abbr')
|
||||||
->add('pinyin_abbr')
|
->add('pinyin_abbr')
|
||||||
->add('created_at_formatted', fn (Artist $model) => Carbon::parse($model->created_at)->format('d/m/Y H:i:s'));
|
->add('created_at_formatted', fn (Artist $model) => Carbon::parse($model->created_at)->format('Y-m-d H:i:s'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function columns(): array
|
public function columns(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
Column::make(__('artists.no'), 'id'),
|
Column::make(__('artists.no'), 'id'),
|
||||||
Column::make(__('artists.category'), 'category_id'),
|
Column::make(__('artists.category'),'category_name', 'category.name')->searchable(),
|
||||||
Column::make(__('artists.name'), 'name')
|
Column::make(__('artists.name'), 'name')
|
||||||
->sortable()
|
->sortable()
|
||||||
->searchable(),
|
->searchable(),
|
||||||
|
|
||||||
Column::make(__('artists.name.simplified'), 'simplified')
|
Column::make(__('artists.name.simplified'), 'simplified')
|
||||||
->sortable()
|
->sortable()
|
||||||
->searchable(),
|
->searchable()
|
||||||
|
->hidden(true, false),
|
||||||
|
|
||||||
Column::make(__('artists.name.phinetic'), 'phonetic_abbr')
|
Column::make(__('artists.name.phinetic'), 'phonetic_abbr')
|
||||||
->sortable()
|
->sortable()
|
||||||
@ -98,7 +107,8 @@ final class ArtistTable extends PowerGridComponent
|
|||||||
->searchable(),
|
->searchable(),
|
||||||
|
|
||||||
Column::make('Created at', 'created_at_formatted', 'created_at')
|
Column::make('Created at', 'created_at_formatted', 'created_at')
|
||||||
->sortable(),
|
->sortable()
|
||||||
|
->hidden(true, false),
|
||||||
|
|
||||||
Column::action(__('artists.actions'))
|
Column::action(__('artists.actions'))
|
||||||
];
|
];
|
||||||
@ -107,6 +117,10 @@ final class ArtistTable extends PowerGridComponent
|
|||||||
public function filters(): array
|
public function filters(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
Filter::select('category_name', 'category_id')
|
||||||
|
->dataSource(ArtistCategory::all())
|
||||||
|
->optionValue('id')
|
||||||
|
->optionLabel('name'),
|
||||||
Filter::inputText('name')->placeholder(__('artists.name')),
|
Filter::inputText('name')->placeholder(__('artists.name')),
|
||||||
Filter::inputText('phonetic_abbr')->placeholder(__('artists.name.phinetic')),
|
Filter::inputText('phonetic_abbr')->placeholder(__('artists.name.phinetic')),
|
||||||
Filter::inputText('pinyin_abbr')->placeholder(__('artists.name.pinyin')),
|
Filter::inputText('pinyin_abbr')->placeholder(__('artists.name.pinyin')),
|
||||||
@ -114,7 +128,7 @@ final class ArtistTable extends PowerGridComponent
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
#[On('bulkDelete.{tableName}')]
|
/* #[On('bulkDelete.{tableName}')]
|
||||||
public function bulkDelete(): void
|
public function bulkDelete(): void
|
||||||
{
|
{
|
||||||
$this->js('alert(window.pgBulkActions.get(\'' . $this->tableName . '\'))');
|
$this->js('alert(window.pgBulkActions.get(\'' . $this->tableName . '\'))');
|
||||||
@ -122,7 +136,7 @@ final class ArtistTable extends PowerGridComponent
|
|||||||
Artist::destroy($this->checkboxValues);
|
Artist::destroy($this->checkboxValues);
|
||||||
$this->js('window.pgBulkActions.clearAll()'); // clear the count on the interface.
|
$this->js('window.pgBulkActions.clearAll()'); // clear the count on the interface.
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
public function actions(Artist $row): array
|
public function actions(Artist $row): array
|
||||||
{
|
{
|
||||||
@ -133,11 +147,11 @@ final class ArtistTable extends PowerGridComponent
|
|||||||
->icon('solid-pencil-square')
|
->icon('solid-pencil-square')
|
||||||
->class('inline-flex items-center gap-1 px-3 py-1 rounded ')
|
->class('inline-flex items-center gap-1 px-3 py-1 rounded ')
|
||||||
->dispatchTo('admin.artist-form', 'openEditArtistModal', ['id' => $row->id]),
|
->dispatchTo('admin.artist-form', 'openEditArtistModal', ['id' => $row->id]),
|
||||||
Button::add('delete')
|
/* Button::add('delete')
|
||||||
->slot(__('artists.delete'))
|
->slot(__('artists.delete'))
|
||||||
->icon('solid-trash')
|
->icon('solid-trash')
|
||||||
->class('inline-flex items-center gap-1 px-3 py-1 rounded ')
|
->class('inline-flex items-center gap-1 px-3 py-1 rounded ')
|
||||||
->dispatchTo('admin.artist-form', 'deleteArtist', ['id' => $row->id]),
|
->dispatchTo('admin.artist-form', 'deleteArtist', ['id' => $row->id]), */
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Livewire\Admin;
|
|
||||||
|
|
||||||
use Livewire\Component;
|
|
||||||
use Livewire\WithPagination;
|
|
||||||
use Spatie\Permission\Models\Role;
|
|
||||||
use Spatie\Permission\Models\Permission;
|
|
||||||
|
|
||||||
class Roles extends Component
|
|
||||||
{
|
|
||||||
use WithPagination;
|
|
||||||
|
|
||||||
public $users ;
|
|
||||||
public $search = '';
|
|
||||||
public $name = '';
|
|
||||||
public bool $showCreateModal = false;
|
|
||||||
public ?int $editingRoleId = null;
|
|
||||||
public string $sortField = 'id';
|
|
||||||
public string $sortDirection = 'asc';
|
|
||||||
public $permissions = []; // 所有權限清單
|
|
||||||
public $selectedPermissions = []; // 表單中選到的權限
|
|
||||||
|
|
||||||
protected $rules = [
|
|
||||||
'name' => 'required|string|max:255',
|
|
||||||
];
|
|
||||||
|
|
||||||
protected $paginationTheme = 'tailwind';
|
|
||||||
|
|
||||||
public function getRolesProperty()
|
|
||||||
{
|
|
||||||
return Role::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->permissions = Permission::all();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function openCreateModal()
|
|
||||||
{
|
|
||||||
$this->resetFields();
|
|
||||||
$this->showCreateModal = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function openEditModal($id)
|
|
||||||
{
|
|
||||||
$role = Role::findOrFail($id);
|
|
||||||
$this->editingRoleId = $role->id;
|
|
||||||
$this->name = $role->name;
|
|
||||||
$this->selectedPermissions = $role->permissions()->pluck('id')->toArray();
|
|
||||||
$this->showCreateModal = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function save()
|
|
||||||
{
|
|
||||||
$this->validate();
|
|
||||||
|
|
||||||
if ($this->editingRoleId) {
|
|
||||||
$role = Role::findOrFail($this->editingRoleId);
|
|
||||||
$role->update(['name' => $this->name]);
|
|
||||||
$role->syncPermissions($this->selectedPermissions);
|
|
||||||
session()->flash('message', '角色已更新');
|
|
||||||
} else {
|
|
||||||
$role = Role::create(['name' => $this->name]);
|
|
||||||
$role->syncPermissions($this->selectedPermissions);
|
|
||||||
session()->flash('message', '角色已新增');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->resetFields();
|
|
||||||
$this->showCreateModal = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function delete($id)
|
|
||||||
{
|
|
||||||
Role::findOrFail($id)->delete();
|
|
||||||
session()->flash('message', '角色已刪除');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function resetFields()
|
|
||||||
{
|
|
||||||
$this->name = '';
|
|
||||||
$this->selectedPermissions = [];
|
|
||||||
$this->editingRoleId = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render()
|
|
||||||
{
|
|
||||||
return view('livewire.admin.roles', [
|
|
||||||
'roles' => $this->roles,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,7 +9,7 @@ use Spatie\Permission\Models\Role;
|
|||||||
|
|
||||||
class UserForm extends Component
|
class UserForm extends Component
|
||||||
{
|
{
|
||||||
protected $listeners = ['openCreateUserModal','openEditUserModal', 'deleteUser','bulkDeleteUser'];
|
protected $listeners = ['openCreateUserModal','openEditUserModal', 'deleteUser'];
|
||||||
|
|
||||||
public bool $showCreateModal = false;
|
public bool $showCreateModal = false;
|
||||||
public ?int $userId = null;
|
public ?int $userId = null;
|
||||||
|
@ -19,10 +19,10 @@ return [
|
|||||||
'select' => '選擇時段',
|
'select' => '選擇時段',
|
||||||
],
|
],
|
||||||
'pagination' => [
|
'pagination' => [
|
||||||
'showing' => 'Showing',
|
'showing' => '顯示',
|
||||||
'to' => 'to',
|
'to' => '到',
|
||||||
'of' => 'of',
|
'of' => '共',
|
||||||
'results' => 'Results',
|
'results' => '筆.',
|
||||||
'all' => '全部',
|
'all' => '全部',
|
||||||
],
|
],
|
||||||
'multi_select' => [
|
'multi_select' => [
|
||||||
|
@ -1,3 +1,24 @@
|
|||||||
<div>
|
<div class="p-6 space-y-4">
|
||||||
{{-- A good traveler has no fixed plans and is not intent upon arriving. --}}
|
@if ($showCreateModal)
|
||||||
</div>
|
<x-wireui:modal-card title="{{ $artistId ? '編輯歌手' : '新增歌手' }}" blur wire:model.defer="showCreateModal">
|
||||||
|
<div class="space-y-4">
|
||||||
|
<x-wireui:select
|
||||||
|
label="類別"
|
||||||
|
wire:model.defer="selectedCategory"
|
||||||
|
placeholder="選擇類別"
|
||||||
|
option-label="label"
|
||||||
|
option-value="value"
|
||||||
|
:options="$artistCategory->map(fn($p) => ['value' => $p->id, 'label' => $p->name])->toArray()"
|
||||||
|
/>
|
||||||
|
<x-wireui:input label="名稱" wire:model.defer="name" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<x-slot name="footer">
|
||||||
|
<div class="flex justify-center gap-2">
|
||||||
|
<x-wireui:button primary label="{{__('artists.cancel')}}" x-on:click="$dispatch('close')" />
|
||||||
|
<x-wireui:button primary label="{{__('artists.submit')}}" wire:click="save" />
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
||||||
|
</x-wireui:modal-card>
|
||||||
|
@endif
|
||||||
|
</div>
|
Loading…
x
Reference in New Issue
Block a user