using System.Text.Json; using System.Text.Json.Serialization; using System.Diagnostics; using Microsoft.Maui.Controls; namespace CORP_MAUI.Models; public class User { public int Id { get; set; } public string Username { get; set; } = string.Empty; public string Email { get; set; } = string.Empty; [JsonPropertyName("phone_number")] public string? PhoneNumber { get; set; } [JsonPropertyName("first_name")] public string FirstName { get; set; } = string.Empty; [JsonPropertyName("last_name")] public string LastName { get; set; } = string.Empty; [JsonPropertyName("departments")] public List? Departments { get; set; } // Может быть либо объектом Department, либо строкой (для обратной совместимости) public object? Department { get; set; } // Может быть либо объектом Position, либо строкой (для обратной совместимости) public object? Position { get; set; } public List? Skills { get; set; } [JsonPropertyName("is_online")] public bool IsOnline { get; set; } [JsonPropertyName("avatar_url")] public string? AvatarUrl { get; set; } [JsonPropertyName("avatar")] public string? Avatar { get; set; } // Вспомогательные свойства для удобства [JsonIgnore] public string FullName => $"{FirstName} {LastName}".Trim(); [JsonIgnore] public string? DisplayAvatarUrl { get { if (!string.IsNullOrEmpty(Avatar)) return Avatar; if (string.IsNullOrEmpty(AvatarUrl)) return null; // Handle protocol-relative URLs if (AvatarUrl.StartsWith("//")) return $"https:{AvatarUrl}"; if (AvatarUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase)) return AvatarUrl; string cleanUrl = AvatarUrl.TrimStart('/'); return $"https://corp.robotail.pro/{cleanUrl}"; } } /// /// Универсальное свойство для отображения аватара (поддерживает Base64 и URL) /// [JsonIgnore] public ImageSource? DisplayAvatarSource { get { try { // 1. Проверяем, есть ли Base64 изображение в Avatar if (!string.IsNullOrEmpty(Avatar) && Avatar.StartsWith("data:image")) { // Извлекаем Base64 данные из строки "data:image/jpeg;base64,..." string base64Data = Avatar; int commaIndex = base64Data.IndexOf(','); if (commaIndex > 0) { base64Data = base64Data.Substring(commaIndex + 1); byte[] imageBytes = Convert.FromBase64String(base64Data); return ImageSource.FromStream(() => new MemoryStream(imageBytes)); } } // 2. Если есть URL аватара string? url = DisplayAvatarUrl; if (!string.IsNullOrEmpty(url)) { return ImageSource.FromUri(new Uri(url)); } } catch (Exception ex) { Trace.WriteLine($"[User] ⚠️ Ошибка загрузки аватара для {FullName}: {ex.Message}"); } // 3. Возвращаем placeholder return ImageSource.FromFile("dotnet_bot.png"); } } [JsonIgnore] public string DepartmentName { get { if (Departments != null && Departments.Count > 0) return Departments[0].Name; if (Department is Department dept) return dept.Name; if (Department is string str) return str; if (Department is JsonElement element) { if (element.ValueKind == JsonValueKind.String) return element.GetString() ?? string.Empty; if (element.ValueKind == JsonValueKind.Object && element.TryGetProperty("name", out JsonElement nameProp)) return nameProp.GetString() ?? string.Empty; } return string.Empty; } } [JsonIgnore] public string PositionName { get { if (Position is Position pos) return pos.Name; if (Position is string str) return str; if (Position is JsonElement element) { if (element.ValueKind == JsonValueKind.String) return element.GetString() ?? string.Empty; if (element.ValueKind == JsonValueKind.Object && element.TryGetProperty("name", out JsonElement nameProp)) return nameProp.GetString() ?? string.Empty; } return string.Empty; } } }