'required|file|mimes:geojson,kmz,kml,shp,dwg,zip|max:51200', 'layerName' => 'required|string|max:255', 'layerColor' => 'nullable|string|size:7', ]; public function mount(Project $project, Phase $phase) { $this->project = $project; $this->phase = $phase; $this->loadLayers(); if ($this->phase->project_id !== $this->project->id) { abort(404); } // Por defecto todas visibles $this->visibleLayers = $this->layers->pluck('id')->toArray(); $this->emitInitialLayersData(); } public function loadLayers() { $this->layers = Layer::where('phase_id', $this->phase->id)->latest()->get(); // Eliminar de visibles las que ya no existen $this->visibleLayers = array_intersect($this->visibleLayers, $this->layers->pluck('id')->toArray()); } private function emitInitialLayersData() { $layersData = $this->layers->map(function($layer) { return [ 'id' => $layer->id, 'geojson' => $layer->geojson_data, 'color' => $layer->geojson_data['style']['color'] ?? '#3b82f6', ]; }); $this->dispatch('initialLayersData', [ 'layers' => $layersData, 'visibleLayers' => $this->visibleLayers, 'selectedLayerId' => $this->selectedLayer?->id, ]); } public function toggleLayerVisibility($layerId) { if ($this->selectedLayer && $this->selectedLayer->id == $layerId) { session()->flash('info', 'No puedes ocultar la capa que estás editando.'); return; } if (in_array($layerId, $this->visibleLayers)) { $this->visibleLayers = array_diff($this->visibleLayers, [$layerId]); } else { $this->visibleLayers[] = $layerId; } $this->dispatch('visibilityChanged', $this->visibleLayers); } public function selectLayer($layerId) { $this->selectedLayer = Layer::find($layerId); if (!$this->selectedLayer) return; // Asegurar que la capa seleccionada está visible if (!in_array($layerId, $this->visibleLayers)) { $this->visibleLayers[] = $layerId; $this->dispatch('visibilityChanged', $this->visibleLayers); } $geojson = $this->selectedLayer->geojson_data; $this->dispatch('layerSelectedForEdit', [ 'layerId' => $layerId, 'geojson' => $geojson, 'color' => $geojson['style']['color'] ?? '#3b82f6', ]); session()->flash('info', 'Editando capa: ' . $this->selectedLayer->name); } public function importFile() { $this->validate(); $user = Auth::user(); if (!$user->can('upload layers') && !$user->hasRole('Admin')) { session()->flash('error', 'Sin permisos.'); return; } $projectDir = "uploads/projects/{$this->project->id}/layers"; $originalPath = $this->uploadFile->store($projectDir, 'public'); $geojson = SpatialFileConverter::convertToGeoJson($this->uploadFile); if (!$geojson) { session()->flash('error', 'Conversión fallida.'); return; } $geojson['style'] = ['color' => $this->layerColor ?: '#3b82f6']; $layer = Layer::create([ 'project_id' => $this->project->id, 'phase_id' => $this->phase->id, 'name' => $this->layerName, 'geojson_data' => $geojson, 'original_file' => $originalPath, 'uploaded_by' => $user->id, ]); $this->loadLayers(); $this->visibleLayers[] = $layer->id; $this->reset(['uploadFile', 'layerName']); $this->emitInitialLayersData(); session()->flash('message', 'Capa importada.'); } public function createEmptyLayer() { $user = Auth::user(); $emptyGeojson = [ 'type' => 'FeatureCollection', 'features' => [], 'style' => ['color' => $this->layerColor ?: '#3b82f6'] ]; $layer = Layer::create([ 'project_id' => $this->project->id, 'phase_id' => $this->phase->id, 'name' => $this->layerName ?: 'Nueva capa', 'geojson_data' => $emptyGeojson, 'original_file' => null, 'uploaded_by' => $user->id, ]); $this->loadLayers(); $this->visibleLayers[] = $layer->id; $this->selectLayer($layer->id); $this->emitInitialLayersData(); session()->flash('message', 'Capa vacía creada y seleccionada.'); } public function saveManualGeojson($geojsonString) { if (!$this->selectedLayer) { session()->flash('error', 'No hay capa seleccionada.'); return; } $geojson = json_decode($geojsonString, true); if (json_last_error() !== JSON_ERROR_NONE) { session()->flash('error', 'GeoJSON inválido.'); return; } $geojson['style'] = ['color' => $this->layerColor ?: ($this->selectedLayer->geojson_data['style']['color'] ?? '#3b82f6')]; $this->selectedLayer->geojson_data = $geojson; $this->selectedLayer->save(); $this->loadLayers(); // recargar por si acaso $this->selectLayer($this->selectedLayer->id); $this->emitInitialLayersData(); session()->flash('message', 'Capa guardada.'); } public function deleteLayer($layerId) { $user = Auth::user(); if (!$user->can('delete layers') && !$user->hasRole('Admin')) abort(403); $layer = Layer::find($layerId); if (!$layer) return; if ($layer->original_file) Storage::disk('public')->delete($layer->original_file); $layer->delete(); $this->loadLayers(); if ($this->selectedLayer && $this->selectedLayer->id == $layerId) { $this->selectedLayer = null; } $this->emitInitialLayersData(); session()->flash('message', 'Capa eliminada.'); } public function cancelEditing() { $this->selectedLayer = null; $this->dispatch('layerSelectedForEdit', null); } public function render() { return view('livewire.layer-manager'); } }