'required|file|max:51200', 'layerName' => 'required|string|max:255', 'layerColor' => 'nullable|string|size:7', ]; public function mount($projectId = null, $phaseId = null) { $this->projectId = $projectId; $this->phaseId = $phaseId; } public function upload() { $user = Auth::user(); if (!$user->can('upload layers') && !$user->hasRole('Admin')) { session()->flash('error', 'Sin permisos.'); return; } $this->validate(); if (!$this->projectId || !$this->phaseId) { session()->flash('error', 'Faltan datos del proyecto/fase.'); return; } $project = Project::findOrFail($this->projectId); $phase = Phase::findOrFail($this->phaseId); $extension = strtolower($this->uploadFile->getClientOriginalExtension()); $mime = $this->uploadFile->getMimeType(); $allowedExtensions = ['geojson', 'kmz', 'kml', 'shp', 'dwg', 'zip']; $allowedMimes = [ 'application/vnd.google-earth.kml+xml', 'application/vnd.google-earth.kmz', 'application/zip', 'application/x-zip-compressed', 'application/x-shapefile', 'image/vnd.dwg', 'application/acad', 'application/geo+json', 'text/xml', 'application/xml', ]; if (!in_array($extension, $allowedExtensions) && !in_array($mime, $allowedMimes)) { session()->flash('error', 'Tipo de archivo no permitido.'); return; } $projectDir = "uploads/projects/{$project->id}/layers"; $originalPath = $this->uploadFile->store($projectDir, 'public'); $geojson = SpatialFileConverter::convertToGeoJson($this->uploadFile); if (!$geojson) { session()->flash('error', 'Conversión fallida.'); return; } $layerColor = $this->layerColor ?: '#3b82f6'; $geojson['style'] = ['color' => $layerColor]; $layer = Layer::create([ 'project_id' => $project->id, 'phase_id' => $phase->id, 'name' => $this->layerName, 'color' => $layerColor, 'original_file' => $originalPath, 'uploaded_by' => $user->id, ]); if (isset($geojson['features'])) { foreach ($geojson['features'] as $featureData) { Feature::create([ 'layer_id' => $layer->id, 'name' => $featureData['properties']['name'] ?? null, 'geometry' => $featureData['geometry'], 'properties' => $featureData['properties'] ?? [], 'template_id' => $featureData['properties']['template_id'] ?? null, 'progress' => $featureData['properties']['progress'] ?? 0, 'responsible' => $featureData['properties']['responsible'] ?? null, ]); } } $this->reset(['uploadFile', 'layerName']); session()->flash('message', "Capa '{$layer->name}' importada correctamente con " . count($geojson['features'] ?? []) . ' elementos.'); $this->dispatch('layerUploaded', projectId: $project->id); } public function render() { $projects = Project::accessibleBy(Auth::user())->get(); $phases = $this->projectId ? Phase::where('project_id', $this->projectId)->orderBy('order')->get() : collect(); return view('livewire.layer-upload', compact('projects', 'phases')); } }