You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
PadelClubData/PadelClubData/Data/Event.swift

226 lines
8.1 KiB

//
// Event_v2.swift
// Padel Tournament
//
// Created by razmig on 10/03/2024.
//
import Foundation
import LeStorage
import SwiftUI
@Observable
final public class Event: BaseEvent {
public init(creator: String? = nil, club: String? = nil, name: String? = nil, tenupId: String? = nil) {
super.init(creator: creator, club: club, name: name, tenupId: tenupId)
self.relatedUser = creator
}
required init(from decoder: Decoder) throws {
try super.init(from: decoder)
}
required public init() {
super.init()
}
public override func deleteUnusedSharedDependencies(store: Store) {
store.deleteUnusedSharedDependencies(type: Tournament.self) { $0.event == self.id && $0.isDeleted == false }
store.deleteUnusedSharedDependencies(type: DateInterval.self) { $0.event == self.id }
}
public override func deleteDependencies(store: Store, actionOption: ActionOption) {
store.deleteDependencies(type: Tournament.self, actionOption: actionOption) { $0.event == self.id && $0.isDeleted == false }
store.deleteDependencies(type: DateInterval.self, actionOption: actionOption) { $0.event == self.id }
}
// MARK: - Computed dependencies
public var tournaments: [Tournament] {
DataStore.shared.tournaments.filter { $0.event == self.id && $0.isDeleted == false }.sorted(by: \.startDate)
}
public func clubObject() -> Club? {
guard let club else { return nil }
return Store.main.findById(club)
}
public var courtsUnavailability: [DateInterval] {
DataStore.shared.dateIntervals.filter({ $0.event == id })
}
// MARK: -
public func eventCourtCount() -> Int {
tournaments.map { $0.courtCount }.max() ?? 2
}
public func eventStartDate() -> Date {
tournaments.map { $0.startDate }.min() ?? Date()
}
public func eventDayDuration() -> Int {
tournaments.map { $0.dayDuration }.max() ?? 1
}
public func eventTitle() -> String {
if let name, name.isEmpty == false {
return name
} else {
return "Événement"
}
}
public func existingBuild(_ build: any TournamentBuildHolder) -> Tournament? {
tournaments.first(where: { $0.isSameBuild(build) })
}
public func tournamentsCourtsUsed(exluding tournamentId: String) -> [DateInterval] {
tournaments.filter { $0.id != tournamentId }.flatMap({ tournament in
tournament.getPlayedMatchDateIntervals(in: self)
})
}
public func federalTournaments() -> [Tournament] {
tournaments.filter({ $0.isAnimation() == false && $0.isCanceled == false && $0.isDeleted == false })
}
public func paidTournaments() -> [Tournament] {
tournaments.filter({ $0.isFree() == false && $0.isCanceled == false && $0.isDeleted == false })
}
public func confirmedTournaments() -> [Tournament] {
tournaments.filter({ $0.isCanceled == false && $0.isDeleted == false })
}
public func shareURL() -> URL? {
return URL(string: URLs.main.url.appending(path: "event/\(id)").absoluteString.removingPercentEncoding!)
}
public func formattedDateInterval() -> String {
let tournaments = self.tournaments
guard !tournaments.isEmpty else {
return "" // Handle empty tournament list
}
let firstTournament = tournaments.first!
let lastTournament = tournaments.last!
// Helper to check if two dates are on the same day
func isSameDay(date1: Date, date2: Date) -> Bool {
return Calendar.current.isDate(date1, inSameDayAs: date2)
}
// Scenario 1: Only one tournament
if tournaments.count == 1 {
return firstTournament.startDate.formattedAsDate()
}
// Scenario 2: Multiple tournaments, but all start and end on the same day (single-day event overall)
let overallEventIsSingleDay = isSameDay(date1: firstTournament.startDate, date2: lastTournament.startDate)
if overallEventIsSingleDay {
return firstTournament.startDate.formattedAsDate()
}
// Scenario 3: Multiple tournaments, spanning multiple days (requires "Du ... au ...")
let startDay = firstTournament.startDate.localizedDay()
let endDay = lastTournament.startDate.localizedDay()
let startMonthYear = firstTournament.startDate.monthYearFormatted
let endMonthYear = lastTournament.startDate.monthYearFormatted
let calendar = Calendar.current
let firstStartComponents = calendar.dateComponents([.year, .month], from: firstTournament.startDate)
let lastEndComponents = calendar.dateComponents([.year, .month], from: lastTournament.startDate)
if firstStartComponents.year == lastEndComponents.year && firstStartComponents.month == lastEndComponents.month {
// Same month and year: "Du 13 au 15 Juin 2025"
return "Du \(startDay) au \(endDay) \(startMonthYear)"
} else if firstStartComponents.year == lastEndComponents.year {
// Different months, same year: "Du 13 Juin au 15 Juillet 2025"
return "Du \(startDay) \(startMonthYear) au \(endDay) \(endMonthYear)"
} else {
// Different years: "Du 13 Juin 2025 au 15 Juin 2026"
return "Du \(startDay) \(startMonthYear) au \(endDay) \(endMonthYear)"
}
}
public func tournamentInformation() -> String? {
confirmedTournaments().first?.information
}
public func eventLinksPasteData() -> String {
let tournaments = self.confirmedTournaments()
var link = [String?]()
link.append(eventTitle())
link.append(tournamentInformation())
if let url = shareURL() {
var tournamentLink = [String]()
tournamentLink.append("Lien de l'événement")
tournamentLink.append(url.absoluteString)
let eventLink = tournamentLink.joined(separator: "\n")
link.append(eventLink)
}
link.append("Retrouvez toutes les infos en suivant le\(tournaments.count.pluralSuffix) lien\(tournaments.count.pluralSuffix) ci-dessous :")
link.append(tournaments.compactMap({ tournament in
if let url = tournament.shareURL(.info) {
var tournamentLink = [String]()
tournamentLink.append(tournament.tournamentTitle(.title))
tournamentLink.append(url.absoluteString)
return tournamentLink.joined(separator: "\n")
} else {
return nil
}
}).joined(separator: "\n\n"))
return link.compactMap({ $0 }).joined(separator: "\n\n")
}
public func selectedTeams() -> [TeamRegistration] {
confirmedTournaments().flatMap({ $0.selectedSortedTeams() })
}
public func umpireMail() -> [String]? {
confirmedTournaments().first?.umpireMail()
}
public func mailSubject() -> String {
let tournaments = confirmedTournaments()
guard !tournaments.isEmpty else {
return eventTitle()
}
// Get the date range from all confirmed tournaments
let dates = tournaments.compactMap { $0.startDate }
guard let firstDate = dates.min(), let lastDate = dates.max() else {
return eventTitle()
}
let dateRange = firstDate == lastDate
? firstDate.formattedDate(.short)
: "\(firstDate.formattedDate(.short)) - \(lastDate.formattedDate(.short))"
let subject = [eventTitle(), dateRange, clubObject()?.name].compactMap({ $0 }).joined(separator: " | ")
return subject
}
func insertOnServer() throws {
DataStore.shared.events.writeChangeAndInsertOnServer(instance: self)
for tournament in self.tournaments {
try tournament.insertOnServer()
}
for dataInterval in self.courtsUnavailability {
try dataInterval.insertOnServer()
}
}
}