diff --git a/README.md b/README.md index 1dd4d0d..90b8ee0 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,12 @@ - Ajout de commentaires sur un projet (associés à une tâche système si nécessaire) - Affichage des commentaires récents avec auteur et date -### 🎨 Interface +### �️ Météo des émotions +- Suivi du bien-être de l'équipe via des questionnaires +- Visualisation de l'état émotionnel des membres +- Historique des réponses pour analyse des tendances + +### �🎨 Interface - UI responsive avec **Tailwind CSS** - Composants dynamiques Livewire pour une interaction fluide - Affichage clair des priorités et statuts par couleurs @@ -118,9 +123,6 @@ sail npm run dev - Documentation technique & utilisateur complète - Mise en production -## Suivi de la météo des émotions -- Questionnaire - ## Mise en concurrence hebdomadaire - Challenge sous forme de mission hebdomadaire diff --git a/app/Livewire/CommentComponent.php b/app/Livewire/CommentComponent.php index 185b4bf..f86dd4c 100644 --- a/app/Livewire/CommentComponent.php +++ b/app/Livewire/CommentComponent.php @@ -2,10 +2,42 @@ namespace App\Livewire; +use App\Models\Comment; use Livewire\Component; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Gate; class CommentComponent extends Component { + public $comment; + + public function mount(Comment $comment) + { + $this->comment = $comment; + } + + public function deleteComment() + { + // Vérifier les permissions + if (!Gate::allows('deleteComment', $this->comment)) { + $this->dispatch('flash', type: 'error', text: 'Vous n\'avez pas les permissions pour supprimer ce commentaire.'); + return; + } + + try { + $this->comment->delete(); + $this->dispatch('flash', type: 'success', text: 'Le commentaire a été supprimé avec succès.'); + $this->dispatch('commentDeleted'); + } catch (\Exception $e) { + $this->dispatch('flash', type: 'error', text: 'Une erreur est survenue lors de la suppression du commentaire.'); + } + } + + public function canDelete() + { + return Gate::allows('deleteComment', $this->comment); + } + public function render() { return view('livewire.comment-component'); diff --git a/app/Livewire/Dashboard.php b/app/Livewire/Dashboard.php index 1bdbbd1..0392979 100644 --- a/app/Livewire/Dashboard.php +++ b/app/Livewire/Dashboard.php @@ -7,6 +7,7 @@ use App\Models\User; use Livewire\Component; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Gate; class Dashboard extends Component { @@ -45,6 +46,23 @@ public function createTeam() $this->dispatch('flash', type: 'success', text: 'Équipe créée avec succès !'); } + public function deleteTeam(Team $team) + { + // Vérifier les permissions + if (!Gate::allows('deleteTeam', $team)) { + $this->dispatch('flash', type: 'error', text: 'Vous n\'avez pas les permissions pour supprimer cette équipe.'); + return; + } + + 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: 'error', text: 'Une erreur est survenue lors de la suppression de l\'équipe.'); + } + } + public function render() { $user = Auth::user(); @@ -54,7 +72,7 @@ public function render() $teams = Team::all(); } else { // Sinon, seulement ses équipes - $teams = $user->teams()->get(); + $teams = $user->teams; } return view('livewire.dashboard', [ diff --git a/app/Livewire/ProjectComponent.php b/app/Livewire/ProjectComponent.php index 5a7fada..89598ff 100644 --- a/app/Livewire/ProjectComponent.php +++ b/app/Livewire/ProjectComponent.php @@ -7,6 +7,7 @@ use App\Models\User; use Livewire\Component; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Gate; class ProjectComponent extends Component { @@ -172,6 +173,23 @@ public function demoteFromAdmin($userId) $this->dispatch('flash', type: 'success', text: $user->name . ' n\'est plus administrateur de l\'équipe !'); } + public function deleteProject(Project $project) + { + // Vérifier les permissions + if (!Gate::allows('deleteProject', $project)) { + $this->dispatch('flash', type: 'error', text: 'Vous n\'avez pas les permissions pour supprimer ce projet.'); + return; + } + + try { + $projectName = $project->name; + $project->delete(); + $this->dispatch('flash', type: 'success', text: 'Le projet "' . $projectName . '" a été supprimé avec succès.'); + } catch (\Exception $e) { + $this->dispatch('flash', type: 'error', text: 'Une erreur est survenue lors de la suppression du projet.'); + } + } + public function render() { $projects = Project::where('team_id', $this->teamId)->get(); diff --git a/app/Livewire/TaskComponent.php b/app/Livewire/TaskComponent.php index f09bd4f..18909f4 100644 --- a/app/Livewire/TaskComponent.php +++ b/app/Livewire/TaskComponent.php @@ -7,6 +7,7 @@ use App\Models\Comment; use Livewire\Component; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Gate; class TaskComponent extends Component { @@ -146,7 +147,7 @@ public function setSort($field) $this->sortDir = $this->sortDir === 'asc' ? 'desc' : 'asc'; } else { $this->sortField = $field; - $this->sortDir = $field === 'priority' ? 'desc' : 'desc'; + $this->sortDir = 'desc'; } } @@ -160,6 +161,39 @@ public function resetFilters() $this->sortDir = 'desc'; } + public function deleteTask(Task $task) + { + // Vérifier les permissions + if (!Gate::allows('deleteTask', $task)) { + $this->dispatch('flash', type: 'error', text: 'Vous n\'avez pas les permissions pour supprimer cette tâche.'); + return; + } + + try { + $taskTitle = $task->title; + $task->delete(); + $this->dispatch('flash', type: 'success', text: 'La tâche "' . $taskTitle . '" a été supprimée avec succès.'); + } catch (\Exception $e) { + $this->dispatch('flash', type: 'error', text: 'Une erreur est survenue lors de la suppression de la tâche.'); + } + } + + public function deleteComment(Comment $comment) + { + // Vérifier les permissions + if (!Gate::allows('deleteComment', $comment)) { + $this->dispatch('flash', type: 'error', text: 'Vous n\'avez pas les permissions pour supprimer ce commentaire.'); + return; + } + + try { + $comment->delete(); + $this->dispatch('flash', type: 'success', text: 'Le commentaire a été supprimé avec succès.'); + } catch (\Exception $e) { + $this->dispatch('flash', type: 'error', text: 'Une erreur est survenue lors de la suppression du commentaire.'); + } + } + public function render() { $teamMembers = $this->project->team->users; diff --git a/app/Livewire/TeamComponent.php b/app/Livewire/TeamComponent.php index d3b1b59..a1d2744 100644 --- a/app/Livewire/TeamComponent.php +++ b/app/Livewire/TeamComponent.php @@ -6,6 +6,7 @@ use Livewire\Component; use Livewire\WithPagination; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Gate; class TeamComponent extends Component { @@ -43,6 +44,23 @@ public function sortBy($field) $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(); diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 4bb01cf..3bacbae 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -43,5 +43,29 @@ public function boot(): void Gate::define('manageUsers', function (User $user) { return $user->role === User::ROLE_ADMIN; }); + + // ===================================== + // PERMISSIONS DE SUPPRESSION + // ===================================== + + // Permission pour supprimer une équipe + Gate::define('deleteTeam', function (User $user, Team $team) { + return $user->canDeleteTeam($team); + }); + + // Permission pour supprimer un projet + Gate::define('deleteProject', function (User $user, $project) { + return $user->canDeleteProject($project); + }); + + // Permission pour supprimer une tâche + Gate::define('deleteTask', function (User $user, $task) { + return $user->canDeleteTask($task); + }); + + // Permission pour supprimer un commentaire + Gate::define('deleteComment', function (User $user, $comment) { + return $user->canDeleteComment($comment); + }); } } diff --git a/app/Traits/HasTeamPermissions.php b/app/Traits/HasTeamPermissions.php index b506bc2..5ed0674 100644 --- a/app/Traits/HasTeamPermissions.php +++ b/app/Traits/HasTeamPermissions.php @@ -101,4 +101,70 @@ public function getTeamsWithPermission(string $permission): \Illuminate\Database return $permissionMap[$permission] ?? collect(); } + + // ===================================== + // PERMISSIONS DE SUPPRESSION + // ===================================== + + /** + * Check if user can delete a team + */ + public function canDeleteTeam(Team $team): bool + { + if ($this->isAdmin()) { + return true; // Site admin can delete any team + } + + return $this->isTeamAdminFor($team); + } + + /** + * Check if user can delete a project + */ + public function canDeleteProject(\App\Models\Project $project): bool + { + if ($this->isAdmin()) { + return true; // Site admin can delete any project + } + + return $this->isTeamAdminFor($project->team); + } + + /** + * Check if user can delete a task + */ + public function canDeleteTask(\App\Models\Task $task): bool + { + if ($this->isAdmin()) { + return true; // Site admin can delete any task + } + + return $this->isTeamAdminFor($task->project->team); + } + + /** + * Check if user can delete a comment + */ + public function canDeleteComment(\App\Models\Comment $comment): bool + { + // Si l'utilisateur est l'auteur du commentaire, il peut le supprimer + if ($comment->user_id === $this->id) { + return true; + } + + // Site admin peut supprimer n'importe quel commentaire + if ($this->isAdmin()) { + return true; + } + + // Team admin peut supprimer les commentaires dans son équipe + $team = null; + if ($comment->isTaskComment()) { + $team = $comment->task->project->team; + } elseif ($comment->isProjectComment()) { + $team = $comment->project->team; + } + + return $team ? $this->isTeamAdminFor($team) : false; + } } diff --git a/resources/views/components/hexagon-grid.blade.php b/resources/views/components/hexagon-grid.blade.php deleted file mode 100644 index 6ac88fd..0000000 --- a/resources/views/components/hexagon-grid.blade.php +++ /dev/null @@ -1,50 +0,0 @@ -@props(['teams']) - - - -
{{ Str::limit($team->description, 100) }}
- @endif -- Membres: {{ $team->users()->count() }} -
-- Projets: {{ $team->projects()->count() }} -
-- Créée le {{ $team->created_at->format('d/m/Y') }} -
+{{ Str::limit($team->description, 100) }}
+ @endif ++ Membres: {{ $team->users()->count() }} +
++ Projets: {{ $team->projects()->count() }} +
++ Créée le {{ $team->created_at->format('d/m/Y') }} +
+{{ Str::limit($project->description, 100) }}
- @endif -{{ Str::limit($project->description, 100) }}
+ @endif ++ Période: + @if($project->start_date) + {{ $project->start_date->format('d/m/Y') }} + @else + Non définie + @endif + @if($project->end_date) + - {{ $project->end_date->format('d/m/Y') }} + @endif +
+ @endif- Période: - @if($project->start_date) - {{ $project->start_date->format('d/m/Y') }} - @else - Non définie - @endif - @if($project->end_date) - - {{ $project->end_date->format('d/m/Y') }} - @endif + Statut: + + {{ $project->status === 'active' ? 'Actif' : 'Archivé' }} +
- @endif -- Statut: - - {{ $project->status === 'active' ? 'Actif' : 'Archivé' }} - -
-- Tâches: {{ $project->tasks()->count() }} -
-- Propriétaire: {{ $project->owner->name }} -
-- Créé le {{ $project->created_at->format('d/m/Y') }} -
++ Tâches: {{ $project->tasks()->count() }} +
++ Propriétaire: {{ $project->owner->name }} +
++ Créé le {{ $project->created_at->format('d/m/Y') }} +
+{{ $comment->content }}