setPrimaryKey('id') ->setDefaultSort('order', 'asc') ->setSortingPillsEnabled(false) ->setAdditionalSelects(['phases.id as id', 'phases.order as order']); } /** Re-render when the parent (PhaseList) creates/edits a phase. */ #[On('phases-changed')] public function refreshRows(): void { // no-op: triggers a re-render so the builder re-runs with fresh data. } public function builder(): Builder { $user = Auth::user(); abort_unless( $user->can('manage all') || $user->can('edit projects') || Project::whereKey($this->projectId)->whereHas('users', fn ($q) => $q->where('user_id', $user->id))->exists(), 403 ); return Phase::where('phases.project_id', $this->projectId); } public function columns(): array { return [ Column::make('Orden', 'order')->sortable(), Column::make('Nombre', 'name') ->sortable() ->searchable() ->format(function ($value, $row) { $html = ''.e($value).''; if ($row->description) { $html .= '
'.e(\Illuminate\Support\Str::limit($row->description, 60)).'
'; } return $html; }) ->html(), Column::make('Progreso', 'progress_percent') ->sortable() ->format(fn ($value) => '
'.(int) $value.'%
') ->html(), Column::make('Fechas') ->label(function ($row) { $ps = $row->planned_start?->format('d/m/Y'); $pe = $row->planned_end?->format('d/m/Y'); if (! $ps && ! $pe) { return ''; } return ''.($ps ?: '?').' → '.($pe ?: '?').''; }) ->html(), Column::make('Color', 'color') ->format(fn ($value) => '
') ->html(), Column::make('Acciones') ->label(function ($row) { $user = Auth::user(); $progress = route('phases.progress', $row->id); $html = '
'; $html .= ' '; if ($user->can('manage phases')) { $html .= ''; $html .= ''; } $html .= '
'; return $html; }) ->html(), ]; } public function deletePhase(int $id): void { abort_unless(Auth::user()->can('manage phases'), 403); Phase::where('project_id', $this->projectId)->findOrFail($id)->delete(); $this->dispatch('phases-changed'); $this->dispatch('notify', 'Fase eliminada'); } }