import Foundation struct SearchDataPayload: Decodable { let users: [UserSearchResult] } struct UserSearchResult: Decodable, Identifiable { let userId: UUID let login: String let fullName: String? let customName: String? let createdAt: Date? let profile: SearchProfile? var id: UUID { userId } } struct SearchProfile: Decodable { let userId: UUID let login: String? let fullName: String? let customName: String? let bio: String? let lastSeen: Int? let createdAt: Date? } extension UserSearchResult { var officialFullName: String? { trimmed(fullName) ?? trimmed(profile?.fullName) } var preferredCustomName: String? { trimmed(customName) ?? trimmed(profile?.customName) } var loginHandle: String { "@\(login)" } var displayName: String { if let official = officialFullName { return official } if let custom = preferredCustomName { return custom } if let profileFull = trimmed(profile?.fullName) { return profileFull } if let profileCustom = trimmed(profile?.customName) { return profileCustom } return loginHandle } var avatarInitial: String { let source = officialFullName ?? preferredCustomName ?? trimmed(profile?.login) ?? login if let character = source.first(where: { !$0.isWhitespace && $0 != "@" }) { return String(character).uppercased() } return "?" } var isOfficial: Bool { officialFullName != nil } private func trimmed(_ value: String?) -> String? { guard let value = value?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { return nil } return value } }