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.
305 lines
12 KiB
305 lines
12 KiB
//
|
|
// FollowUpMatchView.swift
|
|
// PadelClub
|
|
//
|
|
// Created by razmig on 11/10/2024.
|
|
//
|
|
|
|
import SwiftUI
|
|
import PadelClubData
|
|
|
|
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 "Piste"
|
|
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, runningMatches: runningMatches)
|
|
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, runningMatches: runningMatches)
|
|
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 readyMatches.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..<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 la piste")
|
|
}
|
|
.labelsHidden()
|
|
.underline()
|
|
}
|
|
}
|
|
}
|
|
.onChange(of: readyMatches) {
|
|
dismissWhenPresentFollowUpMatchIsDismissed = true
|
|
if autoDismiss {
|
|
dismiss()
|
|
} else if readyMatches.isEmpty && matchesLeft.isEmpty {
|
|
dismiss()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|