歌手列表 20250425

This commit is contained in:
allen.yan 2025-04-25 11:34:45 +08:00
parent 382a8b4efb
commit d7240465af
6 changed files with 135 additions and 130 deletions

View File

@ -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');

View File

@ -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]), */
]; ];
} }

View File

@ -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,
]);
}
}

View File

@ -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;

View File

@ -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' => [

View File

@ -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>