// // FollowUpMatchView.swift // PadelClub // // Created by razmig on 11/10/2024. // import SwiftUI struct FollowUpMatchView: View { @EnvironmentObject var dataStore: DataStore @Environment(\.dismiss) private var dismiss let match: Match? let readyMatches: [Match] let matchesLeft: [Match] let isFree: Bool var autoDismiss: Bool = false @State private var sortingMode: SortingMode? = .index @State private var selectedCourt: Int? @State private var checkCanPlay: Bool = false @State private var seeAll: Bool = true @Binding var dismissWhenPresentFollowUpMatchIsDismissed: Bool var matches: [Match] { seeAll ? matchesLeft : readyMatches } enum SortingMode: Int, Identifiable, CaseIterable, Selectable, Equatable { func selectionLabel(index: Int) -> String { localizedSortingModeLabel() } func badgeValue() -> Int? { nil } func badgeImage() -> Badge? { nil } func badgeValueColor() -> Color? { nil } static func == (lhs: SortingMode, rhs: SortingMode) -> Bool { return lhs.id == rhs.id } var id: Int { self.rawValue } case winner case loser case index case restingTime case court func canHaveSeeAllOption() -> Bool { switch self { case .index, .restingTime: return true case .winner, .loser, .court: return false } } func localizedSortingModeLabel() -> String { switch self { case .index: return "Ordre prévu" case .court: return "Terrain" case .restingTime: return "Temps de repos" case .winner: return "Gagnant" case .loser: return "Perdant" } } } init(match: Match, dismissWhenPresentFollowUpMatchIsDismissed: Binding) { _dismissWhenPresentFollowUpMatchIsDismissed = dismissWhenPresentFollowUpMatchIsDismissed self.match = match _selectedCourt = .init(wrappedValue: match.courtIndex) let currentTournament = match.currentTournament() let allMatches = currentTournament?.allMatches() ?? [] self.matchesLeft = Tournament.matchesLeft(allMatches) let runningMatches = Tournament.runningMatches(allMatches) let readyMatches = Tournament.readyMatches(allMatches) self.readyMatches = Tournament.availableToStart(readyMatches, in: runningMatches, checkCanPlay: false) self.isFree = currentTournament?.isFree() ?? true } init(selectedCourt: Int?, allMatches: [Match], autoDismiss: Bool = true) { _dismissWhenPresentFollowUpMatchIsDismissed = .constant(false) _selectedCourt = .init(wrappedValue: selectedCourt) self.match = nil self.autoDismiss = autoDismiss self.matchesLeft = Tournament.matchesLeft(allMatches) let runningMatches = Tournament.runningMatches(allMatches) let readyMatches = Tournament.readyMatches(allMatches) self.readyMatches = Tournament.availableToStart(readyMatches, in: runningMatches, checkCanPlay: false) self.isFree = false } var winningTeam: TeamRegistration? { match?.winner() } var losingTeam: TeamRegistration? { match?.loser() } var sortingModeCases: [SortingMode] { var sortingModes = [SortingMode]() if winningTeam != nil { sortingModes.append(.winner) } if losingTeam != nil { sortingModes.append(.loser) } sortingModes.append(.index) sortingModes.append(.restingTime) // sortingModes.append(.court) return sortingModes } func contentUnavailableDescriptionLabel() -> String { switch sortingMode! { case .winner: if let winningTeam { return "Aucun match à suivre pour \(winningTeam.teamLabel())" } else { return "La paire gagnante n'a pas été décidé" } case .loser: if let losingTeam { return "Aucun match à suivre pour \(losingTeam.teamLabel())" } else { return "La paire perdante n'a pas été décidé" } case .index: return "Ce tournoi n'a aucun match prêt à démarrer" case .restingTime: return "Ce tournoi n'a aucun match prêt à démarrer" case .court: return "Ce tournoi n'a aucun match prêt à démarrer" } } var sortedMatches: [Match] { switch sortingMode! { case .index: return matches case .restingTime: return matches.sorted(by: \.restingTimeForSorting) case .court: return matchesLeft.filter({ $0.courtIndex == selectedCourt }) case .winner: if let winningTeam, let followUpMatch = matchesLeft.first(where: { $0.containsTeamId(winningTeam.id) }) { return [followUpMatch] } else { return [] } case .loser: if let losingTeam, let followUpMatch = matchesLeft.first(where: { $0.containsTeamId(losingTeam.id) }) { return [followUpMatch] } else { return [] } } } var body: some View { NavigationStack { VStack(spacing: 0) { GenericDestinationPickerView(selectedDestination: $sortingMode, destinations: sortingModeCases, nilDestinationIsValid: false) List { // // Toggle(isOn: $checkCanPlay) { // if isFree { // Text("Vérifier le paiement ou la présence") // } else { // Text("Vérifier la présence") // } // } // } footer: { // if isFree { // Text("Masque les matchs où un ou plusieurs joueurs qui ne sont pas encore arrivé") // } else { // Text("Masque les matchs où un ou plusieurs joueurs n'ont pas encore réglé ou qui ne sont pas encore arrivé") // } if sortedMatches.isEmpty == false { ForEach(sortedMatches) { match in let tournament = match.currentTournament() Section { MatchRowView(match: match, updatedField: selectedCourt) .matchViewStyle(.followUpStyle) } header: { if let tournament { HStack { Text(tournament.tournamentTitle(.short)) Spacer() if let club = tournament.club() { Text("@" + club.clubTitle(.short)) } } } } footer: { HStack { if let tournament { Text(tournament.eventLabel()) } #if DEBUG Spacer() if let roundObject = match.roundObject { Text(roundObject.index.formatted()) Text(roundObject.theoryCumulativeMatchCount.formatted()) } Text(match.computedOrder.formatted()) FooterButtonView("copier l'id") { let pasteboard = UIPasteboard.general pasteboard.string = match.id } #endif } } } } else { ContentUnavailableView("Aucun match à venir", systemImage: "xmark.circle", description: Text(contentUnavailableDescriptionLabel())) } } .navigationTitle("À suivre sur") .toolbarBackground(.visible, for: .navigationBar) .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .bottomBar) .toolbarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .topBarLeading) { Button("Retour", role: .cancel) { if readyMatches.isEmpty && matchesLeft.isEmpty { dismissWhenPresentFollowUpMatchIsDismissed = true } dismiss() } } ToolbarItem(placement: .status) { Button { seeAll.toggle() } label: { Text(seeAll ? "Masquer les matchs incomplets" : "Voir tous les matchs") .underline() } .disabled(sortingMode?.canHaveSeeAllOption() == false) } // ToolbarItem(placement: .principal) { // Picker(selection: $sortingMode) { // ForEach(sortingModeCases) { sortingMode in // Text(sortingMode.localizedSortingModeLabel()).tag(sortingMode) // } // } label: { // Text("Méthode de tri") // } // .labelsHidden() // .pickerStyle(.segmented) // } ToolbarItem(placement: .topBarTrailing) { Picker(selection: $selectedCourt) { Image(systemName: "sportscourt").tag(nil as Int?) if let tournament = match?.currentTournament() { ForEach(0..