From 420a86b92fb82a9bc67aa89ff4a9ba2ab67684e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A5=D0=B0=D0=BB=D0=B8=D0=BC=D0=BE=D0=B2=20=D0=A0=D1=83?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D0=BC?= Date: Fri, 6 Mar 2026 21:43:37 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B0=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B8=D1=81=D0=BA=D0=B0,=20=D1=81=D0=BE=D1=80=D1=82?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Host/Endpoints/SearchEndpoints.cs | 42 +++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/Host/Endpoints/SearchEndpoints.cs b/src/Host/Endpoints/SearchEndpoints.cs index 4978a2d..1972457 100644 --- a/src/Host/Endpoints/SearchEndpoints.cs +++ b/src/Host/Endpoints/SearchEndpoints.cs @@ -42,10 +42,19 @@ public static class SearchEndpoints nearbyGeoQuery = nearbyGeoQuery.Where(x => x.Id != currentUserId.Value); } - var nearbyGeo = await nearbyGeoQuery + var nearbyGeoRaw = await nearbyGeoQuery .Select(x => new { x.Id, x.State, Latitude = x.Location.Coordinate.Y, Longitude = x.Location.Coordinate.X }) .ToListAsync(ct); + var nearbyGeo = nearbyGeoRaw.Select(x => new + { + x.Id, + x.State, + x.Latitude, + x.Longitude, + DistanceMeters = CalculateDistanceInMeters(lat, lon, x.Latitude, x.Longitude) + }).ToList(); + var nearbyIds = nearbyGeo.Select(x => x.Id).ToList(); if (!nearbyIds.Any()) return Results.Ok(new List()); @@ -62,10 +71,12 @@ public static class SearchEndpoints (inDesc && o.Description != null && o.Description.ToLower().Contains(qLower))); } - var matchedOffers = await offersQuery + var matchedOffersRaw = await offersQuery .Select(o => new { o.Id, o.PerformerId, o.Title, Description = o.Description ?? "", o.Price.Amount, o.Price.Currency }) .ToListAsync(ct); + var matchedOffers = matchedOffersRaw.Select(o => new { o.Id, o.PerformerId, o.Title, o.Description, PriceAmount = o.Amount, PriceCurrency = "₽" }).ToList(); + var performersWithOffers = matchedOffers.Select(o => o.PerformerId).Distinct().ToList(); // 3. Ищем пользователей, их расписание и компетенции (IdentityDbContext) @@ -88,6 +99,14 @@ public static class SearchEndpoints } var profiles = await profilesQuery.ToListAsync(ct); + var profileIds = profiles.Select(p => p.Id).ToList(); + + var accountsRaw = await identityDb.Accounts + .Where(a => profileIds.Contains(a.Id)) + .Select(a => new { a.Id, a.Roles }) + .ToListAsync(ct); + + var accountsDict = accountsRaw.ToDictionary(a => a.Id, a => a.Roles.Select(r => r.ToString()).ToList()); // 4. Сборка результата и логика "Умного статуса" var currentDay = GetRussianDayOfWeek(DateTime.UtcNow.DayOfWeek); @@ -110,6 +129,13 @@ public static class SearchEndpoints ? o.Select(x => (object)x).ToList() : new List(); + var roles = accountsDict.TryGetValue(p.Id, out var r) ? r : new List(); + string roleName = ""; + if (roles.Contains("Company")) roleName = "Компания"; + else if (roles.Contains("Master")) roleName = "Мастер"; + else if (roles.Contains("Candidate")) roleName = "Кандидат в мастера"; + else roleName = "Пользователь"; + return new { PerformerId = p.Id, @@ -118,6 +144,8 @@ public static class SearchEndpoints Latitude = g.Latitude, Longitude = g.Longitude, Status = finalStatus, // "Готов к заказу" или "Офлайн" + Distance = Math.Round(g.DistanceMeters), + Role = roleName, MatchedCompetencies = p.Competencies .Where(c => string.IsNullOrWhiteSpace(qLower) || !inComp || c.Name.ToLower().Contains(qLower)) .Select(c => c.Name).ToList(), @@ -125,7 +153,7 @@ public static class SearchEndpoints }; }); - return Results.Ok(result.OrderByDescending(x => x.Status == "Готов к заказу").ThenBy(x => x.Name)); + return Results.Ok(result.OrderByDescending(x => x.Status == "Готов к заказу").ThenBy(x => x.Distance)); }) .WithName("GlobalSearch") .WithOpenApi(operation => new(operation) @@ -175,4 +203,12 @@ public static class SearchEndpoints DayOfWeek.Sunday => "Воскресенье", _ => "Понедельник" }; + + private static double CalculateDistanceInMeters(double lat1, double lon1, double lat2, double lon2) + { + var dLat = (lat2 - lat1) * Math.PI / 180.0; + var dLon = (lon2 - lon1) * Math.PI / 180.0; + var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(lat1 * Math.PI / 180.0) * Math.Cos(lat2 * Math.PI / 180.0) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2); + return 6371000.0 * 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); + } }