Files
construprogress/app/Livewire/Projects/Traits/MapFeatures.php
T

217 lines
7.8 KiB
PHP
Raw Normal View History

<?php
namespace App\Livewire\Projects\Traits;
use App\Models\Feature;
use App\Models\InspectionTemplate;
use App\Models\Issue;
use App\Notifications\InspectionCompletedNotification;
use App\Notifications\InspectionDeletedNotification;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Livewire\Attributes\On;
trait MapFeatures
{
// Editor properties
public $selectedFeature = null;
public $selectedPhaseId = null;
public $editProgress = 0;
public $editComment = '';
public $editResponsible = '';
public $editPhotos = [];
public $formFullscreen = false;
// Tab management
public $activeTab = 'edit';
public $allFeatures;
public $allInspections;
// Imágenes en mapa
public $showFeatureImages = false;
public $featureImageMarkers = [];
// Feature status ─────────────────────────────────────────────────────────
public function editFeatureStatus($status)
{
if (! $this->selectedFeature) {
return;
}
$feature = Feature::with('layer.phase')->findOrFail($this->selectedFeature->id);
if ($feature->layer->phase->project_id !== $this->project->id) {
abort(403);
}
$feature->status = $status;
if ($status === 'completed') {
$feature->progress = 100;
}
if ($status === 'planned') {
$feature->progress = 0;
}
$feature->save();
$this->selectedFeature = $feature;
$this->editProgress = $feature->progress;
$this->allFeatures = $this->allFeatures->map(fn ($f) => $f->id === $feature->id ? $feature : $f);
$this->dispatch('featureStatusChanged', $feature->id, $feature->status, $feature->status_color);
$this->dispatch('notify', 'Estado actualizado');
}
public function updateProgress($featureId, $newProgress, $comment = null)
{
$feature = Feature::with('layer.phase')->findOrFail($featureId);
$user = Auth::user();
if (! $user->can('update progress')) {
$this->dispatch('notify', 'Sin permisos');
return;
}
if ($feature->layer->phase->project_id !== $this->project->id) {
abort(403);
}
$feature->progress = min(100, max(0, $newProgress));
$feature->save();
$phase = $feature->layer->phase;
$phase->progress_percent = $phase->features()->avg('progress') ?: 0;
$phase->save();
$phase->progressUpdates()->create([
'user_id' => $user->id,
'progress_percent' => $phase->progress_percent,
'comment' => $comment,
]);
$this->dispatch('progressUpdated', $featureId, $feature->progress);
$this->dispatch('notify', 'Progreso actualizado');
if ($this->selectedFeature && $this->selectedFeature->id == $featureId) {
$this->selectedFeature->progress = $feature->progress;
$this->editProgress = $feature->progress;
}
}
#[On('map-select-feature')]
public function selectFeature($featureId)
{
\Log::info('[ProjectMap] map-select-feature received', ['payload' => $featureId, 'type' => gettype($featureId)]);
// Handle both formats: direct ID or { featureId: X }
if (is_array($featureId) && isset($featureId['featureId'])) {
$featureId = $featureId['featureId'];
\Log::info('[ProjectMap] Extracted featureId from array', ['featureId' => $featureId]);
}
$this->selectedFeature = null;
$feature = Feature::with(['template', 'layer.phase'])->find($featureId);
if (! $feature) {
\Log::warning('[ProjectMap] Feature not found', ['featureId' => $featureId]);
return;
}
if ($feature->layer->phase->project_id !== $this->project->id) {
\Log::warning('[ProjectMap] Feature not in project', ['featureId' => $featureId, 'projectId' => $this->project->id]);
abort(403);
}
$this->selectedFeature = $feature;
$this->selectedPhaseId = $feature->layer->phase_id;
$this->editProgress = $feature->progress;
$this->editResponsible = $feature->responsible ?? '';
$this->editPhotos = $feature->properties['photos'] ?? [];
$this->selectedTemplateId = $feature->template_id;
$this->activeTab = 'edit';
$this->loadInspectionHistory();
$this->resetInspectionForm();
$this->dispatch('featureSelected', $featureId, $feature->name);
}
public function saveFeatureProgress()
{
if (! $this->selectedFeature) {
return;
}
$feature = Feature::with('layer.phase')->findOrFail($this->selectedFeature->id);
if ($feature->layer->phase->project_id !== $this->project->id) {
abort(403);
}
$feature->progress = min(100, max(0, (int) $this->editProgress));
$feature->responsible = $this->editResponsible;
$feature->save();
$this->selectedFeature = $feature;
$phase = $feature->layer->phase;
$phase->progress_percent = $phase->features()->avg('progress') ?: 0;
$phase->save();
$this->dispatch('progressUpdated', $phase->id, $phase->progress_percent);
$this->dispatch('notify', 'Progreso guardado');
}
// ─── Feature Images ────────────────────────────────────────────────────────
public function toggleFeatureImages()
{
$this->showFeatureImages = ! $this->showFeatureImages;
$this->loadFeatureImageMarkers();
$this->dispatch('featureImagesToggled', $this->showFeatureImages, $this->featureImageMarkers);
}
public function loadFeatureImageMarkers()
{
if (! $this->showFeatureImages) {
$this->featureImageMarkers = [];
return;
}
$markers = [];
foreach ($this->phases as $phase) {
foreach ($phase->layers as $layer) {
foreach ($layer->features as $feature) {
$image = $feature->images->first();
if ($image) {
$geo = $feature->geometry;
$coords = null;
if ($geo && isset($geo['coordinates'])) {
if ($geo['type'] === 'Point') {
$coords = ['lat' => $geo['coordinates'][1], 'lng' => $geo['coordinates'][0]];
} elseif (in_array($geo['type'], ['Polygon', 'MultiPolygon'])) {
$firstRing = $geo['type'] === 'Polygon' ? $geo['coordinates'][0] : $geo['coordinates'][0][0];
$coords = ['lat' => $firstRing[0][1], 'lng' => $firstRing[0][0]];
}
}
if ($coords && $coords['lat'] && $coords['lng']) {
$markers[] = [
'feature_id' => $feature->id,
'name' => $feature->name,
'lat' => $coords['lat'],
'lng' => $coords['lng'],
'image_url' => $image->url,
'image_name' => $image->name,
];
}
}
}
}
}
$this->featureImageMarkers = $markers;
}
public function toggleFullscreen()
{
$this->formFullscreen = ! $this->formFullscreen;
if (! $this->formFullscreen) {
$this->dispatch('mapResize');
}
}
public function setActiveTab($tab)
{
$this->activeTab = $tab;
}
}