From cf3d32a6fa9d3acb468bb77cb3656cd862769142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Bra=C3=B1a?= Date: Wed, 27 May 2026 20:28:44 +0200 Subject: [PATCH] Add interactive map to project form for setting coordinates and updating address/country --- app/Livewire/ProjectForm.php | 72 ++++++++ .../livewire/projects/project-form.blade.php | 172 +++++++++++++++++- 2 files changed, 243 insertions(+), 1 deletion(-) diff --git a/app/Livewire/ProjectForm.php b/app/Livewire/ProjectForm.php index 1e85751..3c12e66 100644 --- a/app/Livewire/ProjectForm.php +++ b/app/Livewire/ProjectForm.php @@ -3,9 +3,81 @@ namespace App\Livewire; use Livewire\Component; +use App\Models\Project; class ProjectForm extends Component { + public $projectId = null; + public $name = ''; + public $address = ''; + public $lat = null; + public $lng = null; + public $country = ''; + public $start_date = ''; + public $end_date_estimated = ''; + public $status = 'planning'; + + protected $rules = [ + 'name' => 'required|string|max:255', + 'address' => 'required|string', + 'lat' => 'nullable|numeric', + 'lng' => 'nullable|numeric', + 'start_date' => 'required|date', + 'end_date_estimated' => 'nullable|date', + 'status' => 'required|in:planning,in_progress,paused,completed', + ]; + + public function mount($projectId = null) + { + if ($projectId) { + $this->projectId = $projectId; + $project = Project::findOrFail($projectId); + $this->name = $project->name; + $this->address = $project->address; + $this->lat = $project->lat; + $this->lng = $project->lng; + $this->start_date = $project->start_date->format('Y-m-d'); + $this->end_date_estimated = $project->end_date_estimated?->format('Y-m-d'); + $this->status = $project->status; + // country? we don't have stored, maybe we can leave blank or compute from lat/lng? We'll leave blank for now. + } + } + + public function setCoordinates($lat, $lng) + { + $this->lat = $lat; + $this->lng = $lng; + // Optionally, we could trigger reverse geocoding here via JS and update address and country. + // But we'll do that entirely in JavaScript for better UX. + // We'll emit an event to JS to fetch address. + $this->dispatch('coordinatesUpdated', lat: $lat, lng: $lng); + } + + public function save() + { + $this->validate(); + + if ($this->projectId) { + $project = Project::findOrFail($this->projectId); + } else { + $project = new Project(); + $project->created_by = auth()->id(); + } + + $project->name = $this->name; + $project->address = $this->address; + $project->lat = $this->lat; + $project->lng = $this->lng; + $project->start_date = $this->start_date; + $project->end_date_estimated = $this->end_date_estimated; + $project->status = $this->status; + $project->save(); + + session()->flash('message', 'Project saved successfully.'); + + return redirect()->route('projects.index'); + } + public function render() { return view('livewire.projects.project-form'); diff --git a/resources/views/livewire/projects/project-form.blade.php b/resources/views/livewire/projects/project-form.blade.php index cdda2ce..abdcd5b 100644 --- a/resources/views/livewire/projects/project-form.blade.php +++ b/resources/views/livewire/projects/project-form.blade.php @@ -1,3 +1,173 @@
- {{-- In work, do what you enjoy. --}} +
+

{{ $projectId ? __('Edit Project') : __('New Project') }}

+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+

{{ __('Project Location') }}

+

+ {{ __('Click on the map to set the project location. The address and country will be filled automatically.') }} +

+
+ + +
+ +
+ + +
+
+ + @if(session()->has('message')) +
+ {{ session('message') }} +
+ @endif +
+ +@push('scripts') + +@endpush