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/Match/MatchSetupView.swift

243 lines
11 KiB

//
// MatchSetupView.swift
// PadelClub
//
// Created by Razmig Sarkissian on 23/03/2024.
//
import SwiftUI
import LeStorage
struct MatchSetupView: View {
static let confirmationMessage = "Au moins une tête de série a été placée dans la branche de ce match dans les tours précédents. En plaçant une équipe sur ici, les équipes déjà placées dans la même branche seront retirées du tableau et devront être replacées."
@EnvironmentObject var dataStore: DataStore
@State var match: Match
@State private var seedGroup: SeedInterval?
var tournamentStore: TournamentStore {
return match.tournamentStore
}
var matchTypeContext: MatchType {
match.matchType
}
@ViewBuilder
var body: some View {
ForEach(TeamPosition.allCases) { teamPosition in
_teamView(inTeamPosition: teamPosition)
}
}
@ViewBuilder
func _teamView(inTeamPosition teamPosition: TeamPosition) -> some View {
let scores = match.teamScores
let team = scores.isEmpty ? nil : match.team(teamPosition)
let teamScore = (team != nil) ? scores.first(where: { $0.teamRegistration == team!.id }) : nil
let walkOutSpot = teamScore?.walkOut == 1
let shouldConfirm = match.previousMatch(teamPosition)?.isSeeded() == true
if let team, teamScore?.walkOut == nil {
VStack(alignment: .leading, spacing: 0) {
if let teamScore, teamScore.luckyLoser != nil, match.isLoserBracket == false {
Text("Repêchée").italic().font(.caption)
}
Menu {
_removeTeam(team: team, teamPosition: teamPosition)
} label: {
TeamRowView(team: team, teamPosition: teamPosition)
}
.buttonStyle(.plain)
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
_removeTeam(team: team, teamPosition: teamPosition)
}
}
} else {
VStack(alignment: .leading) {
if let team {
TeamRowView(team: team, teamPosition: teamPosition)
.strikethrough()
}
HStack {
let luckyLosers = walkOutSpot ? match.luckyLosers() : []
TeamPickerView(shouldConfirm: shouldConfirm, round: match.roundObject, matchTypeContext: matchTypeContext, luckyLosers: luckyLosers, teamPicked: { team in
print(team.pasteData())
if walkOutSpot || team.bracketPosition != nil || matchTypeContext == .loserBracket {
match.setLuckyLoser(team: team, teamPosition: teamPosition)
do {
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
} else if team.bracketPosition == nil {
team.setSeedPosition(inSpot: match, slot: teamPosition, opposingSeeding: false)
do {
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
do {
try tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}
}
})
.environment(match)
if matchTypeContext == .bracket, let tournament = match.currentTournament() {
let availableQualifiedTeams = tournament.availableQualifiedTeams()
let availableSeedGroups = tournament.availableSeedGroups()
Text("ou")
Menu {
if walkOutSpot, luckyLosers.isEmpty == false {
Button {
if let randomTeam = luckyLosers.randomElement() {
match.setLuckyLoser(team: randomTeam, teamPosition: teamPosition)
do {
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
}
} label: {
Label("Repêchage", systemImage: "dice")
}
}
if availableQualifiedTeams.isEmpty == false {
ConfirmButtonView(shouldConfirm: shouldConfirm, message: MatchSetupView.confirmationMessage) {
if let randomTeam = availableQualifiedTeams.randomElement() {
randomTeam.setSeedPosition(inSpot: match, slot: teamPosition, opposingSeeding: false)
do {
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
do {
try tournamentStore.teamRegistrations.addOrUpdate(instance: randomTeam)
} catch {
Logger.error(error)
}
}
} label: {
Label("Qualifié sortant", systemImage: "dice")
}
}
ForEach(availableSeedGroups, id: \.self) { seedGroup in
ConfirmButtonView(shouldConfirm: shouldConfirm, message: MatchSetupView.confirmationMessage) {
if let randomTeam = tournament.randomSeed(fromSeedGroup: seedGroup) {
randomTeam.setSeedPosition(inSpot: match, slot: teamPosition, opposingSeeding: false)
do {
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
do {
try tournamentStore.teamRegistrations.addOrUpdate(instance: randomTeam)
} catch {
Logger.error(error)
}
}
} label: {
Label(seedGroup.localizedInterval(), systemImage: "dice")
}
}
} label: {
Text("Tirer au sort").tag(nil as SeedInterval?)
.underline()
}
.disabled(availableSeedGroups.isEmpty && walkOutSpot == false && availableQualifiedTeams.isEmpty)
if matchTypeContext == .bracket {
Spacer()
if match.isSeedLocked(atTeamPosition: teamPosition) {
Button {
match.unlockSeedPosition(atTeamPosition: teamPosition)
do {
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
} label: {
Text("Libérer")
.underline()
}
} else {
ConfirmButtonView(shouldConfirm: shouldConfirm, message: MatchSetupView.confirmationMessage) {
_ = match.lockAndGetSeedPosition(atTeamPosition: teamPosition)
do {
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
} label: {
Text("Réserver")
.underline()
}
}
}
}
}
.fixedSize(horizontal: false, vertical: true)
.buttonStyle(.borderless)
}
}
}
func _removeTeam(team: TeamRegistration, teamPosition: TeamPosition) -> some View {
Button(role: .cancel) {
//todo
if match.isSeededBy(team: team, inTeamPosition: teamPosition) {
team.bracketPosition = nil
do {
try tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}
//match.updateTeamScores()
match.previousMatches().forEach { previousMatch in
if previousMatch.disabled {
previousMatch.enableMatch()
do {
try tournamentStore.matches.addOrUpdate(instance: previousMatch)
} catch {
Logger.error(error)
}
}
}
do {
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
} else if match.isLoserBracket {
if let score = match.teamScore(ofTeam: team) {
do {
try tournamentStore.teamScores.delete(instance: score)
} catch {
Logger.error(error)
}
}
} else {
match.teamWillBeWalkOut(team)
do {
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
}
} label: {
Label("retirer", systemImage: "xmark")
}
}
}
//#Preview {
// MatchSetupView(match: Match.mock())
// .environmentObject(DataStore.shared)
//}