Files

210 lines
5.9 KiB
PHP
Raw Permalink Normal View History

<?php
namespace App\Livewire\Ideas;
use App\Models\Idea;
use App\Models\Project;
use Livewire\Attributes\Layout;
use Livewire\Component;
#[Layout('components.layouts.app')]
class Index extends Component
{
public bool $showForm = false;
public ?int $editingId = null;
public string $title = '';
public ?string $description = null;
public string $status = 'new';
public ?int $projectId = null;
public int $priority = 0;
public ?string $category = null;
public ?string $tags = null;
public string $search = '';
public string $statusFilter = '';
public string $categoryFilter = '';
public ?int $projectFilter = null;
public bool $unlinkedFilter = false;
public function render()
{
$query = Idea::with(['project', 'user']);
if ($this->search) {
$query->search($this->search);
}
if ($this->statusFilter) {
$query->where('status', $this->statusFilter);
}
if ($this->categoryFilter) {
$query->where('category', $this->categoryFilter);
}
if ($this->projectFilter) {
$query->where('project_id', $this->projectFilter);
}
if ($this->unlinkedFilter) {
$query->unlinked();
}
$ideas = $query->orderBy('priority', 'desc')->orderBy('created_at', 'desc')->get();
return view('livewire.ideas.index', [
'ideas' => $ideas,
'projects' => Project::orderBy('name')->get(),
'statuses' => Idea::STATUSES,
'categories' => Idea::CATEGORIES,
'totalIdeas' => Idea::count(),
'newIdeas' => Idea::new()->count(),
'consideredIdeas' => Idea::considered()->count(),
'plannedIdeas' => Idea::planned()->count(),
'implementedIdeas' => Idea::implemented()->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
{
$idea = Idea::findOrFail($id);
$this->editingId = $idea->id;
$this->title = $idea->title;
$this->description = $idea->description;
$this->status = $idea->status;
$this->projectId = $idea->project_id;
$this->priority = $idea->priority;
$this->category = $idea->category;
$this->tags = $idea->tags;
$this->showForm = true;
}
public function save(): void
{
$validated = $this->validate([
'title' => ['required', 'string', 'max:255'],
'description' => ['nullable', 'string'],
'status' => ['required', 'string', 'in:' . implode(',', Idea::STATUSES)],
'projectId' => ['nullable', 'integer', 'exists:projects,id'],
'priority' => ['integer', 'min:0', 'max:10'],
'category' => ['nullable', 'string', 'in:' . implode(',', Idea::CATEGORIES)],
'tags' => ['nullable', 'string', 'max:255'],
]);
Idea::updateOrCreate(['id' => $this->editingId], [
'title' => $validated['title'],
'description' => $validated['description'],
'status' => $validated['status'],
'project_id' => $validated['projectId'],
'priority' => $validated['priority'],
'category' => $validated['category'],
'tags' => $validated['tags'],
'user_id' => auth()->id(),
]);
$this->resetForm();
$this->showForm = false;
}
public function delete(int $id): void
{
Idea::findOrFail($id)->delete();
}
public function changeStatus(int $id, string $newStatus): void
{
if (!in_array($newStatus, Idea::STATUSES)) {
return;
}
Idea::findOrFail($id)->update(['status' => $newStatus]);
}
public function linkToProject(int $id, int $projectId): void
{
Idea::findOrFail($id)->update(['project_id' => $projectId]);
}
public function unlinkFromProject(int $id): void
{
Idea::findOrFail($id)->update(['project_id' => null]);
}
public function clearFilters(): void
{
$this->search = '';
$this->statusFilter = '';
$this->categoryFilter = '';
$this->projectFilter = null;
$this->unlinkedFilter = false;
}
public function resetForm(): void
{
$this->editingId = null;
$this->title = '';
$this->description = null;
$this->status = 'new';
$this->projectId = null;
$this->priority = 0;
$this->category = null;
$this->tags = null;
$this->resetValidation();
}
public function getStatusColor(string $status): string
{
return match ($status) {
'new' => 'bg-blue-100 text-blue-800',
'considered' => 'bg-yellow-100 text-yellow-800',
'planned' => 'bg-purple-100 text-purple-800',
'rejected' => 'bg-red-100 text-red-800',
'implemented' => 'bg-green-100 text-green-800',
default => 'bg-gray-100 text-gray-800',
};
}
public function getCategoryColor(string $category): string
{
return match ($category) {
'feature' => 'bg-blue-100 text-blue-800',
'improvement' => 'bg-purple-100 text-purple-800',
'bugfix' => 'bg-red-100 text-red-800',
'research' => 'bg-yellow-100 text-yellow-800',
'other' => 'bg-gray-100 text-gray-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';
}
}