chore: remove obsolete duplicate views/components (superseded code)

Deleted (all superseded, recoverable in git history):
- resources/views/projects/edit.blade.php + ProjectController@edit()
- resources/views/projects/create.blade.php + ProjectController@create()
  (projects.create/edit routes point to the Livewire ProjectForm; these
   controller methods were excluded from the resource and never invoked)
- app/Livewire/ProjectEditTabs.php + project-edit-tabs.blade.php
  (old tabbed editor, functionality recovered inside ProjectForm)
- app/Livewire/LayerUpload.php + layer-upload.blade.php (superseded by LayerManager)

Kept resources/views/livewire/issues/issue-manager.blade.php as a reference
for the future rich Issues screen (its companion component was never built).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-17 14:11:23 +02:00
parent 8101f22413
commit 860c502f32
7 changed files with 0 additions and 561 deletions
@@ -19,15 +19,6 @@ class ProjectController extends Controller
return view('projects.index'); return view('projects.index');
} }
/**
* Show the form for creating a new resource.
*/
public function create()
{
Gate::authorize('create projects');
return view('projects.create');
}
/** /**
* Store a newly created resource in storage. * Store a newly created resource in storage.
*/ */
@@ -58,15 +49,6 @@ class ProjectController extends Controller
return redirect()->route('projects.map', $project); return redirect()->route('projects.map', $project);
} }
/**
* Show the form for editing the specified resource.
*/
public function edit(Project $project) // <--- ROUTE MODEL BINDING
{
Gate::authorize('edit projects', $project);
return view('projects.edit', compact('project'));
}
/** /**
* Update the specified resource in storage. * Update the specified resource in storage.
*/ */
-124
View File
@@ -1,124 +0,0 @@
<?php
namespace App\Livewire;
use Livewire\Component;
use Livewire\WithFileUploads;
use App\Models\Project;
use App\Models\Phase;
use App\Models\Layer;
use App\Models\Feature;
use App\Services\SpatialFileConverter;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
class LayerUpload extends Component
{
use WithFileUploads;
public $projectId;
public $phaseId;
public $uploadFile = null;
public $layerName = '';
public $layerColor = '#3b82f6';
protected $rules = [
'uploadFile' => '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'));
}
}
-42
View File
@@ -1,42 +0,0 @@
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Models\Project;
class ProjectEditTabs extends Component
{
public Project $project;
public string $activeTab = 'project-data';
public function mount(Project $project)
{
$this->project = $project;
}
public function setActiveTab($tab)
{
$this->activeTab = $tab;
}
public function tabChanged($tab, $projectId)
{
if ($projectId == $this->project->id) {
$this->activeTab = $tab;
}
}
public function updateProject()
{
$this->project->save();
session()->flash('message', __('Project updated successfully.'));
$this->dispatch('project-updated');
}
public function render()
{
return view('livewire.project-edit-tabs');
}
}
@@ -1,57 +0,0 @@
<div>
@if(session()->has('message'))
<div class="alert alert-success mb-2">{{ session('message') }}</div>
@endif
@if(session()->has('error'))
<div class="alert alert-error mb-2">{{ session('error') }}</div>
@endif
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title">{{ __("Upload Layer") }}</h2>
<form wire:submit.prevent="upload" class="space-y-4">
<div class="form-control">
<label class="label">{{ __("Project") }}</label>
<select wire:model.live="projectId" class="select select-bordered" required>
<option value="">{{ __("Select project") }}...</option>
@foreach($projects as $p)
<option value="{{ $p->id }}">{{ $p->name }}</option>
@endforeach
</select>
</div>
<div class="form-control">
<label class="label">{{ __("Phase") }}</label>
<select wire:model.live="phaseId" class="select select-bordered" required @if(!$projectId) disabled @endif>
<option value="">{{ __("Select phase") }}...</option>
@foreach($phases as $ph)
<option value="{{ $ph->id }}">{{ $ph->name }}</option>
@endforeach
</select>
</div>
<div class="form-control">
<label class="label">{{ __("Layer name") }}</label>
<input type="text" wire:model="layerName" class="input input-bordered" placeholder="Ej: Cimentación" required />
@error('layerName') <span class="text-error text-sm">{{ $message }}</span> @enderror
</div>
<div class="form-control">
<label class="label">{{ __("Color") }}</label>
<input type="color" wire:model="layerColor" class="input input-bordered w-20" />
</div>
<div class="form-control">
<label class="label">{{ __("File") }} (GeoJSON, KML, KMZ, Shapefile .zip, DWG)</label>
<input type="file" wire:model="uploadFile" class="file-input file-input-bordered" accept=".geojson,.kml,.kmz,.zip,.shp,.dwg" />
@error('uploadFile') <span class="text-error text-sm">{{ $message }}</span> @enderror
</div>
<button type="submit" class="btn btn-primary w-full">
{{ __("Upload Layer") }}
</button>
</form>
</div>
</div>
</div>
@@ -1,126 +0,0 @@
<div>
<!-- Tabs -->
<div class="tab-toggle">
<input type="radio" name="tabs-project-edit-{{ $project->id }}" id="tab-project-data-{{ $project->id }}"
{{ $activeTab === 'project-data' ? 'checked' : '' }} class="tab-toggle" />
<label for="tab-project-data-{{ $project->id }}" class="tab {{ $activeTab === 'project-data' ? 'tab-active' : '' }}">
{{ __('Project Data') }}
</label>
<input type="radio" name="tabs-project-edit-{{ $project->id }}" id="tab-phases-{{ $project->id }}"
{{ $activeTab === 'phases' ? 'checked' : '' }} class="tab-toggle" />
<label for="tab-phases-{{ $project->id }}" class="tab {{ $activeTab === 'phases' ? 'tab-active' : '' }}">
{{ __('Phases') }}
</label>
<input type="radio" name="tabs-project-edit-{{ $project->id }}" id="tab-users-{{ $project->id }}"
{{ $activeTab === 'users' ? 'checked' : '' }} class="tab-toggle" />
<label for="tab-users-{{ $project->id }}" class="tab {{ $activeTab === 'users' ? 'tab-active' : '' }}">
{{ __('Users') }}
</label>
<input type="radio" name="tabs-project-edit-{{ $project->id }}" id="tab-companies-{{ $project->id }}"
{{ $activeTab === 'companies' ? 'checked' : '' }} class="tab-toggle" />
<label for="tab-companies-{{ $project->id }}" class="tab {{ $activeTab === 'companies' ? 'tab-active' : '' }}">
{{ __('Companies') }}
</label>
</div>
<!-- Tab Content -->
<div class="tab-content">
<!-- Project Data Tab -->
<div id="tab-project-data-{{ $project->id }}"
class="tab-content-base p-4 {{ $activeTab === 'project-data' ? '' : 'hidden' }}">
<form wire:submit.prevent="updateProject" class="space-y-4">
@csrf
@method('PUT')
<div>
<label class="label">{{ __('Name') }}</label>
<input type="text" name="name"
wire:model.debounce.500ms="project.name"
class="input input-bordered w-full" required>
</div>
<div>
<label class="label">{{ __('Address') }}</label>
<input type="text" name="address"
wire:model.debounce.500ms="project.address"
class="input input-bordered w-full" required>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="label">{{ __('Latitude') }}</label>
<input type="number" step="any" name="lat"
wire:model.debounce.500ms="project.lat"
class="input input-bordered w-full" required>
</div>
<div>
<label class="label">{{ __('Longitude') }}</label>
<input type="number" step="any" name="lng"
wire:model.debounce.500ms="project.lng"
class="input input-bordered w-full" required>
</div>
</div>
<div>
<label class="label">{{ __('Status') }}</label>
<select name="status" wire:model="project.status"
class="select select-bordered w-full">
<option value="planning">{{ __('Planning') }}</option>
<option value="in_progress">{{ __('In progress') }}</option>
<option value="paused">{{ __('Paused') }}</option>
<option value="completed">{{ __('Completed') }}</option>
</select>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="label">{{ __('Start date') }}</label>
<input type="date" name="start_date"
wire:model.debounce.500ms="project.start_date"
class="input input-bordered w-full" required>
</div>
<div>
<label class="label">{{ __('Estimated end date') }}</label>
<input type="date" name="end_date_estimated"
wire:model.debounce.500ms="project.end_date_estimated"
class="input input-bordered w-full">
</div>
</div>
<button type="submit" class="btn btn-primary w-full">
{{ __('Update') }}
</button>
</form>
</div>
<!-- Phases Tab -->
<div id="tab-phases-{{ $project->id }}"
class="tab-content-base p-4 {{ $activeTab === 'phases' ? '' : 'hidden' }}">
<h2 class="text-xl font-bold mb-2">{{ __('Phases') }}</h2>
<livewire:phase-list :project="$project" />
</div>
<!-- Users Tab -->
<div id="tab-users-{{ $project->id }}"
class="tab-content-base p-4 {{ $activeTab === 'users' ? '' : 'hidden' }}">
<h2 class="text-xl font-bold mb-2">{{ __('Users') }}</h2>
<livewire:project-users :project="$project" />
</div>
</div>
</div>
{{-- Alpine.js for tab switching --}}
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('projectTabs', () => ({
activeTab: '{{ $activeTab }}',
projectId: {{ $project->id }},
setTab(tab) {
this.activeTab = tab;
// Update the Livewire component
this.$dispatch('tabChanged', {
tab: tab,
projectId: this.projectId
});
}
}));
});
</script>
-37
View File
@@ -1,37 +0,0 @@
<x-app-layout>
<div class="max-w-2xl mx-auto p-4">
<h1 class="text-2xl font-bold mb-4">{{ __('Create Project') }}</h1>
<form action="{{ route('projects.store') }}" method="POST" class="space-y-4">
@csrf
<div>
<label class="label">{{ __('Project name') }}</label>
<input type="text" name="name" class="input input-bordered w-full" required>
</div>
<div>
<label class="label">{{ __('Address') }}</label>
<input type="text" name="address" class="input input-bordered w-full" required>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="label">{{ __('Latitude') }}</label>
<input type="number" step="any" name="lat" class="input input-bordered w-full" required>
</div>
<div>
<label class="label">{{ __('Longitude') }}</label>
<input type="number" step="any" name="lng" class="input input-bordered w-full" required>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="label">{{ __('Start date') }}</label>
<input type="date" name="start_date" class="input input-bordered w-full" required>
</div>
<div>
<label class="label">{{ __('Estimated end date') }}</label>
<input type="date" name="end_date_estimated" class="input input-bordered w-full">
</div>
</div>
<button type="submit" class="btn btn-primary w-full">{{ __('Create') }} {{ __('Project') }}</button>
</form>
</div>
</x-app-layout>
-157
View File
@@ -1,157 +0,0 @@
<x-app-layout>
<div class="card bg-base-100 shadow-sm">
<div class="card-body">
<div x-data="{ tabActivo: 1 }">
<div role="tablist" class="tabs tabs-border">
<a role="tab" class="tab" :class="{ 'tab-active': tabActivo === 1 }" @click.prevent="tabActivo = 1">{{ __("Project Data") }}</a>
<a role="tab" class="tab" :class="{ 'tab-active': tabActivo === 2 }" @click.prevent="tabActivo = 2">{{ __("Phases") }}</a>
<a role="tab" class="tab" :class="{ 'tab-active': tabActivo === 3 }" @click.prevent="tabActivo = 3">{{ __("Users") }}</a>
<a role="tab" class="tab" :class="{ 'tab-active': tabActivo === 4 }" @click.prevent="tabActivo = 4">{{ __("Companies") }}</a>
</div>
<!-- Los contenedores del contenido -->
<div class="py-4" x-show="tabActivo === 1">
<h1 class="text-2xl font-bold mb-4">{{ __('Edit Project') }}: {{ $project->name }}</h1>
<form action="{{ route('projects.update', $project) }}" method="POST" class="space-y-4">
@csrf
@method('PUT')
<table class="w-full mb-8">
<tbody>
{{-- Nombre --}}
<tr>
<td class="w-1/4 py-3 pr-4 align-bootom font-bold">
{{ __('Reference') }}
</td>
<td class="py-3">
<input type="text"
name="reference"
value="{{ old('reference', $project->reference) }}"
class="input w-64"
required
autofocus>
</td>
</tr>
{{-- Nombre --}}
<tr>
<td class="w-1/4 py-3 pr-4 align-bootom font-bold">
{{ __('Name') }}
</td>
<td class="py-3">
<input type="text"
name="name"
value="{{ old('name', $project->name) }}"
class="input w-64"
required
>
</td>
</tr>
{{-- Dirección --}}
<tr>
<td class="w-1/4 py-3 pr-4 align-bottom font-bold">
{{ __('Address') }}
</td>
<td class="py-3">
<input type="text"
name="address"
value="{{ old('address', $project->address) }}"
class="input w-1/2"
required>
</td>
</tr>
{{-- Coordenadas --}}
<tr>
<td class="w-1/4 py-3 pr-4 align-bottom font-bold">
{{ __('Coordinates') }}
</td>
<td class="py-3">
<div class="grid grid-cols-2 gap-4">
<div>
<label class="label">{{ __('Latitude') }}</label>
<input type="number"
step="any"
name="lat"
value="{{ old('lat', $project->lat) }}"
class="input w-64"
required>
</div>
<div>
<label class="label">{{ __('Longitude') }}</label>
<input type="number"
step="any"
name="lng"
value="{{ old('lng', $project->lng) }}"
class="input w-64"
required>
</div>
</div>
</td>
</tr>
{{-- Estatus --}}
<tr>
<td class="w-1/4 py-3 pr-4 align-bottom ">
{{ __('Status') }}
</td>
<td class="py-3">
<select name="status" class="select select-bordered w-full">
<option value="planning" @selected($project->status == 'planning')>{{ __('Planning') }}</option>
<option value="in_progress" @selected($project->status == 'in_progress')>{{ __('In progress') }}</option>
<option value="paused" @selected($project->status == 'paused')>{{ __('Paused') }}</option>
<option value="completed" @selected($project->status == 'completed')>{{ __('Completed') }}</option>
</select>
</td>
</tr>
{{-- Fecha de Inicio --}}
<tr>
<td class="w-1/4 py-3 pr-4 align-bottom font-bold">
{{ __('Start date') }}
</td>
<td class="py-3">
<input type="date"
name="start_date"
value="{{ old('start_date', $project->start_date->format('Y-m-d')) }}"
class="input w-64"
required>
</td>
</tr>
{{-- Fechas de finalización --}}
<tr>
<td class="w-1/4 py-3 pr-4 align-bottom">
{{ __('Estimated end date') }}
</td>
<td class="py-3">
<input type="date"
name="end_date_estimated"
value="{{ old('end_date_estimated', $project->end_date_estimated?->format('Y-m-d')) }}"
class="input w-64">
</td>
</tr>
</tbody>
</table>
<button type="submit" class="btn btn-primary">{{ __('Update') }}</button>
</form>
</div>
<div class="py-4" x-show="tabActivo === 2">
<h2 class="text-xl font-bold mb-2">{{ __('Phases') }}</h2>
<livewire:phase-list :project="$project" />
</div>
<div class="py-4" x-show="tabActivo === 3">
<h2 class="text-xl font-bold mb-2">{{ __('Users') }}</h2>
<livewire:project-users :project="$project" />
</div>
<div class="py-4" x-show="tabActivo === 4">
<h2 class="text-xl font-bold mb-2">{{ __('Companies') }}</h2>
<livewire:project-companies :project="$project" />
</div>
</div>
</div>
</div>
</x-app-layout>