From 0b28760f41731d85aa701cd20b3a73c777d86085 Mon Sep 17 00:00:00 2001 From: Sholahuddin Al Ayubi Date: Thu, 11 Dec 2025 17:20:34 +0700 Subject: [PATCH] feat: Implement user-branch relationship and update user management views - Added a many-to-many relationship between users and branches in User model. - Updated user creation and editing views to support multiple branch selection. - Modified user index view to display associated branches. - Created UserBranch model to manage user-branch associations. - Added migration for user_branches table with foreign key constraints. - Implemented seeder to populate user_branches based on existing user branch data. Run this command: - php artisan migrate - php artisan module:seed Usermanagement --class=UserBranchesSeeder --- app/Http/Controllers/UsersController.php | 716 +++++++++--------- app/Models/User.php | 9 +- app/Models/UserBranch.php | 34 + ...2_11_084248_create_user_branches_table.php | 34 + database/seeders/UserBranchesSeeder.php | 38 + resources/views/users/create.blade.php | 361 ++++----- resources/views/users/index.blade.php | 5 +- 7 files changed, 666 insertions(+), 531 deletions(-) create mode 100644 app/Models/UserBranch.php create mode 100644 database/migrations/2025_12_11_084248_create_user_branches_table.php create mode 100644 database/seeders/UserBranchesSeeder.php diff --git a/app/Http/Controllers/UsersController.php b/app/Http/Controllers/UsersController.php index 649f535..cefa3f3 100644 --- a/app/Http/Controllers/UsersController.php +++ b/app/Http/Controllers/UsersController.php @@ -1,377 +1,389 @@ middleware('auth'); - /** - * UsersController constructor. - * - * Initializes the user property with the authenticated user. - */ - public function __construct() - { - // Mengatur middleware auth - $this->middleware('auth'); + // Mengatur user setelah middleware auth dijalankan + $this->middleware(function ($request, $next) { + $this->user = Auth::user(); + return $next($request); + }); + } - // Mengatur user setelah middleware auth dijalankan - $this->middleware(function ($request, $next) { - $this->user = Auth::user(); - return $next($request); + /** + * Display a listing of the resource. + * + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function index() + { + if (is_null($this->user) || !$this->user->can('usermanagement.read')) { + abort(403, 'Sorry! You are not allowed to view users.'); + } + + return view('usermanagement::users.index'); + } + + /** + * Process support datatables ajax request. + * + * @param \Illuminate\Http\Request $request + * + * @return \Illuminate\Http\JsonResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function dataForDatatables(Request $request) + { + if (is_null($this->user) || !$this->user->can('usermanagement.read')) { + return response()->json([ + 'message' => 'Sorry! You are not allowed to view users.', + 'success' => false + ]); + } + + $query = User::query()->with(['branches', 'roles']); + + if (!$this->user->hasRole('administrator')) { + $query->whereHas('roles', function ($q) { + $q->where('name', '!=', 'administrator'); }); } - /** - * Display a listing of the resource. - * - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function index() - { - if (is_null($this->user) || !$this->user->can('usermanagement.read')) { - abort(403, 'Sorry! You are not allowed to view users.'); - } - - return view('usermanagement::users.index'); - } - - /** - * Process support datatables ajax request. - * - * @param \Illuminate\Http\Request $request - * - * @return \Illuminate\Http\JsonResponse - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function dataForDatatables(Request $request) - { - if (is_null($this->user) || !$this->user->can('usermanagement.read')) { - return response()->json(['message' => 'Sorry! You are not allowed to view users.','success' => false]); - } - - // Retrieve data from the database - $query = User::query(); - - if(!$this->user->hasRole('administrator')){ - $query->whereHas('roles', function($q){ - $q->where('name', '!=', 'administrator'); - }); - } - - // Apply search filter if provided - if ($request->has('search') && !empty($request->get('search'))) { - $search = $request->get('search'); - $query->whereAny(['name', 'email'], 'like', '%'.$search.'%'); - } - - // Apply sorting if provided - if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) { - $order = $request->get('sortOrder'); - $column = $request->get('sortField'); - $query->orderBy($column, $order); - } - - // Get the total count of records - $totalRecords = $query->count(); - - // Apply pagination if provided - if ($request->has('page') && $request->has('size')) { - $page = $request->get('page'); - $size = $request->get('size'); - $offset = ($page - 1) * $size; // Calculate the offset - - $query->skip($offset)->take($size); - } - - // Get the filtered count of records - $filteredRecords = $query->count(); - - // Get the data for the current page - $data = $query->with(['branch', 'roles'])->get(); - - // Calculate the page count - $pageCount = ceil($totalRecords / $request->get('size')); - - // Calculate the current page number - $currentPage = 0 + 1; - - // Return the response data as a JSON object - return response()->json([ - 'draw' => $request->get('draw'), - 'recordsTotal' => $totalRecords, - 'recordsFiltered' => $filteredRecords, - 'pageCount' => $pageCount, - 'page' => $currentPage, - 'totalCount' => $totalRecords, - 'data' => $data, - ]); - } - - /** - * Show the form for editing the specified resource. - * - * @param int $id - * - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function edit($id) - { - if (is_null($this->user) || !$this->user->can('usermanagement.update')) { - abort(403, 'Sorry! You are not allowed to edit users.'); - } - - $user = User::find($id); - $roles = Role::all(); - if(!$this->user->hasRole('administrator')){ - $roles = $roles->where('name', '!=', 'administrator'); - } - $branches = Branch::all(); - return view('usermanagement::users.create', compact('user', 'roles', 'branches')); - } - - /** - * Remove the specified resource from storage. - * - * @param int $id - * - * @return \Illuminate\Http\RedirectResponse - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function destroy($id) - { - if (is_null($this->user) || !$this->user->can('usermanagement.delete')) { - return response()->json(['message' => 'Sorry! You are not allowed to delete users.','success' => false]); - } - - $user = User::find($id); - $user->delete(); - - return response()->json(['message' => 'User deleted successfully.', 'success' => true]); - } - - /** - * Restore the specified resource from storage. - * - * @param int $id - * - * @return \Illuminate\Http\RedirectResponse - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function restore($id) - { - if (is_null($this->user) || !$this->user->can('usermanagement.restore')) { - abort(403, 'Sorry! You are not allowed to restore users.'); - } - - $user = User::withTrashed()->find($id); - $user->restore(); - - return redirect()->route('users.index')->with('success', 'User restored successfully.'); - } - - /** - * Store a newly created resource in storage. - * - * This function handles the creation of a new user in the application. It validates the incoming request data, - * creates a new user record in the database, and redirects the user to the users index page with a success message. - * - * @param \Modules\Usermanagement\Http\Requests\User $request The incoming request containing the user data. - * - * @return \Illuminate\Http\RedirectResponse Redirects to the users index page with a success message upon successful creation. - * @return \Illuminate\Http\RedirectResponse Redirects to the users create page upon validation failure. - */ - public function store(UserRequest $request) - { - if (is_null($this->user) || !$this->user->can('usermanagement.create')) { - abort(403, 'Sorry! You are not allowed to create a user.'); - } - - $validated = $request->validated(); - - if ($validated) { - $user = User::create($validated); - if ($user) { - if ($request->roles) { - $user->assignRole($request->roles); - } - - return redirect()->route('users.index')->with('success', 'User created successfully.'); - } - } - - return redirect()->route('users.create'); - } - - /** - * Show the form for creating a new resource. - * - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function create() - { - if (is_null($this->user) || !$this->user->can('usermanagement.create')) { - abort(403, 'Sorry! You are not allowed to create a user.'); - } - - $roles = Role::all(); - if(!$this->user->hasRole('administrator')){ - $roles = $roles->where('name', '!=', 'administrator'); - } - $branches = Branch::all(); - return view('usermanagement::users.create', compact('roles', 'branches')); - } - - public function export(Request $request) - { - if (is_null($this->user) || !$this->user->can('usermanagement.export')) { - abort(403, 'Sorry! You are not allowed to export users.'); - } - - // Get search parameter from request + if ($request->has('search') && !empty($request->get('search'))) { $search = $request->get('search'); - - return Excel::download(new UsersExport($search), 'users.xlsx'); + $query->where(function ($q) use ($search) { + $q->where('name', 'like', '%' . $search . '%') + ->orWhere('email', 'like', '%' . $search . '%') + ->orWhereHas('branches', function ($qb) use ($search) { + $qb->where('name', 'like', '%' . $search . '%'); + }); + }); } - public function profile() - { - $user = Auth::user(); - return view('usermanagement::users.profile', compact('user')); + if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) { + $order = $request->get('sortOrder'); + $column = $request->get('sortField'); + $query->orderBy($column, $order); } - public function updateProfile(Request $request) - { - $user = Auth::user(); + $totalRecords = $query->count(); - $validatedData = $request->validate([ - 'name' => 'required|string|max:255', - 'email' => 'required|string|email|max:255|unique:users,email,' . $user->id, - 'sign' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048', - ]); + $page = $request->get('page', 1); + $size = $request->get('size', 10); + $offset = ($page - 1) * $size; - $user->name = $validatedData['name']; - $user->email = $validatedData['email']; - $user->nik = $validatedData['nik']; + $query->skip($offset)->take($size); - if ($request->hasFile('sign')) { - // Delete old e-sign if exists - if ($user->sign) { - Storage::disk('public')->delete('signatures/' . $user->id . '/' . $user->sign); - } + $filteredRecords = $query->count(); - $sign = $request->file('sign'); - $signName = time() . '.' . $sign->getClientOriginalExtension(); + $users = $query->get()->map(function ($user) { + $user->branch_names = $user->branches->pluck('name')->join(', '); + return $user; + }); - // Make sure the directory exists - Storage::disk('public')->makeDirectory('signatures/' . $user->id); - - // Store the file - $sign->storeAs('signatures/' . $user->id, $signName, 'public'); - $user->sign = $signName; - } - - $user->save(); - - return redirect()->route('users.profile')->with('success', 'Profile updated successfully.'); - } - - public function changePassword(Request $request) - { - $validator = Validator::make($request->all(), [ - 'current_password' => 'required', - 'password' => 'required|string|min:8|confirmed', - ], [ - 'password_confirmation' => 'The new password confirmation does not match.', - ]); - - if ($validator->fails()) { - return back()->withErrors($validator)->withInput(); - } - - $user = Auth::user(); - - if (!Hash::check($request->current_password, $user->password)) { - return back()->withErrors(['current_password' => 'The current password is incorrect.']); - } - - $user->password = Hash::make($request->password); - $user->save(); - - return redirect()->route('users.profile')->with('success', 'Password changed successfully.'); - } - - /** - * Update the specified resource in storage. - * - * @param \Modules\Usermanagement\Http\Requests\User $request - * @param int $id - * - * @return \Illuminate\Http\RedirectResponse - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function update(UserRequest $request, $id) - { - if (is_null($this->user) || !$this->user->can('usermanagement.update')) { - abort(403, 'Sorry! You are not allowed to update users.'); - } - - $validated = $request->validated(); - - if ($validated) { - try { - $user = User::find($id); - if ($request->hasFile('sign')) { - $sign = $request->file('sign'); - - $signName = time() . '.' . $sign->getClientOriginalExtension(); - - $sign->storeAs( - 'public/signatures/' . $user->id . '/', - $signName, - ); - - $validated['sign'] = $signName; - } - $user->update($validated); - if ($request->roles) { - $user->roles()->detach(); - $user->assignRole($request->roles); - } - } catch (Exception $e) { - return redirect()->back()->withErrors(['error' => 'Failed to update user. Please try again.']); - } - } - - return redirect()->route('users.index')->with('success', 'User updated successfully.'); - } + $pageCount = ceil($totalRecords / $size); + return response()->json([ + 'draw' => $request->get('draw'), + 'recordsTotal' => $totalRecords, + 'recordsFiltered' => $filteredRecords, + 'pageCount' => $pageCount, + 'page' => $page, + 'totalCount' => $totalRecords, + 'data' => $users, + ]); } + + /** + * Show the form for editing the specified resource. + * + * @param int $id + * + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function edit($id) + { + if (is_null($this->user) || !$this->user->can('usermanagement.update')) { + abort(403, 'Sorry! You are not allowed to edit users.'); + } + + $user = User::find($id); + $roles = Role::all(); + if (!$this->user->hasRole('administrator')) { + $roles = $roles->where('name', '!=', 'administrator'); + } + $branches = Branch::all(); + return view('usermanagement::users.create', compact('user', 'roles', 'branches')); + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function destroy($id) + { + if (is_null($this->user) || !$this->user->can('usermanagement.delete')) { + return response()->json(['message' => 'Sorry! You are not allowed to delete users.', 'success' => false]); + } + + $user = User::find($id); + $user->delete(); + + return response()->json(['message' => 'User deleted successfully.', 'success' => true]); + } + + /** + * Restore the specified resource from storage. + * + * @param int $id + * + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function restore($id) + { + if (is_null($this->user) || !$this->user->can('usermanagement.restore')) { + abort(403, 'Sorry! You are not allowed to restore users.'); + } + + $user = User::withTrashed()->find($id); + $user->restore(); + + return redirect()->route('users.index')->with('success', 'User restored successfully.'); + } + + /** + * Store a newly created resource in storage. + * + * This function handles the creation of a new user in the application. It validates the incoming request data, + * creates a new user record in the database, and redirects the user to the users index page with a success message. + * + * @param \Modules\Usermanagement\Http\Requests\User $request The incoming request containing the user data. + * + * @return \Illuminate\Http\RedirectResponse Redirects to the users index page with a success message upon successful creation. + * @return \Illuminate\Http\RedirectResponse Redirects to the users create page upon validation failure. + */ + public function store(UserRequest $request) + { + if (is_null($this->user) || !$this->user->can('usermanagement.create')) { + abort(403, 'Sorry! You are not allowed to create a user.'); + } + + $validated = $request->validated(); + + if ($validated) { + $user = User::create($validated); + if ($user) { + if ($request->roles) { + $user->assignRole($request->roles); + } + + return redirect()->route('users.index')->with('success', 'User created successfully.'); + } + } + + return redirect()->route('users.create'); + } + + /** + * Show the form for creating a new resource. + * + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create() + { + if (is_null($this->user) || !$this->user->can('usermanagement.create')) { + abort(403, 'Sorry! You are not allowed to create a user.'); + } + + $roles = Role::all(); + if (!$this->user->hasRole('administrator')) { + $roles = $roles->where('name', '!=', 'administrator'); + } + $branches = Branch::all(); + return view('usermanagement::users.create', compact('roles', 'branches')); + } + + public function export(Request $request) + { + if (is_null($this->user) || !$this->user->can('usermanagement.export')) { + abort(403, 'Sorry! You are not allowed to export users.'); + } + + // Get search parameter from request + $search = $request->get('search'); + + return Excel::download(new UsersExport($search), 'users.xlsx'); + } + + public function profile() + { + $user = Auth::user(); + return view('usermanagement::users.profile', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = Auth::user(); + + $validatedData = $request->validate([ + 'name' => 'required|string|max:255', + 'email' => 'required|string|email|max:255|unique:users,email,' . $user->id, + 'sign' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048', + ]); + + $user->name = $validatedData['name']; + $user->email = $validatedData['email']; + $user->nik = $validatedData['nik']; + + if ($request->hasFile('sign')) { + // Delete old e-sign if exists + if ($user->sign) { + Storage::disk('public')->delete('signatures/' . $user->id . '/' . $user->sign); + } + + $sign = $request->file('sign'); + $signName = time() . '.' . $sign->getClientOriginalExtension(); + + // Make sure the directory exists + Storage::disk('public')->makeDirectory('signatures/' . $user->id); + + // Store the file + $sign->storeAs('signatures/' . $user->id, $signName, 'public'); + $user->sign = $signName; + } + + $user->save(); + + return redirect()->route('users.profile')->with('success', 'Profile updated successfully.'); + } + + public function changePassword(Request $request) + { + $validator = Validator::make($request->all(), [ + 'current_password' => 'required', + 'password' => 'required|string|min:8|confirmed', + ], [ + 'password_confirmation' => 'The new password confirmation does not match.', + ]); + + if ($validator->fails()) { + return back()->withErrors($validator)->withInput(); + } + + $user = Auth::user(); + + if (!Hash::check($request->current_password, $user->password)) { + return back()->withErrors(['current_password' => 'The current password is incorrect.']); + } + + $user->password = Hash::make($request->password); + $user->save(); + + return redirect()->route('users.profile')->with('success', 'Password changed successfully.'); + } + + /** + * Update the specified resource in storage. + * + * @param \Modules\Usermanagement\Http\Requests\User $request + * @param int $id + * + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function update(UserRequest $request, $id) + { + if (is_null($this->user) || !$this->user->can('usermanagement.update')) { + abort(403, 'Sorry! You are not allowed to update users.'); + } + + $validated = $request->validated(); + + if ($validated) { + try { + $user = User::findOrFail($id); + + // Handle file upload e-sign + if ($request->hasFile('sign')) { + $sign = $request->file('sign'); + + $signName = time() . '.' . $sign->getClientOriginalExtension(); + + // Simpan file ke storage + $sign->storeAs( + 'public/signatures/' . $user->id . '/', + $signName + ); + + $validated['sign'] = $signName; + } + + // Update data user + $user->update($validated); + + // Update roles + if ($request->roles) { + $user->roles()->detach(); + $user->assignRole($request->roles); + } + + $user->branches()->sync($request->input('branches', [])); + + $branchIds = $user->branches()->pluck('branches.id')->toArray(); + + } catch (Exception $e) { + Log::error('Failed to update user: ' . $e->getMessage()); + return redirect()->back()->withErrors(['error' => 'Failed to update user. Please try again.']); + } + } + + return redirect()->route('users.index')->with('success', 'User updated successfully.'); + } + +} diff --git a/app/Models/User.php b/app/Models/User.php index 3e2fa76..a872078 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -73,8 +73,8 @@ class User extends Authenticatable { return [ 'email_verified_at' => 'datetime', - 'password' => 'hashed', - 'id' => 'string', + 'password' => 'hashed', + 'id' => 'string', ]; } @@ -107,4 +107,9 @@ class User extends Authenticatable { return $this->hasMany(Appointment::class, 'admin_id'); } + + public function branches() + { + return $this->belongsToMany(Branch::class, 'user_branches', 'user_id', 'branch_id'); + } } diff --git a/app/Models/UserBranch.php b/app/Models/UserBranch.php new file mode 100644 index 0000000..0bf2045 --- /dev/null +++ b/app/Models/UserBranch.php @@ -0,0 +1,34 @@ +belongsTo(User::class); + } + + public function branch() + { + return $this->belongsTo(Branch::class); + } +} diff --git a/database/migrations/2025_12_11_084248_create_user_branches_table.php b/database/migrations/2025_12_11_084248_create_user_branches_table.php new file mode 100644 index 0000000..de926c4 --- /dev/null +++ b/database/migrations/2025_12_11_084248_create_user_branches_table.php @@ -0,0 +1,34 @@ +id(); + $table->unsignedBigInteger('user_id'); + $table->unsignedBigInteger('branch_id'); + $table->timestamps(); + + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + $table->foreign('branch_id')->references('id')->on('branches')->onDelete('cascade'); + + $table->unique(['user_id', 'branch_id']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('user_branches'); + } +}; diff --git a/database/seeders/UserBranchesSeeder.php b/database/seeders/UserBranchesSeeder.php new file mode 100644 index 0000000..52c4fea --- /dev/null +++ b/database/seeders/UserBranchesSeeder.php @@ -0,0 +1,38 @@ +branch_id) { + $exists = DB::table('user_branches') + ->where('user_id', $user->id) + ->where('branch_id', $user->branch_id) + ->exists(); + + if (!$exists) { + DB::table('user_branches')->insert([ + 'user_id' => $user->id, + 'branch_id' => $user->branch_id, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } + } + } + + $this->command->info('User branches seeded successfully.'); + } +} diff --git a/resources/views/users/create.blade.php b/resources/views/users/create.blade.php index 3aad24c..cb7dc91 100644 --- a/resources/views/users/create.blade.php +++ b/resources/views/users/create.blade.php @@ -6,188 +6,197 @@ @section('content')
- @if(isset($user->id)) + @if (isset($user->id))
@method('PUT') - @else - - @endif - @csrf -
-
-

- {{ isset($user->id) ? 'Edit' : 'Add' }} User -

-
- -
-
-
+ @else + + @endif + @csrf +
+
+

+ {{ isset($user->id) ? 'Edit' : 'Add' }} User +

+
+ +
+
+
-
- -
- - @error('name') - {{ $message }} - @enderror -
-
-
- -
- - @error('email') - {{ $message }} - @enderror -
-
-
- -
- - @error('nik') - {{ $message }} - @enderror -
-
-
- -
- - @error('branch_id') - {{ $message }} - @enderror -
-
- @if(isset($user->id)) -
- -
- -
-
- @endif -
- +
+ +
+ + @error('name') + {{ $message }} + @enderror +
+
+
+ +
+ + @error('email') + {{ $message }} + @enderror +
+
+
+ +
+ + @error('nik') + {{ $message }} + @enderror +
+
+
+ +
+ + @error('branches') + {{ $message }} + @enderror +
+
+ @if (isset($user->id)) +
+ +
+ +
+
+ @endif +
+ -
-
- -
- - -
-
- @error('password') - {{ $message }} - @enderror -
-
-
- -
-
- -
- - -
-
- @error('password_confirmation') - {{ $message }} - @enderror -
-
-
- -
-
- @foreach($roles as $role) -
-
-
- - - - - - -
- - -
-
-
- - {{ $role->name }} - - - - -
-
-
- @if(isset($user)) - name,$user->roles->pluck("name")->toArray()) ? 'checked' : '' }} name="roles" type="radio" value="{{ $role->name }}"> - @else - - @endif -
-
- @endforeach -
-
-
- -
- -
+
+
+ +
+ +
- + @error('password') + {{ $message }} + @enderror +
+
+
+ +
+
+ +
+ + +
+
+ @error('password_confirmation') + {{ $message }} + @enderror +
+
+
+ +
+
+ @foreach ($roles as $role) +
+
+
+ + + + + + +
+ + +
+
+
+ + {{ $role->name }} + + + + +
+
+
+ @if (isset($user)) + name, $user->roles->pluck('name')->toArray()) ? 'checked' : '' }} + name="roles" type="radio" value="{{ $role->name }}"> + @else + + @endif +
+
+ @endforeach +
+
+
+ +
+ +
+
+
+
@endsection diff --git a/resources/views/users/index.blade.php b/resources/views/users/index.blade.php index 0642830..4dd2e55 100644 --- a/resources/views/users/index.blade.php +++ b/resources/views/users/index.blade.php @@ -160,7 +160,10 @@ branch: { title: 'Branch', render: (item, data) => { - return data.branch?.name || '-'; + if (data.branches && data.branches.length > 0) { + return data.branches.map(b => b.name).join(', '); + } + return '-'; }, }, role: {