user()->currentWorkspaceUser(); // Block Workers entirely — team page is Owner/Manager only if ($workspaceUser->role->is(WorkspaceUserRole::Worker)) { abort(404); } $workspace = $this->currentWorkspace(); $isOwner = $workspaceUser->role->is(WorkspaceUserRole::Owner); // Load members with pivot data $members = $workspace->users() ->withPivot('id', 'role', 'permissions', 'created_at') ->get() ->map(function ($user) use ($isOwner) { $pivotRole = $user->pivot->role; $role = $pivotRole?->value ?? $pivotRole; $data = [ 'id' => $user->id, 'name' => $user->name, 'email' => $user->email, 'role' => $role, 'joined_at' => $user->pivot->created_at, 'status' => 'active', 'workspace_user_id' => $user->pivot->id, 'updateRoleUrl' => route('team.updateRole', $user->pivot->id), 'removeUrl' => route('team.remove', $user->pivot->id), ]; // Add permissions data for Manager members (only visible to Owners) if ($pivotRole instanceof WorkspaceUserRole && $pivotRole->is(WorkspaceUserRole::Manager) && $isOwner) { $data['permissions'] = $user->pivot->permissions ?? []; $data['permissionsUrl'] = route('team.updatePermissions', $user->pivot->id); } return $data; }); // Load pending invitations $pendingInvitations = TeamInvitation::where('workspace_id', $workspace->id) ->whereNull('accepted_at') ->where('expires_at', '>', now()) ->get() ->map(fn ($inv) => [ 'id' => $inv->id, 'email' => $inv->email, 'role' => $inv->role, 'invited_at' => $inv->created_at, 'status' => 'pending', ]); // Can manage team: Owner always, Manager checks permission $canManageTeam = $workspaceUser->role->is(WorkspaceUserRole::Owner) || ($workspaceUser->permissions[Permission::CanManageTeam] ?? false); return Inertia::render('team/Index', [ 'members' => $members, 'pendingInvitations' => $pendingInvitations, 'canManageTeam' => $canManageTeam, 'isOwner' => $isOwner, 'availablePermissions' => $isOwner ? $this->permissionLabels() : [], 'authUserId' => auth()->id(), 'inviteUrl' => route('team.invite'), 'roles' => $this->roleLabels(), ]); } /** * Invite a new team member. */ public function invite(InviteTeamMemberRequest $request): RedirectResponse { $workspace = $this->currentWorkspace(); $invitation = TeamInvitation::create([ 'workspace_id' => $workspace->id, 'email' => $request->validated('email'), 'role' => $request->validated('role'), 'invited_by' => auth()->id(), 'expires_at' => now()->addDays(7), ]); Mail::to($invitation->email)->send(new TeamInvitationMail($workspace, $invitation)); return redirect()->back()->with('success', 'Invitation envoyée'); } /** * Update a team member's role. */ public function updateRole(UpdateTeamMemberRoleRequest $request, int $workspaceUserId): RedirectResponse { $this->authorizePermission(Permission::CanManageTeam); $workspaceUser = WorkspaceUser::where('id', $workspaceUserId) ->where('workspace_id', session('current_workspace_id')) ->firstOrFail(); if ($workspaceUser->role->is(WorkspaceUserRole::Owner)) { abort(404); } if ($workspaceUser->user_id === auth()->id()) { abort(404); } $oldRole = $workspaceUser->role->value; $newRole = $request->validated('role'); DB::transaction(function () use ($workspaceUser, $oldRole, $newRole) { $workspaceUser->update([ 'role' => $newRole, 'permissions' => config("permissions.defaults.{$newRole}", []), ]); $targetUser = User::findOrFail($workspaceUser->user_id); activity() ->performedOn($workspaceUser) ->withProperties([ 'target_user' => $targetUser->name, 'old_role' => $oldRole, 'new_role' => $newRole, ]) ->log('role_changed'); }); return redirect()->back()->with('success', 'Rôle mis à jour'); } /** * Update a Manager's individual permissions. */ public function updatePermissions(UpdatePermissionsRequest $request, int $workspaceUserId): RedirectResponse { $workspaceUser = WorkspaceUser::where('id', $workspaceUserId) ->where('workspace_id', session('current_workspace_id')) ->firstOrFail(); // Only Manager permissions can be toggled if (! $workspaceUser->role->is(WorkspaceUserRole::Manager)) { abort(404); } $newPermissions = $request->validated('permissions'); DB::transaction(function () use ($workspaceUser, $newPermissions) { $oldPermissions = $workspaceUser->permissions ?? []; $workspaceUser->update([ 'permissions' => $newPermissions, ]); $targetUser = User::findOrFail($workspaceUser->user_id); activity() ->performedOn($workspaceUser) ->withProperties([ 'target_user' => $targetUser->name, 'old_permissions' => $oldPermissions, 'new_permissions' => $newPermissions, ]) ->log('permissions_updated'); }); return redirect()->back()->with('success', 'Permissions mises à jour'); } /** * Remove a team member from the workspace. */ public function remove(int $workspaceUserId): RedirectResponse { $this->authorizePermission(Permission::CanManageTeam); $workspaceUser = WorkspaceUser::where('id', $workspaceUserId) ->where('workspace_id', session('current_workspace_id')) ->firstOrFail(); if ($workspaceUser->role->is(WorkspaceUserRole::Owner)) { abort(404); } if ($workspaceUser->user_id === auth()->id()) { abort(404); } $targetUser = User::findOrFail($workspaceUser->user_id); DB::transaction(function () use ($workspaceUser, $targetUser) { $workspaceUser->delete(); activity() ->withProperties([ 'target_user' => $targetUser->name, 'target_email' => $targetUser->email, 'role' => $workspaceUser->role->value, ]) ->log('member_removed'); }); return redirect()->back()->with('success', 'Membre retiré'); } /** * Get role labels for the frontend. * * @return array */ protected function roleLabels(): array { return [ 'manager' => 'Gestionnaire', 'worker' => 'Collaborateur', ]; } /** * Get permission labels (French) for the frontend. * * @return array */ protected function permissionLabels(): array { return [ Permission::CanManageTeam => "Gérer l'équipe", Permission::CanViewActivityLogs => "Voir les journaux d'activité", Permission::CanConfigurePortal => 'Configurer le portail client', ]; } }