Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
146 changes: 146 additions & 0 deletions app/Livewire/Admin/UserManagement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
<?php

namespace App\Livewire\Admin;

use App\Models\User;
use App\Models\Team;
use Livewire\Component;
use Livewire\WithPagination;
use Illuminate\Support\Facades\Auth;

class UserManagement extends Component
{
use WithPagination;

// Filtres
public $search = '';
public $emailFilter = '';
public $teamFilter = '';
public $roleFilter = '';

// Tri
public $sortBy = 'name';
public $sortDirection = 'asc';

// Modal de confirmation
public $showPromoteModal = false;
public $userToPromote = null;

protected $queryString = [
'search' => ['except' => ''],
'emailFilter' => ['except' => ''],
'teamFilter' => ['except' => ''],
'roleFilter' => ['except' => ''],
'sortBy' => ['except' => 'name'],
'sortDirection' => ['except' => 'asc'],
];

public function mount()
{
// Vérifier que l'utilisateur est admin du site
if (Auth::user()->role !== User::ROLE_ADMIN) {
abort(403, 'Accès refusé. Réservé aux administrateurs du site.');
}
}

public function updatingSearch()
{
$this->resetPage();
}

public function updatingEmailFilter()
{
$this->resetPage();
}

public function updatingTeamFilter()
{
$this->resetPage();
}

public function updatingRoleFilter()
{
$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 clearFilters()
{
$this->reset(['search', 'emailFilter', 'teamFilter', 'roleFilter']);
$this->resetPage();
}

public function confirmPromoteUser($userId)
{
$this->userToPromote = User::find($userId);
$this->showPromoteModal = true;
}

public function promoteToAdmin()
{
if ($this->userToPromote && $this->userToPromote->role !== User::ROLE_ADMIN) {
$this->userToPromote->update(['role' => User::ROLE_ADMIN]);

$this->dispatch('flash', [
'type' => 'success',
'text' => "L'utilisateur {$this->userToPromote->name} a été promu administrateur du site."
]);
}

$this->reset(['showPromoteModal', 'userToPromote']);
}

public function demoteFromAdmin($userId)
{
$user = User::find($userId);
if ($user && $user->role === User::ROLE_ADMIN && $user->id !== Auth::id()) {
$user->update(['role' => User::ROLE_USER]);

$this->dispatch('flash', [
'type' => 'success',
'text' => "L'utilisateur {$user->name} n'est plus administrateur du site."
]);
}
}

public function render()
{
$users = User::query()
->when($this->search, function ($query) {
$query->where('name', 'like', "%{$this->search}%");
})
->when($this->emailFilter, function ($query) {
$query->where('email', 'like', "%{$this->emailFilter}%");
})
->when($this->roleFilter, function ($query) {
$query->where('role', $this->roleFilter);
})
->when($this->teamFilter, function ($query) {
$query->whereHas('teams', function ($q) {
$q->where('teams.id', $this->teamFilter);
});
})
->with(['teams' => function ($query) {
$query->select('teams.id', 'teams.name');
}])
->orderBy($this->sortBy, $this->sortDirection)
->paginate(20);

$teams = Team::select('id', 'name')->orderBy('name')->get();

return view('livewire.admin.user-management', [
'users' => $users,
'teams' => $teams,
]);
}
}
32 changes: 32 additions & 0 deletions app/Livewire/CommentComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
29 changes: 28 additions & 1 deletion app/Livewire/Dashboard.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

use App\Models\Team;
use App\Models\TeamUser;
use App\Models\User;
use Livewire\Component;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;

class Dashboard extends Component
{
Expand Down Expand Up @@ -44,9 +46,34 @@ 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()
{
$teams = Auth::user()->teams()->get();
$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;
}

return view('livewire.dashboard', [
'teams' => $teams
Expand Down
28 changes: 27 additions & 1 deletion app/Livewire/ProjectComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -29,7 +30,9 @@ public function mount($teamId)
$query->withPivot('role');
}])->findOrFail($teamId);

if (! $this->team->users->pluck('id')->contains(Auth::id())) {
// Vérifier l'accès : admin du site OU membre de l'équipe
$user = Auth::user();
if ($user->role !== 'admin' && !$this->team->users->pluck('id')->contains(Auth::id())) {
abort(403, 'Vous n\'êtes pas membre de cette équipe.');
}

Expand Down Expand Up @@ -83,6 +86,12 @@ private function checkIfTeamAdmin()
{
$currentUser = Auth::user();

// Admin du site a tous les droits
if ($currentUser->role === 'admin') {
$this->isTeamAdmin = true;
return;
}

if ($this->team->owner_id == $currentUser->id) {
$this->isTeamAdmin = true;
return;
Expand Down Expand Up @@ -164,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();
Expand Down
41 changes: 38 additions & 3 deletions app/Livewire/TaskComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -43,8 +44,9 @@ public function mount($projectId)
$this->projectId = $projectId;
$this->project = Project::with('team')->findOrFail($projectId);

// Vérifier que l'utilisateur fait partie de l'équipe
if (!$this->project->team->users->contains(Auth::id())) {
// Vérifier l'accès : admin du site OU membre de l'équipe
$user = Auth::user();
if ($user->role !== 'admin' && !$this->project->team->users->contains(Auth::id())) {
abort(403, 'Vous n\'avez pas accès à ce projet.');
}
}
Expand Down Expand Up @@ -145,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';
}
}

Expand All @@ -159,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;
Expand Down
Loading
Loading