diff --git a/app/Livewire/Dashboard.php b/app/Livewire/Dashboard.php index 0392979..df70f31 100644 --- a/app/Livewire/Dashboard.php +++ b/app/Livewire/Dashboard.php @@ -6,22 +6,37 @@ use App\Models\TeamUser; use App\Models\User; use Livewire\Component; +use Livewire\WithPagination; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Gate; class Dashboard extends Component { - public $showCreateForm = false; - public $newTeamName = ''; - public $newTeamDescription = ''; + use WithPagination; - public function toggleCreateForm() + // Création d'équipe + public bool $showCreateForm = false; + public string $newTeamName = ''; + public string $newTeamDescription = ''; + + // Liste / filtre / tri + public string $search = ''; + public string $sortBy = 'name'; + public string $sortDirection = 'asc'; + + protected $queryString = [ + 'search' => ['except' => ''], + 'sortBy' => ['except' => 'name'], + 'sortDirection' => ['except' => 'asc'], + ]; + + public function toggleCreateForm(): void { - $this->showCreateForm = !$this->showCreateForm; + $this->showCreateForm = ! $this->showCreateForm; $this->reset(['newTeamName', 'newTeamDescription']); } - public function createTeam() + public function createTeam(): void { $this->validate([ 'newTeamName' => 'required|string|max:255', @@ -34,11 +49,11 @@ public function createTeam() 'owner_id' => Auth::id(), ]); - // Ajouter l'utilisateur à l'équipe + // Ajouter l'utilisateur créateur comme admin de l'équipe TeamUser::create([ 'team_id' => $team->id, 'user_id' => Auth::id(), - 'role' => 'admin', + 'role' => 'admin', // rôle pivot: 'admin' | 'user' | 'rh' ]); $this->reset(['newTeamName', 'newTeamDescription', 'showCreateForm']); @@ -46,10 +61,9 @@ public function createTeam() $this->dispatch('flash', type: 'success', text: 'Équipe créée avec succès !'); } - public function deleteTeam(Team $team) + public function deleteTeam(Team $team): void { - // Vérifier les permissions - if (!Gate::allows('deleteTeam', $team)) { + if (! Gate::allows('deleteTeam', $team)) { $this->dispatch('flash', type: 'error', text: 'Vous n\'avez pas les permissions pour supprimer cette équipe.'); return; } @@ -57,26 +71,73 @@ public function deleteTeam(Team $team) try { $teamName = $team->name; $team->delete(); - $this->dispatch('flash', type: 'success', text: 'L\'équipe "' . $teamName . '" a été supprimée avec succès.'); - } catch (\Exception $e) { + $this->dispatch('flash', type: 'success', text: 'L\'équipe "'.$teamName.'" a été supprimée avec succès.'); + } catch (\Throwable $e) { $this->dispatch('flash', type: 'error', text: 'Une erreur est survenue lors de la suppression de l\'équipe.'); } } + /* --------- Comportements liste --------- */ + + // Reset pagination quand la recherche change + public function updatingSearch(): void + { + $this->resetPage(); + } + + // Toggle tri / reset page quand on change de champ + public function sortBy(string $field): void + { + $allowed = ['name', 'created_at']; + if (! in_array($field, $allowed, true)) { + $field = 'name'; + } + + if ($this->sortBy === $field) { + $this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc'; + } else { + $this->sortBy = $field; + $this->sortDirection = 'asc'; + $this->resetPage(); + } + } + public function render() { $user = Auth::user(); - // Si c'est l'admin du site, il voit toutes les équipes - if ($user->role === User::ROLE_ADMIN) { - $teams = Team::all(); - } else { - // Sinon, seulement ses équipes - $teams = $user->teams; + // Base query + $query = Team::query()->select('teams.*'); + + // Scope d'appartenance: si pas admin site, ne montrer que les équipes dont il est membre + if ($user->role !== User::ROLE_ADMIN) { + $query->whereHas('users', fn ($q) => $q->where('users.id', $user->id)); } + // Recherche (reste dans le scope ci-dessus) + if (filled($this->search)) { + $s = '%' . str_replace('%', '\%', $this->search) . '%'; + $query->where(function ($q) use ($s) { + $q->where('teams.name', 'like', $s) + ->orWhere('teams.description', 'like', $s); + }); + } + + // Compteurs attendus par l'UI + $query->withCount(['users', 'projects']); + + // Tri sécurisé (qualifier) + $allowed = ['name', 'created_at']; + if (! in_array($this->sortBy, $allowed, true)) { + $this->sortBy = 'name'; + } + $query->orderBy('teams.' . $this->sortBy, $this->sortDirection); + + // Pagination + $teams = $query->paginate(10); + return view('livewire.dashboard', [ - 'teams' => $teams + 'teams' => $teams, ]); } } diff --git a/app/Livewire/ProjectComponent.php b/app/Livewire/ProjectComponent.php index 89598ff..fb31277 100644 --- a/app/Livewire/ProjectComponent.php +++ b/app/Livewire/ProjectComponent.php @@ -119,7 +119,7 @@ public function addMember() return; } - $this->team->users()->attach($user, ['role' => 'member']); + $this->team->users()->attach($user, ['role' => 'user']); $this->newMemberEmail = ''; $this->team->refresh(); @@ -166,7 +166,7 @@ public function demoteFromAdmin($userId) return; } - $this->team->users()->updateExistingPivot($userId, ['role' => 'member']); + $this->team->users()->updateExistingPivot($userId, ['role' => 'user']); $this->team->refresh(); $user = User::find($userId); diff --git a/app/Livewire/TeamComponent.php b/app/Livewire/TeamComponent.php deleted file mode 100644 index a1d2744..0000000 --- a/app/Livewire/TeamComponent.php +++ /dev/null @@ -1,90 +0,0 @@ - ['except' => ''], - 'sortBy' => ['except' => 'name'], - 'sortDirection' => ['except' => 'asc'], - ]; - - public function showCreateForm() - { - $this->showCreateForm = !$this->showCreateForm; - } - - public function updatingSearch() - { - $this->resetPage(); - } - - public function sortBy($field) - { - if ($this->sortBy === $field) { - $this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc'; - } else { - $this->sortBy = $field; - $this->sortDirection = 'asc'; - } - $this->resetPage(); - } - - public function deleteTeam(Team $team) - { - // Vérifier les permissions - if (!Gate::allows('deleteTeam', $team)) { - session()->flash('error', 'Vous n\'avez pas les permissions pour supprimer cette équipe.'); - return; - } - - try { - // Supprimer l'équipe et toutes ses relations - $team->delete(); - session()->flash('success', 'L\'équipe "' . $team->name . '" a été supprimée avec succès.'); - } catch (\Exception $e) { - session()->flash('error', 'Une erreur est survenue lors de la suppression de l\'équipe.'); - } - } - - public function render() - { - $user = Auth::user(); - - $teams = Team::query() - ->when($user->role !== 'admin', function ($query) { - // Si pas admin du site, filtrer par appartenance à l'équipe - $query->whereHas('users', function ($q) { - $q->where('users.id', Auth::id()); - }); - }) - ->when($this->search, function ($query) { - $search = "%{$this->search}%"; - $query->where(function ($q) use ($search) { - $q->where('name', 'like', $search) - ->orWhere('description', 'like', $search); - }); - }) - ->withCount(['users', 'projects']) - ->orderBy($this->sortBy, $this->sortDirection) - ->paginate(10); - - return view('livewire.team-component', [ - 'teams' => $teams - ]); - } -} diff --git a/resources/views/livewire/dashboard.blade.php b/resources/views/livewire/dashboard.blade.php index fe28533..5c1431f 100644 --- a/resources/views/livewire/dashboard.blade.php +++ b/resources/views/livewire/dashboard.blade.php @@ -69,42 +69,53 @@ class="bg-slate-400 dark:bg-gray-600 hover:bg-slate-500 dark:hover:bg-gray-700 t
{{ Str::limit($team->description, 100) }}
++ {{ Str::limit($team->description, 100) }} +
@endif- Membres: {{ $team->users()->count() }} + Membres: {{ $team->users_count }}
- Projets: {{ $team->projects()->count() }} + Projets: {{ $team->projects_count }}
Créée le {{ $team->created_at->format('d/m/Y') }} @@ -114,13 +125,19 @@ class="text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300