From 2769e82a374f24c2f9f5a7c48ccc1037fb54c1bc Mon Sep 17 00:00:00 2001 From: "allen.yan" Date: Tue, 29 Jul 2025 00:24:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E8=AA=BF=E6=95=B4=20API=20?= =?UTF-8?q?=E6=94=B6=E5=88=B0=E5=8C=85=E5=BB=82=E6=8C=87=E4=BB=A4=E5=85=88?= =?UTF-8?q?=E6=8A=BC=E8=B3=87=E6=96=99=20=E5=8A=A0=E5=85=A5=20=E5=8C=85?= =?UTF-8?q?=E5=BB=82=E5=88=97=E8=A1=A8=20=E5=8A=A0=E5=85=A5=20=E5=8C=85?= =?UTF-8?q?=E5=BB=82=E6=8E=A7=E5=88=B6=E4=BB=8B=E9=9D=A2=20=E5=8A=A0?= =?UTF-8?q?=E5=85=A5=20=E5=8C=85=E5=BB=82=E8=A8=98=E9=8C=84=20=E8=A3=9C?= =?UTF-8?q?=E4=B8=8A=E6=AD=A3=E8=A6=8F=E5=8A=83=2020250729?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Enums/RoomType.php | 2 +- .../Controllers/RoomControlController.php | 25 +- app/Livewire/Forms/ArtistForm.php | 11 + app/Livewire/Forms/BranchForm.php | 11 +- app/Livewire/Forms/RoomForm.php | 125 +++++++++ app/Livewire/Forms/SongForm.php | 31 ++- app/Livewire/Forms/TextAdsForm.php | 12 +- app/Livewire/Forms/UserForm.php | 24 +- app/Livewire/Grids/RoomGrid.php | 39 ++- app/Livewire/Tables/ArtistTable.php | 6 +- app/Livewire/Tables/BranchTable.php | 9 +- app/Livewire/Tables/RoomStatusLogTable.php | 82 ++++++ app/Livewire/Tables/RoomTable.php | 263 ++++++++++++++++++ app/Livewire/Tables/SongTable.php | 8 +- app/Livewire/Tables/TextAdsTable.php | 6 +- app/Livewire/Tables/UserTable.php | 8 +- app/View/Components/SelectCategory.php | 27 -- app/View/Components/SelectDropdown.php | 35 +++ database/.DS_Store | Bin 6148 -> 6148 bytes resources/lang/zh-tw/activity-log.php | 5 + resources/lang/zh-tw/room-status-log.php | 13 + resources/lang/zh-tw/rooms.php | 29 ++ .../components/admin/branch-select.blade.php | 11 + .../components/admin/section-header.blade.php | 6 +- ...ry.blade.php => select-dropdown.blade.php} | 4 +- .../views/livewire/admin/branches.blade.php | 1 - .../views/livewire/admin/room-grids.blade.php | 4 + .../livewire/admin/room-status-log.blade.php | 3 + .../views/livewire/admin/rooms.blade.php | 7 + .../forms/headers/room-status-log.blade.php | 2 + .../livewire/forms/headers/room.blade.php | 10 + .../views/livewire/forms/room-form.blade.php | 21 ++ .../views/livewire/grids/room-grid.blade.php | 117 ++++---- .../livewire/layout/admin/sidebar.blade.php | 3 + routes/web.php | 2 + 35 files changed, 812 insertions(+), 150 deletions(-) create mode 100644 app/Livewire/Forms/RoomForm.php create mode 100644 app/Livewire/Tables/RoomStatusLogTable.php create mode 100644 app/Livewire/Tables/RoomTable.php delete mode 100644 app/View/Components/SelectCategory.php create mode 100644 app/View/Components/SelectDropdown.php create mode 100644 resources/lang/zh-tw/activity-log.php create mode 100644 resources/lang/zh-tw/room-status-log.php create mode 100644 resources/lang/zh-tw/rooms.php create mode 100644 resources/views/components/admin/branch-select.blade.php rename resources/views/components/{select-category.blade.php => select-dropdown.blade.php} (66%) create mode 100644 resources/views/livewire/admin/room-grids.blade.php create mode 100644 resources/views/livewire/admin/room-status-log.blade.php create mode 100644 resources/views/livewire/admin/rooms.blade.php create mode 100644 resources/views/livewire/forms/headers/room-status-log.blade.php create mode 100644 resources/views/livewire/forms/headers/room.blade.php create mode 100644 resources/views/livewire/forms/room-form.blade.php diff --git a/app/Enums/RoomType.php b/app/Enums/RoomType.php index e311fea..9e54578 100644 --- a/app/Enums/RoomType.php +++ b/app/Enums/RoomType.php @@ -23,7 +23,7 @@ enum RoomType: string { public function labels(): string { return match($this) { - self::Unset => __('enums.room.status.Unset'), + self::Unset => __('enums.Unset'), self::PC => "PC", self::SVR => "SVR", }; diff --git a/app/Http/Controllers/RoomControlController.php b/app/Http/Controllers/RoomControlController.php index c280637..84bd146 100644 --- a/app/Http/Controllers/RoomControlController.php +++ b/app/Http/Controllers/RoomControlController.php @@ -80,8 +80,30 @@ class RoomControlController extends Controller if (empty($branch->external_ip) ) { return ApiResponse::error('分店未設定 外部URL'); } + $roomType = null; + $roomName = null; + // 從 room_name(例如 PC101, SVR01)中擷取 type 與 name + if (preg_match('/^([A-Za-z]+)(\d+)$/', $validated['room_name'], $matches)) { + $roomType = strtolower($matches[1]); // 'PC' → 'pc' + $roomName = $matches[2]; // '101' + } + $room = Room::where([ + 'branch_id' => $branch->id, + 'name' => $roomName, + 'type' => $roomType + ])->first(); + if (!$room) { + return ApiResponse::error('包廂不存在'); + } $command = $validated['command']; + + $room->update([ + 'status' => $command, + 'started_at' => $validated['started_at'] ?? null, + 'ended_at' => $validated['ended_at'] ?? null, + ]); + $payload = [ 'branch_name' => $validated['branch_name'], 'room_name' => $validated['room_name'], @@ -89,8 +111,7 @@ class RoomControlController extends Controller 'started_at' => $validated['started_at'] ?? null, 'ended_at' => $validated['ended_at'] ?? null, ]; - $user = \App\Models\User::find(2); - $token = $user->api_plain_token; + $token = \App\Models\User::find(2)->api_plain_token; $api = new \App\Services\ApiClient($branch->external_ip,$token); $response = $api->post('/api/room/sendSwitch', $payload); diff --git a/app/Livewire/Forms/ArtistForm.php b/app/Livewire/Forms/ArtistForm.php index 3bd5847..2a6a8fd 100644 --- a/app/Livewire/Forms/ArtistForm.php +++ b/app/Livewire/Forms/ArtistForm.php @@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Auth; use Livewire\Component; use WireUi\Traits\WireUiActions; +use Illuminate\Validation\Rules\Enum; use App\Models\Artist; use App\Enums\ArtistCategory; @@ -30,6 +31,15 @@ class ArtistForm extends Component 'name' =>'', 'enable' => true, ]; + + public function rules() + { + return [ + 'fields.category' => ['required', new Enum(ArtistCategory::class)], + 'fields.name' => 'required|string|max:255', + 'fields.enable' => 'required|boolean', + ]; + } public $selectedCategory = []; // 表單中選到的權限 @@ -66,6 +76,7 @@ class ArtistForm extends Component public function save() { + $validated = $this->validate($this->rules()); if ($this->artistId) { if ($this->canEdit) { $artist = Artist::findOrFail($this->artistId); diff --git a/app/Livewire/Forms/BranchForm.php b/app/Livewire/Forms/BranchForm.php index b419e72..13868fe 100644 --- a/app/Livewire/Forms/BranchForm.php +++ b/app/Livewire/Forms/BranchForm.php @@ -31,7 +31,15 @@ class BranchForm extends Component 'enable' => true, 'roomNotes' =>'' ]; - + public function rules() + { + return [ + 'fields.name' => 'required|string|max:255', + 'fields.external_ip' => 'required|string|max:255', + 'fields.enable' => 'required|boolean', // 或 new Enum(...) 如果你用了 Enum + 'fields.roomNotes' => 'nullable|string', + ]; + } public function mount() { @@ -61,6 +69,7 @@ class BranchForm extends Component public function save() { + $validated = $this->validate($this->rules()); if ($this->branchId) { if ($this->canEdit) { $branch = Branch::findOrFail($this->branchId); diff --git a/app/Livewire/Forms/RoomForm.php b/app/Livewire/Forms/RoomForm.php new file mode 100644 index 0000000..f6307aa --- /dev/null +++ b/app/Livewire/Forms/RoomForm.php @@ -0,0 +1,125 @@ +'', + 'type' =>'', + 'name' =>'' + ]; + + + public function mount() + { + $this->typeOptions = collect(RoomType::cases())->map(fn ($type) => [ + 'name' => $type->labels(), + 'value' => $type->value, + ])->toArray(); + $this->canCreate = Auth::user()?->can('room-edit') ?? false; + $this->canEdit = Auth::user()?->can('room-edit') ?? false; + $this->canDelect = Auth::user()?->can('room-delete') ?? false; + } + + public function openModal($id = null) + { + $this->resetFields(); + + if ($id) { + $room = Room::findOrFail($id); + $this->roomId = $room->id; + $this->fields = $room->only(array_keys($this->fields)); + } + + $this->showModal = true; + } + + public function closeModal() + { + $this->resetFields(); + $this->showModal = false; + } + + public function save() + { + $description ="無權修改"; + if ($this->roomId) { + if ($this->canEdit) { + $room = Room::findOrFail($this->roomId); + $room->update($this->fields); + $description='分店已更新'; + } + } else { + if ($this->canCreate) { + $room = Room::create([ + 'floor' => $this->fields['floor'], + 'type' => $this->fields['type'], + 'name' => $this->fields['name'], + ]); + $description='分店已新增'; + } + } + $this->notification()->send([ + 'icon' => 'success', + 'title' => '成功', + 'description' => $description, + ]); + $this->resetFields(); + $this->showModal = false; + $this->dispatch('pg:eventRefresh-room-table'); + } + + public function deleteBranch($id) + { + if ($this->canDelect) { + Room::findOrFail($id)->delete(); + $this->notification()->send([ + 'icon' => 'success', + 'title' => '成功', + 'description' => '分店已刪除', + ]); + + $this->dispatch('pg:eventRefresh-room-table'); + } + } + + public function resetFields() + { + foreach ($this->fields as $key => $value) { + if ($key == 'enable') { + $this->fields[$key] = true; + } else { + $this->fields[$key] = ''; + } + } + $this->branchId = null; + } + + public function render() + { + return view('livewire.forms.room-form'); + } +} diff --git a/app/Livewire/Forms/SongForm.php b/app/Livewire/Forms/SongForm.php index 41818bb..a8f92bd 100644 --- a/app/Livewire/Forms/SongForm.php +++ b/app/Livewire/Forms/SongForm.php @@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Auth; use Livewire\Component; use WireUi\Traits\WireUiActions; +use Illuminate\Validation\Rules\Enum; use App\Enums\SongLanguageType; use App\Enums\SongSituation; use App\Models\Song; @@ -52,10 +53,30 @@ class SongForm extends Component ]; - //protected $rules = [ - // 'name' => 'required|string|max:255', - // - //]; + public function rules() + { + return [ + 'fields.name' => 'required|string|max:255', + 'fields.adddate' => 'required|date', // 或 required, 依照你的需求 + 'fields.filename' => 'required|string|max:255', + 'fields.language_type'=> ['required',new Enum(SongLanguageType::class)], + 'fields.vocal' => 'required|boolean', + 'fields.situation' => ['required',new Enum(SongSituation::class)], + 'fields.copyright01' => 'nullable|string|max:255', + 'fields.copyright02' => 'nullable|string|max:255', + 'fields.note01' => 'nullable|string|max:255', + 'fields.note02' => 'nullable|string|max:255', + 'fields.note03' => 'nullable|string|max:255', + 'fields.note04' => 'nullable|string|max:255', + 'fields.enable' => 'required|boolean', + + // 如果你在表單中也綁定了 selectedArtists / selectedCategories: + 'selectedArtists' => 'required|array', + 'selectedArtists.*' => 'integer|exists:artists,id', + 'selectedCategories' => 'nullable|array', + 'selectedCategories.*'=> 'integer|exists:categories,id', + ]; + } public function mount() { @@ -95,7 +116,7 @@ class SongForm extends Component public function save() { - //$this->validate(); + $validated = $this->validate($this->rules()); if ($this->songId) { if ($this->canEdit) { diff --git a/app/Livewire/Forms/TextAdsForm.php b/app/Livewire/Forms/TextAdsForm.php index ee95bbd..319efe7 100644 --- a/app/Livewire/Forms/TextAdsForm.php +++ b/app/Livewire/Forms/TextAdsForm.php @@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Auth; use Livewire\Component; use WireUi\Traits\WireUiActions; +use Illuminate\Validation\Rules\Enum; use App\Models\TextAd; use App\Enums\TextAdColors; @@ -31,7 +32,15 @@ class TextAdsForm extends Component 'duration' => 1, 'is_active' => 1, ]; - + public function rules() + { + return [ + 'fields.content' => 'required|string|max:255', + 'fields.color' => ['required',new Enum(TextAdColors::class)], + 'fields.duration' => 'required|integer|min:1|max:60', + 'fields.is_active' => 'required|boolean', + ]; + } public function mount() @@ -66,6 +75,7 @@ class TextAdsForm extends Component public function save() { + $validated = $this->validate($this->rules()); if ($this->textAdId) { if ($this->canEdit) { $textAd = TextAd::findOrFail($this->textAdId); diff --git a/app/Livewire/Forms/UserForm.php b/app/Livewire/Forms/UserForm.php index 420dbb8..a8aa720 100644 --- a/app/Livewire/Forms/UserForm.php +++ b/app/Livewire/Forms/UserForm.php @@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Auth; use Livewire\Component; use WireUi\Traits\WireUiActions; +use Illuminate\Validation\Rules\Enum; use App\Models\User; use App\Enums\UserGender; use App\Enums\UserStatus; @@ -41,15 +42,17 @@ class UserForm extends Component 'password_confirmation' => '', // 新增 ]; - - protected $rules = [ - 'fields.name' => 'required|string|max:255', - 'fields.email' => 'required|string|email|max:255', - 'fields.phone' => 'nullable|regex:/^09\d{8}$/', - 'fields.birthday' =>'nullable|date', - 'fields.gender' => 'required|in:male,female,other,unset', - 'fields.status' => 'required|integer|in:0,1,2', - ]; + public function rules() + { + return [ + 'fields.name' => 'required|string|max:255', + 'fields.email' => 'required|string|email|max:255', + 'fields.phone' => 'nullable|regex:/^09\d{8}$/', + 'fields.birthday' =>'nullable|date', + 'fields.gender' => ['required', new Enum(UserGender::class)], + 'fields.status' => ['required', new Enum(UserStatus::class)], + ]; + } public function mount() { @@ -88,7 +91,8 @@ class UserForm extends Component public function save() { - $rules = $this->rules; + //dd($this->fields); + $rules = $this->rules(); // 加入 email / phone 唯一性驗證,排除自己(編輯時) $rules['fields.email'] .= '|unique:users,email' . ($this->userId ? ",{$this->userId}" : ''); $rules['fields.phone'] .= '|unique:users,phone' . ($this->userId ? ",{$this->userId}" : ''); diff --git a/app/Livewire/Grids/RoomGrid.php b/app/Livewire/Grids/RoomGrid.php index 9bd4101..903a000 100644 --- a/app/Livewire/Grids/RoomGrid.php +++ b/app/Livewire/Grids/RoomGrid.php @@ -12,36 +12,35 @@ use Illuminate\Database\Eloquent\Collection; class RoomGrid extends Component { - protected $listeners = ['openModal','closeModal'];//,'refreshRooms' => '$refresh' - - public bool $showModal = false; - public int $branch_id = 0; - public $branchName=""; + public ?int $selectedBranchId = null; + public string $external_ip= ""; public array $roomTypes; - public function mount() { - $this->roomTypes = ['all' => '全部'] + collect(RoomType::cases())->mapWithKeys(fn($e) => [$e->value => $e->labels()])->toArray(); + $this->roomTypes = ['all' => '全部'] + collect(RoomType::cases())->mapWithKeys( + fn($e) => [$e->value => $e->labels()] + )->toArray(); + $this->selectChanged(Branch::first()->id,"",""); + } - public function openModal($branch_id = null) - { - $this->branch_id = $branch_id; - $branch = Branch::find($branch_id); - $this->branchName = Branch::find($branch_id)?->name ?? ''; - $this->showModal = true; - } - public function closeModal(){ - $this->showModal = false; - $this->branch_id = 0; + public function selectChanged($value,$fieldName, $modelId): void + { + $branch = $value ? Branch::find($value) : null; + $this->selectedBranchId=$branch?->id ?? ''; + $this->external_ip = $branch?->external_ip ?? ''; } public function render() { - $rooms = Room::where('branch_id', $this->branch_id)->orderBy('name', 'asc')->get(); - // 取得樓層 + + $rooms = Room::where('branch_id', $this->selectedBranchId)->orderBy('name')->get(); + $floors = $rooms->pluck('floor')->unique()->sort()->values()->toArray(); - return view('livewire.grids.room-grid',['rooms' =>$rooms,'floors' =>$floors]); + return view('livewire.grids.room-grid', [ + 'rooms' => $rooms, + 'floors' => $floors, + ]); } } diff --git a/app/Livewire/Tables/ArtistTable.php b/app/Livewire/Tables/ArtistTable.php index b053eae..71f66d4 100644 --- a/app/Livewire/Tables/ArtistTable.php +++ b/app/Livewire/Tables/ArtistTable.php @@ -99,7 +99,7 @@ final class ArtistTable extends PowerGridComponent ->add('category_str', function (Artist $model) { if ($this->canEdit) { return Blade::render( - '', + '', [ 'options' => ArtistCategory::options(), 'modelId' => intval($model->id), @@ -154,8 +154,8 @@ final class ArtistTable extends PowerGridComponent } } } - #[On('categoryChanged')] - public function categoryChanged($value,$fieldName, $modelId): void + #[On('selectChanged')] + public function selectChanged($value,$fieldName, $modelId): void { // dd($value,$fieldName, $modelId); if ($fieldName == 'category' && $this->canEdit) { diff --git a/app/Livewire/Tables/BranchTable.php b/app/Livewire/Tables/BranchTable.php index 79ff8d2..ae7e7c1 100644 --- a/app/Livewire/Tables/BranchTable.php +++ b/app/Livewire/Tables/BranchTable.php @@ -154,8 +154,8 @@ final class BranchTable extends PowerGridComponent } } } - #[On('categoryChanged')] - public function categoryChanged($value,$fieldName, $modelId): void + #[On('selectChanged')] + public function selectChanged($value,$fieldName, $modelId): void { // dd($value,$fieldName, $modelId); if ($fieldName == 'category' && $this->canEdit) { @@ -201,11 +201,6 @@ final class BranchTable extends PowerGridComponent public function actions(Branch $row): array { $actions = []; - $actions[] = Button::add('room-settings') - ->slot('包廂設定') - ->icon('solid-cog') - ->class('inline-flex items-center gap-1 px-3 py-1 rounded bg-amber-200 text-black') - ->dispatchTo('grids.room-grid', 'openModal', ['branch_id' => $row->id]); $actions[] = Button::add('room-synchronous') ->slot('包廂同步') ->icon('solid-cog') diff --git a/app/Livewire/Tables/RoomStatusLogTable.php b/app/Livewire/Tables/RoomStatusLogTable.php new file mode 100644 index 0000000..0e71dc3 --- /dev/null +++ b/app/Livewire/Tables/RoomStatusLogTable.php @@ -0,0 +1,82 @@ + 'outside']); + } + + public function setUp(): array + { + $actions = []; + $header = PowerGrid::header() + ->withoutLoading() + ->showToggleColumns(); + $header->includeViewOnTop('livewire.forms.headers.room-status-log'); + + $actions[]=$header; + $actions[]=PowerGrid::footer()->showPerPage()->showRecordCount(); + return $actions; + } + + public function datasource(): Builder + { + return RoomStatusLog::query()->latest();; + } + + public function relationSearch(): array + { + return []; + } + + public function fields(): PowerGridFields + { + return PowerGrid::fields() + ->add('id') + ->add('room_name', function (RoomStatusLog $model) { + return $model->room?->type->labelPowergridFilter().$model->room?->name; + }) + ->add('user_name', function (RoomStatusLog $model){ + return $model->user?->name; + }) + ->add('status_str',function (RoomStatusLog $model){ + return $model->status->labelPowergridFilter(); + }) + ->add('message') + ->add('created_at'); + } + + public function columns(): array + { + $column=[]; + $column[]=Column::make(__('room-status-log.id'), 'id'); + $column[]=Column::make(__('room-status-log.room'), 'room_name'); + $column[]=Column::make(__('room-status-log.user'), 'user_name'); + $column[]=Column::make(__('room-status-log.status'), 'status_str'); + $column[]=Column::make(__('room-status-log.message'), 'message'); + $column[]=Column::make(__('room-status-log.created_at'), 'created_at'); + return $column; + } + + public function filters(): array + { + return [ + ]; + } +} diff --git a/app/Livewire/Tables/RoomTable.php b/app/Livewire/Tables/RoomTable.php new file mode 100644 index 0000000..2bb34da --- /dev/null +++ b/app/Livewire/Tables/RoomTable.php @@ -0,0 +1,263 @@ + 'outside']); + //權限設定 + $this->canCreate = Auth::user()?->can('room-edit') ?? false; + $this->canEdit = Auth::user()?->can('room-edit') ?? false; + $this->canDownload=Auth::user()?->can('room-delete') ?? false; + $this->canDelect = Auth::user()?->can('room-delete') ?? false; + $branch = Branch::first(); + $this->selectedBranchId = $branch?->id; + $this->external_ip = $branch?->external_ip; + } + + public function setUp(): array + { + if($this->canDownload || $this->canDelect){ + $this->showCheckBox(); + } + $actions = []; + if($this->canDownload){ + $actions[]=PowerGrid::exportable(fileName: $this->tableName.'-file') + ->type(Exportable::TYPE_XLS, Exportable::TYPE_CSV); + } + $header = PowerGrid::header() + ->withoutLoading() + ->showToggleColumns(); + if($this->canCreate){ + $header->includeViewOnTop('livewire.forms.headers.room'); + } + $actions[]=$header; + $actions[]=PowerGrid::footer()->showPerPage()->showRecordCount(); + return $actions; + } + public function header(): array + { + $actions = []; + if ($this->canDelect) { + $actions[]=Button::add('bulk-delete') + ->slot('Bulk delete ()') + ->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, []); + } + return $actions; + } + + public function datasource(): Builder + { + $query = Room::query()->orderBy('name'); + + if ($this->selectedBranchId) { + $query->where('branch_id', $this->selectedBranchId); + } + + return $query; + } + public function updatedSelectedBranchId($value) + { + $this->resetPage(); // 重設分頁 + } + + public function relationSearch(): array + { + return []; + } + + public function fields(): PowerGridFields + { + return PowerGrid::fields() + ->add('id') + ->add('floor') + ->add('type_str',function(Room $model){ + if ($this->canEdit) { + return Blade::render( + '', + [ + 'options' => RoomType::options(), + 'modelId' => intval($model->id), + 'fieldName'=>'type', + 'selected' => $model->type->value + ] + ); + } + return $model->type->labelPowergridFilter(); + }) + ->add('name') + ->add('is_online', fn ($model) => $model->is_online===true ? '在線' : '斷線') + ->add('status_str',function (Room $model){ + return $model->status->labelPowergridFilter(); + }) + ->add('str_started_at', fn (Room $model) => $model->str_started_at()) + ->add('str_ended_at', fn (Room $model) => $model->str_ended_at()) + ->add('created_at'); + } + + public function columns(): array + { + $column=[]; + $column[]=Column::make(__('rooms.id'), 'id'); + $column[]=Column::make(__('rooms.floor'), 'floor')->sortable()->searchable()->editOnClick( + hasPermission: $this->canEdit, + dataField: 'floor', + fallback: 'N/A', + saveOnMouseOut: true + ); + $column[]=Column::make(__('rooms.type'), 'type_str','room.type')->sortable()->searchable(); + $column[]=Column::make(__('rooms.name'), 'name')->sortable()->searchable() + ->editOnClick( + hasPermission: $this->canEdit, + dataField: 'name', + fallback: 'N/A', + saveOnMouseOut: true + ); + $column[]=Column::make(__('rooms.isOnline'), 'is_online'); + $column[]=Column::make(__('rooms.status'), 'status_str','room.status')->sortable()->searchable()->hidden(true, false); + $column[]=Column::make(__('rooms.started_at'), 'str_started_at', 'started_at')->sortable()->hidden(true, false); + $column[]=Column::make(__('rooms.ended_at'), 'str_ended_at', 'ended_at')->sortable()->hidden(true, false); + $column[]=Column::make(__('rooms.created_at'), 'created_at')->sortable()->searchable(); + $column[]=Column::action('Action'); + + return $column; + } + + public function filters(): array + { + return [ + Filter::datetimepicker('started_at'), + Filter::datetimepicker('ended_at'), + Filter::boolean('is_online') + ->label('在線', '斷線'), + ]; + } + + + #[On('bulkDelete.{tableName}')] + public function bulkDelete(): void + { + if ($this->canDelect) { + $this->js('alert(window.pgBulkActions.get(\'' . $this->tableName . '\'))'); + if($this->checkboxValues){ + Branch::destroy($this->checkboxValues); + $this->js('window.pgBulkActions.clearAll()'); // clear the count on the interface. + } + } + } + #[On('selectChanged')] + public function selectChanged($value,$fieldName, $modelId): void + { + //dd($value,$fieldName, $modelId); + if($fieldName == 'selectedBranchId'){ + $this->selectedBranchId=$value; + $branch = Branch::find($this->selectedBranchId); + $this->external_ip=$branch->external_ip; + } + if ($fieldName == 'type' && $this->canEdit) { + $this->noUpdated($modelId,$fieldName,$value); + } + } + #[On('onUpdatedEditable')] + public function onUpdatedEditable($id, $field, $value): void + { + if($field === 'floor' && $this->canEdit){ + if (!is_numeric($value)) { + $this->notification()->send([ + 'icon' => 'error', + 'title' => '無效輸入', + 'description' => '樓層必須是數字', + ]); + return; + } + $this->noUpdated($id,$field,$value); + }else if ($field === 'name' && $this->canEdit) { + $this->noUpdated($id,$field,$value); + } + } + + private function noUpdated($id,$field,$value){ + $room = Room::find($id); + if ($room) { + $room->{$field} = $value; + $room->save(); // 明確觸發 saving + } + $this->notification()->send([ + 'icon' => 'success', + 'title' => $id.'.'.__('room.'.$field).':'.$value, + 'description' => '已經寫入', + ]); + } + + public function actions(Room $row): array + { + $actions = []; + + if ($this->canEdit) { + $actions[] =Button::add('edit') + ->slot(__('rooms.edit')) + ->icon('solid-pencil-square') + ->class('inline-flex items-center gap-1 px-3 py-1 rounded ') + ->dispatchTo('forms.room-form', 'openModal', ['id' => $row->id]); + } + if($this->canDelect){ + $actions[] =Button::add('delete') + ->slot(__('rooms.delete')) + ->icon('solid-trash') + ->class('inline-flex items-center gap-1 px-3 py-1 rounded ') + ->dispatchTo('forms.room-form', 'deleteRoom', ['id' => $row->id]); + } + if ($row->type->value === 'pc') { + $actions[] = Button::add('room-settings') + ->slot('包廂設定') + ->icon('solid-cog') + ->class('inline-flex items-center gap-1 px-3 py-1 rounded ') + ->dispatchTo('forms.modals.room-detail-modal', 'openModal', ['roomId' => $row->id]); + } + return $actions; + } + + /* + public function actionRules($row): array + { + return [ + // Hide button edit for ID 1 + Rule::button('edit') + ->when(fn($row) => $row->id === 1) + ->hide(), + ]; + } + */ +} diff --git a/app/Livewire/Tables/SongTable.php b/app/Livewire/Tables/SongTable.php index 56342d9..83f2c73 100644 --- a/app/Livewire/Tables/SongTable.php +++ b/app/Livewire/Tables/SongTable.php @@ -107,7 +107,7 @@ final class SongTable extends PowerGridComponent //->add('language_type_str', fn (Song $model) => SongLanguageType::from($model->language_type->value)->labels()) ->add('language_type_str', function (Song $model) { return Blade::render( - '', + '', [ 'options' => SongLanguageType::options(), 'modelId' => intval($model->id), @@ -120,7 +120,7 @@ final class SongTable extends PowerGridComponent //->add('situation_str', fn (Song $model) => SongSituation::from($model->situation->value)->labels()) ->add('situation_str', function (Song $model){ return Blade::render( - '', + '', [ 'options' => SongSituation::options(), 'modelId' => intval($model->id), @@ -214,8 +214,8 @@ final class SongTable extends PowerGridComponent $this->js('window.pgBulkActions.clearAll()'); // clear the count on the interface. } } - #[On('categoryChanged')] - public function categoryChanged($value,$fieldName, $modelId): void + #[On('selectChanged')] + public function selectChanged($value,$fieldName, $modelId): void { // dd($value,$fieldName, $modelId); if (in_array($fieldName, ['language_type', 'situation'])) { diff --git a/app/Livewire/Tables/TextAdsTable.php b/app/Livewire/Tables/TextAdsTable.php index ef950b1..cfcb8ae 100644 --- a/app/Livewire/Tables/TextAdsTable.php +++ b/app/Livewire/Tables/TextAdsTable.php @@ -97,7 +97,7 @@ final class TextAdsTable extends PowerGridComponent ->add('color_str', function (TextAd $model) { if ($this->canEdit) { return Blade::render( - '', + '', [ 'options' => TextAdColors::options(), 'modelId' => intval($model->id), @@ -148,8 +148,8 @@ final class TextAdsTable extends PowerGridComponent $this->js('window.pgBulkActions.clearAll()'); // clear the count on the interface. } } - #[On('categoryChanged')] - public function categoryChanged($value,$fieldName, $modelId): void + #[On('selectChanged')] + public function selectChanged($value,$fieldName, $modelId): void { //dd($value,$fieldName, $modelId); if (in_array($fieldName, ['color'])) { diff --git a/app/Livewire/Tables/UserTable.php b/app/Livewire/Tables/UserTable.php index e80d0db..9d4267e 100644 --- a/app/Livewire/Tables/UserTable.php +++ b/app/Livewire/Tables/UserTable.php @@ -96,7 +96,7 @@ final class UserTable extends PowerGridComponent ->add('gender_str', function (User $model) { if ($this->canEdit) { return Blade::render( - '', + '', [ 'options' => UserGender::options(), 'modelId' => intval($model->id), @@ -112,7 +112,7 @@ final class UserTable extends PowerGridComponent ->add('status_str', function (User $model) { if ($this->canEdit) { return Blade::render( - '', + '', [ 'options' => UserStatus::options(), 'modelId' => intval($model->id), @@ -180,8 +180,8 @@ final class UserTable extends PowerGridComponent } } } - #[On('categoryChanged')] - public function categoryChanged($value,$fieldName, $modelId): void + #[On('selectChanged')] + public function selectChanged($value,$fieldName, $modelId): void { // dd($value,$fieldName, $modelId); if (in_array($fieldName,['gender','status']) && $this->canEdit) { diff --git a/app/View/Components/SelectCategory.php b/app/View/Components/SelectCategory.php deleted file mode 100644 index b2837aa..0000000 --- a/app/View/Components/SelectCategory.php +++ /dev/null @@ -1,27 +0,0 @@ -options = $options; + $this->fieldName = $fieldName; + $this->modelId = $modelId; + $this->selected = $selected; + } + + /** + * Get the view / contents that represent the component. + */ + public function render(): View|Closure|string + { + return view('components.select-dropdown'); + } +} \ No newline at end of file diff --git a/database/.DS_Store b/database/.DS_Store index 9a9a023a3b99fb7b125cd44b10191445d78bca31..780579599a8d83aa7068b7c2f1386b758910a918 100644 GIT binary patch delta 87 zcmZoMXfc=|#>CJzu~2NHo}wrt0|NsP3otMwGL$f6GUPMlF%(ZMRA*$|e2USQZ4;9n m<7Rdaeh#3H%^w-RGf(Ch(d7hbIsn8BlWlmUH^+!9VFmzHvlEa2 delta 274 zcmZoMXfc=|#>B`mu~2NHo}wr-0|Nsi1A_nqLlQ$GLoq`tgC0Zi#Er}AK@$87DL}yz zAV!j8C}hZC$OMX}7L+9Ulopp10aYq7gn~5}0ZDzJ`WzrkWyk{>Rte|uHJD4XnumAvPhBuJ_ diff --git a/resources/lang/zh-tw/activity-log.php b/resources/lang/zh-tw/activity-log.php new file mode 100644 index 0000000..5e31e84 --- /dev/null +++ b/resources/lang/zh-tw/activity-log.php @@ -0,0 +1,5 @@ + '操作記錄' +]; \ No newline at end of file diff --git a/resources/lang/zh-tw/room-status-log.php b/resources/lang/zh-tw/room-status-log.php new file mode 100644 index 0000000..40ae803 --- /dev/null +++ b/resources/lang/zh-tw/room-status-log.php @@ -0,0 +1,13 @@ + '包廂狀態紀錄', + + 'id' => '編號', + 'room' => '包廂', + 'user' => '操成者', + 'status' => '狀態', + 'message' => '紀錄', + 'created_at' => '建立於' + + ]; \ No newline at end of file diff --git a/resources/lang/zh-tw/rooms.php b/resources/lang/zh-tw/rooms.php new file mode 100644 index 0000000..154c4f2 --- /dev/null +++ b/resources/lang/zh-tw/rooms.php @@ -0,0 +1,29 @@ + '包廂列表', + 'CreateNew' => '新增包廂', + 'EditRoom' => '編輯包廂', + 'create' => '新增', + 'edit' => '編輯', + 'delete' => '刪除', + + 'id' =>'編號', + 'floor' =>'樓層', + 'type' =>'型別', + 'name' =>'名稱', + 'isOnline' =>'在線', + 'status' =>'狀態', + 'started_at' =>'開始於', + 'ended_at' =>'結束於', + 'created_at' =>'建立於', + 'active' => '正常', + 'error' => '維修', + + 'select_type' =>'選擇型別', + + 'actions' => '操作', + 'view' => '查看', + 'submit' => '提交', + 'cancel' => '取消', +]; \ No newline at end of file diff --git a/resources/views/components/admin/branch-select.blade.php b/resources/views/components/admin/branch-select.blade.php new file mode 100644 index 0000000..9783b54 --- /dev/null +++ b/resources/views/components/admin/branch-select.blade.php @@ -0,0 +1,11 @@ +
+ + @if ($selectedBranchId) + - 包廂設定 ({{ $external_ip }}) + @endif +
\ No newline at end of file diff --git a/resources/views/components/admin/section-header.blade.php b/resources/views/components/admin/section-header.blade.php index 0c2fd95..cb12623 100644 --- a/resources/views/components/admin/section-header.blade.php +++ b/resources/views/components/admin/section-header.blade.php @@ -1,9 +1,9 @@
{{-- 左邊標題 --}} -

- {{ $title }} -

+
+ {!! $title !!} +
{{-- 右邊 slot 注入按鈕群 --}}
diff --git a/resources/views/components/select-category.blade.php b/resources/views/components/select-dropdown.blade.php similarity index 66% rename from resources/views/components/select-category.blade.php rename to resources/views/components/select-dropdown.blade.php index 5fde8ab..4580191 100644 --- a/resources/views/components/select-category.blade.php +++ b/resources/views/components/select-dropdown.blade.php @@ -1,6 +1,6 @@ -@props(['selected','fieldName', 'modelId']) +@props(['options', 'modelId' , 'fieldName', 'selected' ])
- @foreach ($options as $id => $name)