diff --git a/PadelClub/Data/Match.swift b/PadelClub/Data/Match.swift index 05e2ed6..cf19e34 100644 --- a/PadelClub/Data/Match.swift +++ b/PadelClub/Data/Match.swift @@ -55,6 +55,14 @@ class Match: ModelObject, Storable { return RoundRule.matchIndexWithinRound(fromMatchIndex: index) } + func matchWarningSubject() -> String { + [roundTitle(), matchTitle()].compacted().joined(separator: " ") + } + + func matchWarningMessage() -> String { + [roundTitle(), matchTitle(), startDate?.localizedDate(), courtName()].compacted().joined(separator: "\n") + } + func matchTitle(_ displayStyle: DisplayStyle = .wide) -> String { if let groupStageObject { return groupStageObject.localizedMatchUpLabel(for: index) diff --git a/PadelClub/Views/Calling/Components/MenuWarningView.swift b/PadelClub/Views/Calling/Components/MenuWarningView.swift index e8e5218..31c74ed 100644 --- a/PadelClub/Views/Calling/Components/MenuWarningView.swift +++ b/PadelClub/Views/Calling/Components/MenuWarningView.swift @@ -14,9 +14,9 @@ struct MenuWarningView: View { var umpireMail: String? var subject: String? - @State private var contactType: ContactType? - - func getUmpireMail() -> [String]? { + @Binding var contactType: ContactType? + + private func _getUmpireMail() -> [String]? { if let umpireMail { return [umpireMail] } @@ -29,7 +29,7 @@ struct MenuWarningView: View { contactType = .message(date: date, recipients: players.compactMap({ $0.phoneNumber }), body: message, tournamentBuild: nil) } Button("Mail") { - contactType = .mail(date: date, recipients: privateMode ? getUmpireMail() : players.compactMap({ $0.email }), bccRecipients: privateMode ? players.compactMap({ $0.email }) : nil, body: message, subject: subject, tournamentBuild: nil) + contactType = .mail(date: date, recipients: privateMode ? _getUmpireMail() : players.compactMap({ $0.email }), bccRecipients: privateMode ? players.compactMap({ $0.email }) : nil, body: message, subject: subject, tournamentBuild: nil) } } @@ -76,5 +76,5 @@ struct MenuWarningView: View { } #Preview { - MenuWarningView(teams: []) + MenuWarningView(teams: [], contactType: .constant(nil)) } diff --git a/PadelClub/Views/Calling/SendToAllView.swift b/PadelClub/Views/Calling/SendToAllView.swift index c577015..891cbf5 100644 --- a/PadelClub/Views/Calling/SendToAllView.swift +++ b/PadelClub/Views/Calling/SendToAllView.swift @@ -10,10 +10,23 @@ import LeStorage struct SendToAllView: View { @Environment(Tournament.self) var tournament: Tournament + @EnvironmentObject var networkMonitor: NetworkMonitor + + @State private var contactType: ContactType? = nil @State private var contactMethod: Int = 1 @State private var contactRecipients: Set = Set() + @State private var sentError: ContactManagerError? = nil + + var messageSentFailed: Binding { + Binding { + sentError != nil + } set: { newValue in + if newValue == false { + sentError = nil + } + } + } - var body: some View { NavigationStack { List(selection: $contactRecipients) { @@ -55,7 +68,11 @@ struct SendToAllView: View { Section { RowButtonView("Contacter \(_totalString())") { - + if contactMethod == 0 { + contactType = .message(date: nil, recipients: _teams().flatMap { $0.unsortedPlayers() }.compactMap { $0.phoneNumber }, body: tournament.tournamentTitle(), tournamentBuild: nil) + } else { + contactType = .mail(date: nil, recipients: nil, bccRecipients: _teams().flatMap { $0.unsortedPlayers() }.compactMap { $0.email }, body: nil, subject: tournament.tournamentTitle(), tournamentBuild: nil) + } } } } @@ -64,10 +81,68 @@ struct SendToAllView: View { .navigationTitle("Réglages") .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .navigationBar) + .alert("Un problème est survenu", isPresented: messageSentFailed) { + Button("OK") { + } + } message: { + let message = [networkMonitor.connected == false ? "L'appareil n'est pas connecté à internet." as String? : nil, sentError == .mailNotSent ? "Le mail est dans la boîte d'envoi de l'app Mail. Vérifiez son état dans l'app Mail avant d'essayer de le renvoyer." as String? : nil, (sentError == .messageFailed || sentError == .messageNotSent) ? "Le SMS n'a pas été envoyé" as String? : nil, sentError == .mailFailed ? "Le mail n'a pas été envoyé" as String? : nil].compacted().joined(separator: "\n") + Text(message) + } + .sheet(item: $contactType) { contactType in + Group { + switch contactType { + case .message(_, let recipients, let body, _): + if Guard.main.paymentForNewTournament() != nil { + MessageComposeView(recipients: recipients, body: body) { result in + switch result { + case .cancelled: + break + case .failed: + self.sentError = .messageFailed + case .sent: + if networkMonitor.connected == false { + self.sentError = .messageNotSent + } + @unknown default: + break + } + } + } else { + SubscriptionView(showLackOfPlanMessage: true) + } + case .mail(_, let recipients, let bccRecipients, let body, let subject, _): + if Guard.main.paymentForNewTournament() != nil { + MailComposeView(recipients: recipients, bccRecipients: bccRecipients, body: body, subject: subject) { result in + switch result { + case .cancelled, .saved: + self.contactType = nil + case .failed: + self.contactType = nil + self.sentError = .mailFailed + case .sent: + if networkMonitor.connected == false { + self.contactType = nil + self.sentError = .mailNotSent + } + @unknown default: + break + } + } + } else { + SubscriptionView(showLackOfPlanMessage: true) + } + } + } + .tint(.master) + } } } func _teams() -> [TeamRegistration] { + _roundTeams() + _groupStagesTeams() + } + + func _roundTeams() -> [TeamRegistration] { let rounds : [Round] = contactRecipients.compactMap { Store.main.findById($0) } return rounds.flatMap({ $0.teams() }) } @@ -81,7 +156,7 @@ struct SendToAllView: View { if contactRecipients.isEmpty { return "toutes les équipes" } else { - let teams = _teams() + _groupStagesTeams() + let teams = _teams() return teams.count.formatted() + " équipe" + teams.count.pluralSuffix } } diff --git a/PadelClub/Views/Match/MatchDetailView.swift b/PadelClub/Views/Match/MatchDetailView.swift index 0e59ae9..9815eb1 100644 --- a/PadelClub/Views/Match/MatchDetailView.swift +++ b/PadelClub/Views/Match/MatchDetailView.swift @@ -9,6 +9,7 @@ import SwiftUI struct MatchDetailView: View { @EnvironmentObject var dataStore: DataStore + @EnvironmentObject var networkMonitor: NetworkMonitor @Environment(\.dismiss) var dismiss let matchViewStyle: MatchViewStyle @@ -23,6 +24,19 @@ struct MatchDetailView: View { @State private var endDate: Date = Date() @State private var isEditing: Bool = false @State private var showDetails: Bool = false + @State private var contactType: ContactType? = nil + @State private var sentError: ContactManagerError? = nil + + var messageSentFailed: Binding { + Binding { + sentError != nil + } set: { newValue in + if newValue == false { + sentError = nil + } + } + } + var match: Match init(match: Match, matchViewStyle: MatchViewStyle = .standardStyle) { @@ -114,7 +128,7 @@ struct MatchDetailView: View { showDetails = true } Spacer() - MenuWarningView(teams: match.teams()) + MenuWarningView(teams: match.teams(), message: match.matchWarningMessage(), umpireMail: dataStore.user?.email, subject: match.matchWarningSubject(), contactType: $contactType) .buttonStyle(.borderless) } } @@ -191,6 +205,60 @@ struct MatchDetailView: View { // } } + .alert("Un problème est survenu", isPresented: messageSentFailed) { + Button("OK") { + } + } message: { + let message = [networkMonitor.connected == false ? "L'appareil n'est pas connecté à internet." as String? : nil, sentError == .mailNotSent ? "Le mail est dans la boîte d'envoi de l'app Mail. Vérifiez son état dans l'app Mail avant d'essayer de le renvoyer." as String? : nil, (sentError == .messageFailed || sentError == .messageNotSent) ? "Le SMS n'a pas été envoyé" as String? : nil, sentError == .mailFailed ? "Le mail n'a pas été envoyé" as String? : nil].compacted().joined(separator: "\n") + Text(message) + } + .sheet(item: $contactType) { contactType in + Group { + switch contactType { + case .message(_, let recipients, let body, _): + if Guard.main.paymentForNewTournament() != nil { + MessageComposeView(recipients: recipients, body: body) { result in + switch result { + case .cancelled: + break + case .failed: + self.sentError = .messageFailed + case .sent: + if networkMonitor.connected == false { + self.sentError = .messageNotSent + } + @unknown default: + break + } + } + } else { + SubscriptionView(showLackOfPlanMessage: true) + } + case .mail(_, let recipients, let bccRecipients, let body, let subject, _): + if Guard.main.paymentForNewTournament() != nil { + MailComposeView(recipients: recipients, bccRecipients: bccRecipients, body: body, subject: subject) { result in + switch result { + case .cancelled, .saved: + self.contactType = nil + case .failed: + self.contactType = nil + self.sentError = .mailFailed + case .sent: + if networkMonitor.connected == false { + self.contactType = nil + self.sentError = .mailNotSent + } + @unknown default: + break + } + } + } else { + SubscriptionView(showLackOfPlanMessage: true) + } + } + } + .tint(.master) + } // .refreshable { // if match.isBroadcasted() { @@ -258,6 +326,7 @@ struct MatchDetailView: View { .navigationTitle(match.matchTitle()) .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .navigationBar) + } enum ScoreType: Int, Identifiable, Hashable {