diff --git a/app/Livewire/Client/ClientProjects.php b/app/Livewire/Client/ClientProjects.php index cf2ea96..1f24371 100644 --- a/app/Livewire/Client/ClientProjects.php +++ b/app/Livewire/Client/ClientProjects.php @@ -7,6 +7,7 @@ use App\Models\Project; use App\Models\Phase; use App\Models\Inspection; use App\Models\Feature; +use App\Models\ChangeOrder; use Carbon\Carbon; class ClientProjects extends Component @@ -49,7 +50,8 @@ class ClientProjects extends Component $project = Project::with([ 'phases.features', - 'inspections.template' + 'inspections.template', + 'changeOrders' // Load change orders for this project ])->find($this->selectedProject); if (!$project) { @@ -66,68 +68,103 @@ class ClientProjects extends Component 'progress' => $project->phases->avg('progress_percent') ?? 0, ]; - // Get recent images (simulated for now) - $this->galleryImages = [ - [ - 'url' => 'https://via.placeholder.com/400x300?text=Avance+1', - 'title' => 'Avance inicial', - 'date' => now()->subDays(30)->format('d/m/Y') - ], - [ - 'url' => 'https://via.placeholder.com/400x300?text=Avance+2', - 'title' => 'Estructura levantada', - 'date' => now()->subDays(15)->format('d/m/Y') - ], - [ - 'url' => 'https://via.placeholder.com/400x300?text=Avance+3', - 'title' => 'Instalaciones', - 'date' => now()->subDays(5)->format('d/m/Y') - ] - ]; + // Get recent images (we can fetch from media table if needed, but for now we'll keep simulated or link to real) + // For simplicity, we'll try to get some media images for the project + $mediaImages = $project->media() + ->where('category', 'image') + ->latest() + ->take(3) + ->get() + ->map(function($media) { + return [ + 'url' => $media->url, + 'title' => $media->name, + 'date' => $media->created_at->format('d/m/Y') + ]; + }) + ->toArray(); - // Get change orders (simulated for now) - $this->changeOrders = [ - [ - 'id' => 124, - 'title' => 'Ampliación de zona de almacenamiento', - 'description' => 'Solicitud de ampliación de zona de almacenamiento debido a cambios logísticos.', - 'status' => 'pending', - 'requested_at' => now()->subDays(10)->format('d/m/Y'), - 'amount' => 1500.00 - ], - [ - 'id' => 125, - 'title' => 'Cambio de material en acabados interiores', - 'description' => 'Cambio de cerámica estándar a porcelanato en baños y cocinas.', - 'status' => 'pending', - 'requested_at' => now()->subDays(5)->format('d/m/Y'), - 'amount' => 3200.00 - ] - ]; + // If we don't have 3 images, we can fallback to placeholders or just use what we have + if (count($mediaImages) > 0) { + $this->galleryImages = $mediaImages; + } else { + // Fallback to placeholders + $this->galleryImages = [ + [ + 'url' => 'https://via.placeholder.com/400x300?text=Avance+1', + 'title' => 'Avance inicial', + 'date' => now()->subDays(30)->format('d/m/Y') + ], + [ + 'url' => 'https://via.placeholder.com/400x300?text=Avance+2', + 'title' => 'Estructura levantada', + 'date' => now()->subDays(15)->format('d/m/Y') + ], + [ + 'url' => 'https://via.placeholder.com/400x300?text=Avance+3', + 'title' => 'Instalaciones', + 'date' => now()->subDays(5)->format('d/m/Y') + ] + ]; + } + + // Get change orders for this project + $this->changeOrders = $project->changeOrders + ->orderBy('requested_at', 'desc') + ->get() + ->map(function($order) { + return [ + 'id' => $order->id, + 'title' => $order->title, + 'description' => $order->description, + 'status' => $order->status, + 'requested_at' => $order->requested_at->format('d/m/Y'), + 'amount' => $order->amount + ]; + }) + ->toArray(); } public function approveChangeOrder($orderId) { - // In a real app, this would update the database - foreach ($this->changeOrders as &$order) { - if ($order['id'] == $orderId) { - $order['status'] = 'approved'; - break; + // Update the change order in the database + $changeOrder = ChangeOrder::find($orderId); + if ($changeOrder) { + // Check that the change order belongs to the selected project (security) + if ($changeOrder->project_id == $this->selectedProject) { + $changeOrder->status = 'approved'; + $changeOrder->responded_at = now()->toDateString(); + $changeOrder->responded_by = auth()->id(); + $changeOrder->save(); + + // Refresh the change orders list + $this->loadProjectDetails(); + + // Notify any listeners (optional) + $this->dispatch('changeOrderUpdated', ['id' => $orderId, 'status' => 'approved']); } } - $this->dispatch('changeOrderUpdated', ['id' => $orderId, 'status' => 'approved']); } public function rejectChangeOrder($orderId) { - // In a real app, this would update the database - foreach ($this->changeOrders as &$order) { - if ($order['id'] == $orderId) { - $order['status'] = 'rejected'; - break; + // Update the change order in the database + $changeOrder = ChangeOrder::find($orderId); + if ($changeOrder) { + // Check that the change order belongs to the selected project (security) + if ($changeOrder->project_id == $this->selectedProject) { + $changeOrder->status = 'rejected'; + $changeOrder->responded_at = now()->toDateString(); + $changeOrder->responded_by = auth()->id(); + $changeOrder->save(); + + // Refresh the change orders list + $this->loadProjectDetails(); + + // Notify any listeners (optional) + $this->dispatch('changeOrderUpdated', ['id' => $orderId, 'status' => 'rejected']); } } - $this->dispatch('changeOrderUpdated', ['id' => $orderId, 'status' => 'rejected']); } public function render() diff --git a/app/Livewire/ProjectTable.php.bak b/app/Livewire/ProjectTable.php.bak deleted file mode 100644 index a800e1a..0000000 --- a/app/Livewire/ProjectTable.php.bak +++ /dev/null @@ -1,111 +0,0 @@ -setPrimaryKey('id') - ->setDefaultSort('created_at', 'desc') - ->setTableAttributes(['class' => 'table-auto w-full']) - ->setThAttributes(['class' => 'px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider']) - ->setTdAttributes(['class' => 'px-4 py-2 whitespace-nowrap text-sm text-gray-900']); - - $this->addColumn('name', __('Project Name')) - ->setSortable() - ->setSearchable(); - - $this->addColumn('address', __('Address')) - ->setSortable() - ->setSearchable(); - - $this->addColumn('status', __('Status')) - ->setSortable() - ->setFilterable([ - 'planning' => __('Planning'), - 'in_progress' => __('In progress'), - 'paused' => __('Paused'), - 'completed' => __('Completed'), - ]) - ->setLabel(fn ($value, $row, $column, $component) => - match ($value) { - 'planning' => ''.__('Planning').'', - 'in_progress' => ''.__('In progress').'', - 'paused' => ''.__('Paused').'', - 'completed' => ''.__('Completed').'', - default => $value - } - ); - - $this->addColumn('start_date', __('Start Date')) - ->setSortable() - ->setFormat(fn ($value, $row, $column) => $value ? $value->format('Y-m-d') : ''); - - $this->addColumn('end_date_estimated', __('Estimated End Date')) - ->setSortable() - ->setFormat(fn ($value, $row, $column) => $value ? $value->format('Y-m-d') : ''); - - $this->addColumn('actions', __('Actions')) - ->setLabel(fn ($row) => '
| Nombre | -Descripción | -Fase | -Campos | -Acciones | -
|---|---|---|---|---|
| {{ $template->name }} | -{{ $template->description ?? '-' }} | -{{ $template->phase ? $template->phase->name : 'Global' }} | -{{ count($template->fields) }} | -- - - | -
| No hay templates creados. Presiona "Nuevo template" para comenzar. | -||||