import Foundation import SwiftUI // MARK: - Club struct Club: Identifiable, Equatable, Codable { let id: String let name: String let description: String let clubType: ClubType let privacy: ClubPrivacy let location: String let latitude: Double? let longitude: Double? var memberCount: Int let maxMembers: Int? let imageUrl: String? let rules: String? let ownerId: String let ownerName: String var membershipStatus: MembershipStatus let createdAt: Date enum CodingKeys: String, CodingKey { case id, name, description, clubType, privacy, location, latitude, longitude, memberCount, maxMembers, imageUrl, rules, ownerId, ownerName, membershipStatus, createdAt } init( id: String, name: String, description: String, clubType: ClubType, privacy: ClubPrivacy, location: String, latitude: Double?, longitude: Double?, memberCount: Int, maxMembers: Int?, imageUrl: String?, rules: String?, ownerId: String, ownerName: String, membershipStatus: MembershipStatus, createdAt: Date ) { self.id = id self.name = name self.description = description self.clubType = clubType self.privacy = privacy self.location = location self.latitude = latitude self.longitude = longitude self.memberCount = memberCount self.maxMembers = maxMembers self.imageUrl = imageUrl self.rules = rules self.ownerId = ownerId self.ownerName = ownerName self.membershipStatus = membershipStatus self.createdAt = createdAt } static func == (lhs: Club, rhs: Club) -> Bool { lhs.id == rhs.id && lhs.membershipStatus == rhs.membershipStatus } var availableSpots: Int? { guard let max = maxMembers else { return nil } return max - memberCount } var isFull: Bool { guard let max = maxMembers else { return false } return memberCount >= max } } // MARK: - Club Type enum ClubType: String, CaseIterable, Codable { case running case walking case cycling case triathlon case crossfit case general var displayName: String { switch self { case .running: return "Running" case .walking: return "Walking" case .cycling: return "Cycling" case .triathlon: return "Triathlon" case .crossfit: return "CrossFit" case .general: return "General Fitness" } } var icon: String { switch self { case .running: return "figure.run" case .walking: return "figure.walk" case .cycling: return "bicycle" case .triathlon: return "triangle.fill" case .crossfit: return "dumbbell.fill" case .general: return "heart.fill" } } var color: Color { switch self { case .running: return .blue case .walking: return .green case .cycling: return .orange case .triathlon: return .purple case .crossfit: return .red case .general: return .indigo } } } // MARK: - Club Privacy enum ClubPrivacy: String, CaseIterable, Codable { case publicPrivacy case privateClub case invitationOnly var displayName: String { switch self { case .publicPrivacy: return "Public" case .privateClub: return "Private" case .invitationOnly: return "Invitation Only" } } var icon: String { switch self { case .publicPrivacy: return "globe" case .privateClub: return "lock.fill" case .invitationOnly: return "mail.fill" } } } // MARK: - Membership Status enum MembershipStatus: String, CaseIterable, Codable { case active case pending case invited case left } // MARK: - Club Member struct ClubMember: Identifiable, Codable { let id: String let name: String let avatarUrl: String? let role: MemberRole let joinedAt: Date let membershipStatus: MembershipStatus } enum MemberRole: String, CaseIterable, Codable { case owner case admin case member var displayName: String { switch self { case .owner: return "Owner" case .admin: return "Admin" case .member: return "Member" } } } // MARK: - Create Club Request struct CreateClubRequest: Encodable { let name: String let description: String let clubType: ClubType let privacy: ClubPrivacy let location: String let latitude: Double? let longitude: Double? let maxMembers: Int? let rules: String? } // MARK: - Update Club Request struct UpdateClubRequest: Encodable { var name: String? var description: String? var clubType: ClubType? var privacy: ClubPrivacy? var location: String? var latitude: Double? var longitude: Double? var maxMembers: Int? var rules: String? } // MARK: - Club Filter struct ClubFilter: Encodable { var clubType: ClubType? var privacy: ClubPrivacy? var membershipStatus: MembershipStatus? var location: String? var radiusKm: Double? var limit: Int var offset: Int init( clubType: ClubType? = nil, privacy: ClubPrivacy? = nil, membershipStatus: MembershipStatus? = nil, location: String? = nil, radiusKm: Double? = nil, limit: Int = 20, offset: Int = 0 ) { self.clubType = clubType self.privacy = privacy self.membershipStatus = membershipStatus self.location = location self.radiusKm = radiusKm self.limit = limit self.offset = offset } } // MARK: - API Response Types struct ClubListResponse: Decodable { let clubs: [Club] let hasMore: Bool } struct ClubDetailResponse: Decodable { let club: Club let members: [ClubMember] } struct CreateClubResponse: Decodable { let club: Club } struct UpdateClubResponse: Decodable { let club: Club } struct MembershipResponse: Decodable { let success: Bool let clubId: String let status: MembershipStatus } struct InviteMemberResponse: Decodable { let success: Bool let clubId: String let memberId: String } struct RemoveMemberResponse: Decodable { let success: Bool let clubId: String let memberId: String }