diff --git a/app/Http/Controllers/Admin/BasicSettings/MachineSettingController.php b/app/Http/Controllers/Admin/BasicSettings/MachineSettingController.php index 36b2403..d131a3d 100644 --- a/app/Http/Controllers/Admin/BasicSettings/MachineSettingController.php +++ b/app/Http/Controllers/Admin/BasicSettings/MachineSettingController.php @@ -45,8 +45,28 @@ class MachineSettingController extends AdminController } $models_list = $modelQuery->latest()->paginate($per_page)->withQueryString(); + // 3. 處理機台權限 (Permissions Tab) - 僅顯示 is_admin 帳號 + $users_list = null; + if ($tab === 'permissions') { + $userQuery = \App\Models\System\User::query() + ->where('is_admin', true) + ->with(['company', 'machines']); + + if ($search) { + $userQuery->where(function($q) use ($search) { + $q->where('name', 'like', "%{$search}%") + ->orWhere('username', 'like', "%{$search}%"); + }); + } - // 3. 基礎下拉資料 (用於新增/編輯機台的彈窗) + if ($request->filled('company_id')) { + $userQuery->where('company_id', $request->company_id); + } + + $users_list = $userQuery->latest()->paginate($per_page)->withQueryString(); + } + + // 4. 基礎下拉資料 (用於新增/編輯機台的彈窗) $models = MachineModel::select('id', 'name')->get(); $paymentConfigs = PaymentConfig::select('id', 'name')->get(); $companies = \App\Models\System\Company::select('id', 'name', 'code')->get(); @@ -54,6 +74,7 @@ class MachineSettingController extends AdminController return view('admin.basic-settings.machines.index', compact( 'machines', 'models_list', + 'users_list', 'models', 'paymentConfigs', 'companies', diff --git a/resources/views/admin/basic-settings/machines/index.blade.php b/resources/views/admin/basic-settings/machines/index.blade.php index eed8012..ce4e7bf 100644 --- a/resources/views/admin/basic-settings/machines/index.blade.php +++ b/resources/views/admin/basic-settings/machines/index.blade.php @@ -114,6 +114,80 @@ window.dispatchEvent(new CustomEvent('toast', { detail: { message: '{{ __('Error processing request') }}', type: 'error' } })); }); }, + // Permission Management + showPermissionModal: false, + isPermissionsLoading: false, + targetUserId: null, + targetUserName: '', + allMachines: [], + allMachinesCount: 0, + permissions: {}, + openPermissionModal(user) { + this.targetUserId = user.id; + this.targetUserName = user.name; + this.showPermissionModal = true; + this.isPermissionsLoading = true; + this.permissions = {}; + this.allMachines = []; + this.permissionSearchQuery = ''; + + fetch(`/admin/machines/permissions/accounts/${user.id}`) + .then(res => res.json()) + .then(data => { + if (data.machines) { + this.allMachines = data.machines; + this.allMachinesCount = data.machines.length; + const tempPermissions = {}; + data.machines.forEach(m => { + tempPermissions[m.id] = (data.assigned_ids || []).includes(m.id); + }); + this.permissions = tempPermissions; + } + }) + .catch(e => { + window.dispatchEvent(new CustomEvent('toast', { detail: { message: '{{ __('Failed to load permissions') }}', type: 'error' } })); + }) + .finally(() => { + this.isPermissionsLoading = false; + }); + }, + togglePermission(machineId) { + this.permissions = { ...this.permissions, [machineId]: !this.permissions[machineId] }; + }, + toggleSelectAll() { + const filtered = this.allMachines.filter(m => + !this.permissionSearchQuery || + m.name.toLowerCase().includes(this.permissionSearchQuery.toLowerCase()) || + m.serial_no.toLowerCase().includes(this.permissionSearchQuery.toLowerCase()) + ); + if (filtered.length === 0) return; + const allSelected = filtered.every(m => this.permissions[m.id]); + filtered.forEach(m => this.permissions[m.id] = !allSelected); + }, + savePermissions() { + const machineIds = Object.keys(this.permissions).filter(id => this.permissions[id]); + + fetch(`/admin/machines/permissions/accounts/${this.targetUserId}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').content, + 'Accept': 'application/json' + }, + body: JSON.stringify({ machine_ids: machineIds }) + }) + .then(res => res.json()) + .then(data => { + if (data.success) { + window.dispatchEvent(new CustomEvent('toast', { detail: { message: data.message, type: 'success' } })); + setTimeout(() => window.location.reload(), 500); + } else { + throw new Error(data.error || 'Update failed'); + } + }) + .catch(e => { + window.dispatchEvent(new CustomEvent('toast', { detail: { message: e.message, type: 'error' } })); + }); } }" @execute-regenerate.window="executeRegeneration($event.detail)"> @@ -131,7 +205,7 @@ {{ __('Add Machine') }} - @else + @elseif($tab === 'models')