fe57388f05
The edit/create project page used a stripped-down inline form. Rewired it to the existing-but-orphaned pieces: - Project Data uses the rich partial project-data-form (labels-left/field-right layout, sections Identification/Location/Planning, address search + Leaflet map with draggable marker + reverse/forward geocoding, country dropdown) - When editing, tabs added for Phases / Users / Companies (nested Livewire components phase-list / project-users / project-companies) - ProjectForm now provides $countryList (the partial's country dropdown needs it) - Added the map JS the partial was missing: inits #project-location-map, search box, and calls $this->setLocation(lat,lng,address,country) so the wire:model fields update Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
142 lines
5.5 KiB
PHP
142 lines
5.5 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire;
|
|
|
|
use Livewire\Component;
|
|
use Livewire\Attributes\Layout;
|
|
use App\Models\Project;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Gate;
|
|
|
|
#[Layout('layouts.app')]
|
|
class ProjectForm extends Component
|
|
{
|
|
public ?Project $project = null;
|
|
|
|
// Identification
|
|
public string $name = '';
|
|
public string $reference = '';
|
|
public string $status = 'planning';
|
|
|
|
// Location
|
|
public string $address = '';
|
|
public string $country = '';
|
|
public string $lat = '';
|
|
public string $lng = '';
|
|
|
|
// Planning
|
|
public string $startDate = '';
|
|
public string $endDateEstimated = '';
|
|
|
|
public function mount(?Project $project = null): void
|
|
{
|
|
if ($project && $project->exists) {
|
|
Gate::authorize('edit projects', $project);
|
|
$this->project = $project;
|
|
$this->name = $project->name;
|
|
$this->reference = $project->reference ?? '';
|
|
$this->status = $project->status;
|
|
$this->address = $project->address;
|
|
$this->country = $project->country ?? '';
|
|
$this->lat = (string) ($project->lat ?? '');
|
|
$this->lng = (string) ($project->lng ?? '');
|
|
$this->startDate = $project->start_date->format('Y-m-d');
|
|
$this->endDateEstimated = $project->end_date_estimated?->format('Y-m-d') ?? '';
|
|
} else {
|
|
Gate::authorize('create projects');
|
|
$this->startDate = today()->format('Y-m-d');
|
|
}
|
|
}
|
|
|
|
// Called from JS after map click / marker drag + reverse geocode
|
|
public function setLocation(string $lat, string $lng, string $address = '', string $country = ''): void
|
|
{
|
|
$this->lat = $lat;
|
|
$this->lng = $lng;
|
|
if ($address) $this->address = $address;
|
|
if ($country) $this->country = strtolower($country);
|
|
}
|
|
|
|
protected function rules(): array
|
|
{
|
|
return [
|
|
'name' => 'required|string|max:255',
|
|
'reference' => 'nullable|string|max:100',
|
|
'status' => 'required|in:planning,in_progress,paused,completed',
|
|
'address' => 'required|string',
|
|
'country' => 'nullable|string|size:2',
|
|
'lat' => 'nullable|numeric|between:-90,90',
|
|
'lng' => 'nullable|numeric|between:-180,180',
|
|
'startDate' => 'required|date',
|
|
'endDateEstimated' => 'nullable|date|after_or_equal:startDate',
|
|
];
|
|
}
|
|
|
|
protected $validationAttributes = [
|
|
'name' => 'nombre',
|
|
'reference' => 'referencia',
|
|
'status' => 'estado',
|
|
'address' => 'dirección',
|
|
'country' => 'país',
|
|
'lat' => 'latitud',
|
|
'lng' => 'longitud',
|
|
'startDate' => 'fecha de inicio',
|
|
'endDateEstimated' => 'fecha de fin estimada',
|
|
];
|
|
|
|
public function save(): void
|
|
{
|
|
$this->validate();
|
|
|
|
$data = [
|
|
'name' => $this->name,
|
|
'reference' => $this->reference ?: null,
|
|
'status' => $this->status,
|
|
'address' => $this->address,
|
|
'country' => $this->country ?: null,
|
|
'lat' => $this->lat ?: null,
|
|
'lng' => $this->lng ?: null,
|
|
'start_date' => $this->startDate,
|
|
'end_date_estimated' => $this->endDateEstimated ?: null,
|
|
];
|
|
|
|
if ($this->project && $this->project->exists) {
|
|
$this->project->update($data);
|
|
session()->flash('notify', 'Proyecto actualizado correctamente.');
|
|
} else {
|
|
$project = Project::create(array_merge($data, ['created_by' => Auth::id()]));
|
|
$project->users()->attach(Auth::id(), ['role_in_project' => 'supervisor']);
|
|
session()->flash('notify', 'Proyecto creado correctamente.');
|
|
}
|
|
|
|
$this->redirect(route('projects.index'), navigate: true);
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.projects.project-form', [
|
|
'countryList' => $this->countryList(),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* ISO alpha-2 (lowercase, matches flagcdn) => display name.
|
|
*/
|
|
private function countryList(): array
|
|
{
|
|
return [
|
|
'es' => 'España', 'pt' => 'Portugal', 'fr' => 'Francia', 'it' => 'Italia',
|
|
'de' => 'Alemania', 'gb' => 'Reino Unido', 'ie' => 'Irlanda', 'nl' => 'Países Bajos',
|
|
'be' => 'Bélgica', 'ch' => 'Suiza', 'at' => 'Austria', 'lu' => 'Luxemburgo',
|
|
'se' => 'Suecia', 'no' => 'Noruega', 'dk' => 'Dinamarca', 'fi' => 'Finlandia',
|
|
'pl' => 'Polonia', 'cz' => 'Chequia', 'gr' => 'Grecia', 'ro' => 'Rumanía',
|
|
'us' => 'Estados Unidos', 'ca' => 'Canadá', 'mx' => 'México', 'gt' => 'Guatemala',
|
|
'cr' => 'Costa Rica', 'pa' => 'Panamá', 'co' => 'Colombia', 've' => 'Venezuela',
|
|
'ec' => 'Ecuador', 'pe' => 'Perú', 'bo' => 'Bolivia', 'cl' => 'Chile',
|
|
'ar' => 'Argentina', 'uy' => 'Uruguay', 'py' => 'Paraguay', 'br' => 'Brasil',
|
|
'do' => 'República Dominicana', 'ma' => 'Marruecos', 'gq' => 'Guinea Ecuatorial',
|
|
'ao' => 'Angola', 'cv' => 'Cabo Verde', 'us' => 'Estados Unidos',
|
|
];
|
|
}
|
|
}
|