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.
200 lines
7.3 KiB
200 lines
7.3 KiB
//
|
|
// TeamsCallingView.swift
|
|
// PadelClub
|
|
//
|
|
// Created by razmig on 10/07/2024.
|
|
//
|
|
|
|
import SwiftUI
|
|
import LeStorage
|
|
import PadelClubData
|
|
|
|
struct TeamsCallingView: View {
|
|
@Environment(Tournament.self) var tournament: Tournament
|
|
@EnvironmentObject var dataStore: DataStore
|
|
let teams : [TeamRegistration]
|
|
|
|
@State private var hideConfirmed: Bool = false
|
|
@State private var hideGoodSummoned: Bool = false
|
|
@State private var hideSummoned: Bool = false
|
|
@State private var searchText: String = ""
|
|
|
|
var filteredTeams: [TeamRegistration] {
|
|
teams
|
|
.filter({ hideConfirmed == false || $0.confirmed() == false })
|
|
.filter({ hideSummoned == false || $0.called() == false })
|
|
.filter({ hideGoodSummoned == false || tournament.isStartDateIsDifferentThanCallDate($0) == true })
|
|
.filter({ searchText.isEmpty || $0.contains(searchText) })
|
|
}
|
|
|
|
var anyFilterEnabled: Bool {
|
|
hideConfirmed || hideGoodSummoned || hideSummoned
|
|
}
|
|
|
|
var body: some View {
|
|
List {
|
|
if tournament.isPrivate {
|
|
Section {
|
|
RowButtonView("Rendre visible sur Padel Club") {
|
|
tournament.isPrivate = false
|
|
do {
|
|
try dataStore.tournaments.addOrUpdate(instance: tournament)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
}
|
|
} footer: {
|
|
Text("Si vous convoquez un tournoi privée, les joueurs n'auront pas le lien pour suivre le tournoi.")
|
|
.foregroundStyle(.logoRed)
|
|
}
|
|
}
|
|
|
|
|
|
PlayersWithoutContactView(players: teams.flatMap({ $0.unsortedPlayers() }).sorted(by: \.computedRank))
|
|
|
|
let called = teams.filter { tournament.isStartDateIsDifferentThanCallDate($0) == false }
|
|
let confirmed = teams.filter { $0.confirmed() }
|
|
let justCalled = teams.filter { $0.called() }
|
|
|
|
let label = "\(justCalled.count.formatted()) / \(teams.count.formatted())"
|
|
let subtitle = "dont \(called.count.formatted()) au bon horaire"
|
|
let confirmedLabel = "\(confirmed.count.formatted()) / \(teams.count.formatted())"
|
|
|
|
if teams.isEmpty == false, searchText.isEmpty {
|
|
Section {
|
|
LabeledContent {
|
|
Text(label).font(.title3)
|
|
} label: {
|
|
Text("Paire\(justCalled.count.pluralSuffix) convoquée\(justCalled.count.pluralSuffix)")
|
|
Text(subtitle)
|
|
}
|
|
LabeledContent {
|
|
Text(confirmedLabel).font(.title3)
|
|
} label: {
|
|
Text("Paire\(confirmed.count.pluralSuffix) confirmée\(confirmed.count.pluralSuffix)")
|
|
}
|
|
} footer: {
|
|
Text("Vous pouvez filtrer cette liste en appuyant sur ") + Text(Image(systemName: "line.3.horizontal.decrease.circle"))
|
|
}
|
|
}
|
|
|
|
if filteredTeams.isEmpty == false {
|
|
Section {
|
|
ForEach(filteredTeams) { team in
|
|
TeamCallView(team: team) {
|
|
searchText = ""
|
|
}
|
|
}
|
|
} header: {
|
|
HStack {
|
|
Text("Paire\(filteredTeams.count.pluralSuffix)")
|
|
Spacer()
|
|
Text(filteredTeams.count.formatted())
|
|
}
|
|
} footer: {
|
|
CallView(teams: filteredTeams)
|
|
}
|
|
} else {
|
|
ContentUnavailableView("Aucune équipe", systemImage: "person.2.slash")
|
|
}
|
|
}
|
|
.toolbar(content: {
|
|
ToolbarItem(placement: .topBarTrailing) {
|
|
Menu {
|
|
Toggle(isOn: $hideConfirmed) {
|
|
Text("Masquer les confirmées")
|
|
}
|
|
Toggle(isOn: $hideSummoned) {
|
|
Text("Masquer les convoquées")
|
|
}
|
|
Toggle(isOn: $hideGoodSummoned) {
|
|
Text("Masquer les convoquées à la bonne heure")
|
|
}
|
|
} label: {
|
|
LabelFilter()
|
|
.symbolVariant(anyFilterEnabled ? .fill : .none)
|
|
}
|
|
}
|
|
})
|
|
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
|
|
.headerProminence(.increased)
|
|
.navigationTitle("Statut des convocations")
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.toolbarBackground(.visible, for: .navigationBar)
|
|
}
|
|
}
|
|
|
|
struct CallMenuOptionsView: View {
|
|
@Environment(\.dismiss) private var dismiss
|
|
@Environment(Tournament.self) var tournament: Tournament
|
|
let team: TeamRegistration
|
|
let action: (() -> Void)?
|
|
|
|
var confirmed: Binding<Bool> {
|
|
Binding {
|
|
team.confirmed()
|
|
} set: { _ in
|
|
team.toggleSummonConfirmation()
|
|
do {
|
|
try self.tournament.tournamentStore?.teamRegistrations.addOrUpdate(instance: team)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
action?()
|
|
}
|
|
}
|
|
|
|
var body: some View {
|
|
List {
|
|
Section {
|
|
TeamRowView(team: team, displayCallDate: true)
|
|
Toggle(isOn: confirmed) {
|
|
Text("Confirmation reçue")
|
|
}
|
|
if team.expectedSummonDate() != nil {
|
|
CallView(team: team, displayContext: .menu)
|
|
}
|
|
} footer: {
|
|
CallView(teams: [team])
|
|
}
|
|
|
|
Section {
|
|
NavigationLink {
|
|
EditingTeamView(team: team)
|
|
.environment(tournament)
|
|
} label: {
|
|
Text("Détails de l'équipe")
|
|
}
|
|
}
|
|
|
|
Section {
|
|
RowButtonView("Effacer la date de convocation", role: .destructive) {
|
|
team.callDate = nil
|
|
do {
|
|
try self.tournament.tournamentStore?.teamRegistrations.addOrUpdate(instance: team)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
action?()
|
|
dismiss()
|
|
}
|
|
}
|
|
|
|
Section {
|
|
RowButtonView("Indiquer comme convoquée", role: .destructive) {
|
|
team.callDate = team.initialMatch()?.startDate ?? tournament.startDate
|
|
do {
|
|
try self.tournament.tournamentStore?.teamRegistrations.addOrUpdate(instance: team)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
action?()
|
|
dismiss()
|
|
}
|
|
}
|
|
}
|
|
.navigationTitle("Options de convocation")
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.toolbarBackground(.visible, for: .navigationBar)
|
|
}
|
|
}
|
|
|