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/Tournament/Screen/TournamentCashierView.swift

205 lines
7.4 KiB

//
// TournamentCashierView.swift
// PadelClub
//
// Created by Razmig Sarkissian on 17/04/2024.
//
import SwiftUI
import Combine
import PadelClubData
enum CashierDestination: Identifiable, Selectable, Equatable {
static func == (lhs: CashierDestination, rhs: CashierDestination) -> Bool {
return lhs.id == rhs.id
}
case summary
case groupStage(GroupStage)
case bracket(Round)
case all(Tournament)
var id: String {
switch self {
case .summary:
return String(describing: self)
case .all(let tournament):
return tournament.id
case .groupStage(let groupStage):
return groupStage.id
case .bracket(let round):
return round.id
}
}
func selectionLabel(index: Int) -> String {
switch self {
case .summary:
return "Bilan"
case .groupStage(let groupStage):
return groupStage.selectionLabel(index: index)
case .bracket(let round):
return round.selectionLabel(index: index)
case .all:
return "Tous"
}
}
func displayImageIfValueZero() -> Bool {
return true
}
func badgeValue() -> Int? {
switch self {
case .summary:
return nil
case .groupStage(let groupStage):
if groupStage.tournamentObject()?.isFree() == true {
return groupStage.unsortedPlayers().filter({ $0.hasArrived == false }).count
}
return groupStage.unsortedPlayers().filter({ $0.hasPaid() == false }).count
case .bracket(let round):
let playerRegistrations: [PlayerRegistration] = round.seeds().flatMap { $0.unsortedPlayers() }
if round.tournamentObject()?.isFree() == true {
return playerRegistrations.filter({ $0.hasArrived == false }).count
}
return playerRegistrations.filter({ $0.hasPaid() == false }).count
case .all(_):
return nil
}
}
func badgeValueColor() -> Color? {
return nil
}
func badgeImage() -> Badge? {
switch self {
case .summary:
return nil
case .all:
return nil
default:
return .checkmark
}
}
}
struct TournamentCashierView: View {
var tournament: Tournament
@State private var selectedDestination: CashierDestination?
@StateObject private var cashierViewModel: CashierViewModel = CashierViewModel()
var allDestinations: [CashierDestination]
init(tournament: Tournament) {
self.tournament = tournament
var allDestinations : [CashierDestination] = []
let tournamentHasEnded = tournament.hasEnded()
if tournamentHasEnded {
allDestinations.append(.summary)
}
let all = CashierDestination.all(tournament)
allDestinations.append(all)
let destinations: [CashierDestination] = tournament.groupStages().map { CashierDestination.groupStage($0) }
allDestinations.append(contentsOf: destinations)
tournament.rounds().forEach { round in
if round.seeds().isEmpty == false {
allDestinations.append(CashierDestination.bracket(round))
}
}
if tournamentHasEnded == false {
allDestinations.append(.summary)
}
self.allDestinations = allDestinations
_selectedDestination = .init(wrappedValue: all)
// if tournament.hasEnded() {
// if tournament.players().anySatisfy({ $0.hasPaid() == false }) == false {
// _selectedDestination = .init(wrappedValue: .summary)
// } else {
// _selectedDestination = .init(wrappedValue: all)
// }
// } else {
// let gs = tournament.getActiveGroupStage()
// if let gs, let destination = allDestinations.first(where: { $0.id == gs.id }) {
// _selectedDestination = State(wrappedValue: destination)
// } else if let rs = tournament.getActiveRound(withSeeds: true), let destination = allDestinations.first(where: { $0.id == rs.id }) {
// _selectedDestination = State(wrappedValue: destination)
// }
// }
}
var body: some View {
if let store = self.tournament.tournamentStore {
VStack(spacing: 0) {
GenericDestinationPickerView(selectedDestination: $selectedDestination, destinations: allDestinations, nilDestinationIsValid: true)
switch selectedDestination {
case .none:
CashierSettingsView(tournament: tournament)
case .some(let selectedCall):
switch selectedCall {
case .summary:
CashierDetailView(tournament: tournament).id(selectedCall.id)
case .groupStage(let groupStage):
CashierView(tournament: tournament, teams: groupStage.teams()).id(selectedCall.id)
.searchable(text: $cashierViewModel.searchText, isPresented: $cashierViewModel.isSearching, placement: .navigationBarDrawer(displayMode: .always), prompt: Text("Chercher un joueur"))
case .bracket(let round):
CashierView(tournament: tournament, teams: round.seeds()).id(selectedCall.id)
.searchable(text: $cashierViewModel.searchText, isPresented: $cashierViewModel.isSearching, placement: .navigationBarDrawer(displayMode: .always), prompt: Text("Chercher un joueur"))
case .all(let tournament):
CashierView(tournament: tournament, teams: tournament.selectedSortedTeams()).id(selectedCall.id)
.searchable(text: $cashierViewModel.searchText, isPresented: $cashierViewModel.isSearching, placement: .navigationBarDrawer(displayMode: .always), prompt: Text("Chercher un joueur"))
}
}
}
.environment(tournament)
.environmentObject(store)
.environmentObject(cashierViewModel)
.navigationBarTitleDisplayMode(.inline)
.toolbarBackground(.visible, for: .navigationBar)
.navigationTitle(tournament.isFree() ? "Présence" : "Encaissement")
.ifAvailableiOS26 {
if #available(iOS 26.0, *) {
$0.navigationSubtitle(tournament.tournamentTitle())
}
}
} else {
Text("no store")
}
}
}
//#Preview {
// TournamentCashierView(tournament: Tournament.mock())
//}
//class DebouncedObject: ObservableObject {
// @Published var searchText: String = "" {
// didSet {
// debounceSearchTextPublisher.send(searchText)
// }
// }
//
// private var debounceSearchTextPublisher = PassthroughSubject<String, Never>()
// private var cancellables = Set<AnyCancellable>()
//
// init() {
// debounceSearchTextPublisher
// .debounce(for: .milliseconds(300), scheduler: RunLoop.main)
// .sink { [weak self] in self?.performSearch(with: $0) }
// .store(in: &cancellables)
// }
//
// private func performSearch(with text: String) {
// // Perform the search with the debounced text
// print("Performing search with text: \(text)")
// }
//}