has('project_id')) { $this->projectFilter = (int) request('project_id'); } } public function render() { $query = Task::with(['project', 'comments']); if ($this->search) { $query->where('title', 'like', '%' . $this->search . '%') ->orWhere('description', 'like', '%' . $this->search . '%'); } if ($this->statusFilter) { $query->where('status', $this->statusFilter); } if ($this->priorityFilter) { $query->where('priority', $this->priorityFilter); } if ($this->projectFilter) { $query->where('project_id', $this->projectFilter); } $tasks = $query->orderBy('priority', 'desc')->orderBy('created_at')->get(); return view('livewire.tasks.index', [ 'tasks' => $tasks, 'projects' => Project::orderBy('name')->get(), 'statuses' => Task::STATUSES, 'totalTasks' => Task::count(), 'todoTasks' => Task::todo()->count(), 'inProgressTasks' => Task::inProgress()->count(), 'doneTasks' => Task::done()->count(), 'blockedTasks' => Task::blocked()->count(), 'waitingReviewTasks' => Task::waitingReview()->count(), 'dueSoonTasks' => Task::dueSoon()->count(), 'overdueTasks' => Task::overdue()->count(), ]); } public function create(): void { $this->resetForm(); // Pre-select the filtered project if one is selected if ($this->projectFilter) { $this->projectId = $this->projectFilter; } $this->showForm = true; } public function edit(int $id): void { $task = Task::findOrFail($id); $this->editingId = $task->id; $this->title = $task->title; $this->description = $task->description; $this->status = $task->status; $this->projectId = $task->project_id; $this->priority = $task->priority; $this->dueAt = $task->due_at?->format('Y-m-d\TH:i') ?? ''; $this->estimatedHours = $task->estimated_hours; $this->actualHours = $task->actual_hours; $this->showForm = true; } public function save(): void { $validated = $this->validate([ 'title' => ['required', 'string', 'max:255'], 'description' => ['nullable', 'string'], 'status' => ['required', 'string', 'in:' . implode(',', Task::STATUSES)], 'projectId' => ['nullable', 'integer', 'exists:projects,id'], 'priority' => ['integer', 'min:0', 'max:10'], 'dueAt' => ['nullable', 'date'], 'estimatedHours' => ['nullable', 'numeric', 'min:0'], 'actualHours' => ['nullable', 'numeric', 'min:0'], ]); Task::updateOrCreate(['id' => $this->editingId], [ 'title' => $validated['title'], 'description' => $validated['description'], 'status' => $validated['status'], 'project_id' => $validated['projectId'], 'priority' => $validated['priority'], 'due_at' => $validated['dueAt'] ?: null, 'estimated_hours' => $validated['estimatedHours'] ?: null, 'actual_hours' => $validated['actualHours'] ?: null, ]); $this->resetForm(); $this->showForm = false; } public function delete(int $id): void { Task::findOrFail($id)->delete(); } public function changeStatus(int $id, string $newStatus): void { if (!in_array($newStatus, Task::STATUSES)) { return; } $task = Task::findOrFail($id); $task->update(['status' => $newStatus]); // Auto-set timestamps based on status if ($newStatus === 'in_progress' && !$task->started_at) { $task->update(['started_at' => now()]); } if ($newStatus === 'done' && !$task->completed_at) { $task->update(['completed_at' => now()]); } if ($newStatus !== 'in_progress' && $newStatus !== 'done') { $task->update(['started_at' => null, 'completed_at' => null]); } } public function clearFilters(): void { $this->search = ''; $this->statusFilter = ''; $this->priorityFilter = ''; $this->projectFilter = null; } public function resetForm(): void { $this->editingId = null; $this->title = ''; $this->description = null; $this->status = 'todo'; $this->projectId = null; $this->priority = 0; $this->dueAt = null; $this->estimatedHours = null; $this->actualHours = null; $this->resetValidation(); } public function getStatusColor(string $status): string { return match ($status) { 'todo' => 'bg-gray-100 text-gray-800', 'in_progress' => 'bg-blue-100 text-blue-800', 'done' => 'bg-green-100 text-green-800', 'blocked' => 'bg-red-100 text-red-800', 'waiting_review' => 'bg-yellow-100 text-yellow-800', default => 'bg-gray-100 text-gray-800', }; } public function getPriorityLabel(int $priority): string { if ($priority === 0) return 'None'; if ($priority <= 3) return 'Low'; if ($priority <= 6) return 'Medium'; if ($priority <= 8) return 'High'; return 'Critical'; } public function getCommentsCount(int $taskId): int { return \App\Models\TaskComment::where('task_id', $taskId)->count(); } public function startTracking(int $id): void { $task = Task::findOrFail($id); if ($task->status !== 'in_progress') { $task->update(['status' => 'in_progress', 'started_at' => now()]); } } public function stopTracking(int $id): void { // This would need more complex time tracking logic // For now, just mark as done $task = Task::findOrFail($id); $task->update(['status' => 'done', 'completed_at' => now()]); } }