search) { $query->where('name', 'like', '%' . $this->search . '%') ->orWhere('description', 'like', '%' . $this->search . '%'); } if ($this->statusFilter) { $query->where('status', $this->statusFilter); } $projects = $query->orderBy('name')->get(); return view('livewire.projects.index', [ 'projects' => $projects, 'statuses' => Project::STATUSES, 'totalProjects' => Project::count(), 'activeProjects' => Project::active()->count(), 'completedProjects' => Project::completed()->count(), ]); } public function create(): void { $this->resetForm(); $this->showForm = true; } public function edit(int $id): void { $project = Project::findOrFail($id); $this->editingId = $project->id; $this->name = $project->name; $this->description = $project->description; $this->status = $project->status; $this->dueAt = $project->due_at?->format('Y-m-d\TH:i') ?? ''; $this->showForm = true; } public function save(): void { $validated = $this->validate([ 'name' => ['required', 'string', 'max:255'], 'description' => ['nullable', 'string'], 'status' => ['required', 'string', 'in:' . implode(',', Project::STATUSES)], 'dueAt' => ['nullable', 'date'], ]); Project::updateOrCreate(['id' => $this->editingId], [ 'name' => $validated['name'], 'description' => $validated['description'], 'status' => $validated['status'], 'due_at' => $validated['dueAt'] ?: null, ]); $this->resetForm(); $this->showForm = false; } public function delete(int $id): void { Project::findOrFail($id)->delete(); } public function clearFilters(): void { $this->search = ''; $this->statusFilter = ''; } public function resetForm(): void { $this->editingId = null; $this->name = ''; $this->description = null; $this->status = 'active'; $this->dueAt = null; $this->resetValidation(); } public function getTasksCount(int $projectId): int { return \App\Models\Task::where('project_id', $projectId)->count(); } public function getStatusColor(string $status): string { return match ($status) { 'active' => 'bg-green-100 text-green-800', 'completed' => 'bg-blue-100 text-blue-800', 'archived' => 'bg-gray-100 text-gray-800', 'on_hold' => 'bg-yellow-100 text-yellow-800', 'planned' => 'bg-purple-100 text-purple-800', default => 'bg-gray-100 text-gray-800', }; } }