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.
 
 
PadelClub/PadelClub/Views/Score/FollowUpMatchView.swift

296 lines
12 KiB

//
// 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<Bool>) {
_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, matchViewStyle: .followUpStyle, updatedField: selectedCourt)
} 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()
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..<tournament.courtCount, id: \.self) { courtIndex in
Text(tournament.courtName(atIndex: courtIndex)).tag(courtIndex as Int?)
}
} else {
ForEach(0..<12, id: \.self) { courtIndex in
Text(Court.courtIndexedTitle(atIndex: courtIndex)).tag(courtIndex as Int?)
}
}
} label: {
Text("Sur le terrain")
}
.labelsHidden()
.underline()
}
}
}
.onChange(of: readyMatches) {
if autoDismiss {
dismissWhenPresentFollowUpMatchIsDismissed = true
dismiss()
}
}
}
}
}