diff --git a/src/PostIt/Directory.Packages.props b/src/PostIt/Directory.Packages.props
index 4dd4b2889..2f27340e9 100644
--- a/src/PostIt/Directory.Packages.props
+++ b/src/PostIt/Directory.Packages.props
@@ -16,6 +16,8 @@
+
+
diff --git a/src/PostIt/PostIt.Tests/BillingCommandPageViewModelTests.cs b/src/PostIt/PostIt.Tests/BillingCommandPageViewModelTests.cs
index c7b5b926b..da366d284 100644
--- a/src/PostIt/PostIt.Tests/BillingCommandPageViewModelTests.cs
+++ b/src/PostIt/PostIt.Tests/BillingCommandPageViewModelTests.cs
@@ -115,6 +115,26 @@ public class BillingCommandPageViewModelTests
}
}
+ [Fact]
+ public void ApplyLocationFromMap_sets_coordinates_and_updates_status()
+ {
+ var api = new RecordingApi();
+ var client = new BillingApiClient(api, "https://business.example/api/v1/");
+ var vm =
+ new CommandFormSummary { Id = 12, ActionName = "Rdv", Title = "Rendez-vous" }
+ .CreateCommandPageViewModel(
+ new ActivityInfo { Code = "dev", Name = "Développement" },
+ new ActivityUserDisplayItem { PerformerId = "perf-1", UserName = "Alice" },
+ client) as RdvViewModel;
+
+ vm!.Address = string.Empty;
+ vm.ApplyLocationFromMap(48.85661234, 2.35224567);
+
+ Assert.Equal(48.856612, vm.Latitude);
+ Assert.Equal(2.352246, vm.Longitude);
+ Assert.Contains("Position sélectionnée", vm.StatusMessage, StringComparison.OrdinalIgnoreCase);
+ }
+
[Fact]
public async Task InitializeAsync_loads_prestations_for_brush_and_submit_posts_selected_prestation()
{
diff --git a/src/PostIt/PostIt/PostIt.csproj b/src/PostIt/PostIt/PostIt.csproj
index 177e346d3..09632bdf8 100644
--- a/src/PostIt/PostIt/PostIt.csproj
+++ b/src/PostIt/PostIt/PostIt.csproj
@@ -29,6 +29,8 @@
None
All
+
+
diff --git a/src/PostIt/PostIt/ViewModels/Commands/RdvViewModel.cs b/src/PostIt/PostIt/ViewModels/Commands/RdvViewModel.cs
index afd0c54bd..44293f03e 100644
--- a/src/PostIt/PostIt/ViewModels/Commands/RdvViewModel.cs
+++ b/src/PostIt/PostIt/ViewModels/Commands/RdvViewModel.cs
@@ -113,6 +113,20 @@ public partial class RdvViewModel : BillingCommandPageViewModel
};
}
+ public void ApplyLocationFromMap(double latitude, double longitude)
+ {
+ Latitude = Math.Round(latitude, 6);
+ Longitude = Math.Round(longitude, 6);
+
+ if (string.IsNullOrWhiteSpace(Address))
+ {
+ this.SetInfoStatus("Position sélectionnée sur la carte. Complétez l'adresse puis envoyez la commande.");
+ return;
+ }
+
+ this.SetInfoStatus("Position sélectionnée sur la carte.");
+ }
+
protected override async Task SubmitAsync()
{
diff --git a/src/PostIt/PostIt/Views/Commands/RdvPage.axaml b/src/PostIt/PostIt/Views/Commands/RdvPage.axaml
index 4c88b0108..cee3c5c79 100644
--- a/src/PostIt/PostIt/Views/Commands/RdvPage.axaml
+++ b/src/PostIt/PostIt/Views/Commands/RdvPage.axaml
@@ -1,12 +1,13 @@
-
+
+
+
("LocationMap");
+ if (_locationMap is null)
+ return;
+
+ var map = new Map();
+ map.Layers.Add(OpenStreetMap.CreateTileLayer());
+ _locationMap.Map = map;
+ _locationMap.MapTapped += OnMapTapped;
+
+ DataContextChanged += OnDataContextChanged;
+ CenterFromViewModel();
+ }
+
+ private void OnDataContextChanged(object? sender, System.EventArgs e)
+ {
+ CenterFromViewModel();
+ }
+
+ private void OnMapTapped(object? sender, MapEventArgs e)
+ {
+ if (DataContext is not RdvViewModel vm)
+ return;
+
+ var (longitude, latitude) = SphericalMercator.ToLonLat(e.WorldPosition.X, e.WorldPosition.Y);
+ vm.ApplyLocationFromMap(latitude, longitude);
+ CenterMap(latitude, longitude, zoomLevel: 13);
+ }
+
+ private void CenterFromViewModel()
+ {
+ if (DataContext is not RdvViewModel vm)
+ {
+ CenterMap(48.8566, 2.3522, zoomLevel: 4);
+ return;
+ }
+
+ if (vm.Latitude.HasValue && vm.Longitude.HasValue)
+ {
+ CenterMap(vm.Latitude.Value, vm.Longitude.Value, zoomLevel: 13);
+ return;
+ }
+
+ CenterMap(48.8566, 2.3522, zoomLevel: 4);
+ }
+
+ private void CenterMap(double latitude, double longitude, int zoomLevel)
+ {
+ if (_locationMap?.Map is null)
+ return;
+
+ var (x, y) = SphericalMercator.FromLonLat(longitude, latitude);
+ _locationMap.Map.Navigator.CenterOn(x, y);
+ _locationMap.Map.Navigator.ZoomToLevel(zoomLevel);
+ }
}