diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index 9083e8b..1cd11de 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -3650,7 +3650,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.23; + MARKETING_VERSION = 1.1.25; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -3695,7 +3695,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.23; + MARKETING_VERSION = 1.1.25; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/PadelClub/Data/Round.swift b/PadelClub/Data/Round.swift index 4469b28..452d992 100644 --- a/PadelClub/Data/Round.swift +++ b/PadelClub/Data/Round.swift @@ -644,9 +644,9 @@ defer { let roundCount = RoundRule.numberOfRounds(forTeams: currentRoundMatchCount) var loserBracketMatchFormat = tournamentObject()?.loserBracketMatchFormat - if let parentRound { - loserBracketMatchFormat = tournamentObject()?.loserBracketSmartMatchFormat(parentRound.index) - } +// if let parentRound { +// loserBracketMatchFormat = tournamentObject()?.loserBracketSmartMatchFormat(parentRound.index) +// } let rounds = (0.. String? { if isWildCard() { - let wildcardLabel: String = ["wildcard", (wildCardBracket ? "tableau" : "poule")] - .joined(separator: " ") + let wildcardLabel: String = ["Wildcard", (wildCardBracket ? "Tableau" : "Poule")].joined(separator: " ") return wildcardLabel } else { return nil @@ -700,22 +699,48 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable { unsortedPlayers().count > 0 } - func bracketMatchTitleAndQualifiedStatus() -> String? { - let v = groupStageObject()?.groupStageTitle() - var base = "Qualifié" - if qualified { - if let groupStageTitle = groupStageObject()?.groupStageTitle() { - base = base + " (\(groupStageTitle))" - } - } - - let suffix = qualified ? nil : groupStageObject()?.groupStageTitle() - let initalMatchTitle = initialMatch()?.roundAndMatchTitle() ?? suffix - let values = [qualified ? base : nil, initalMatchTitle].compactMap({ $0 }) - if values.isEmpty { - return nil + func teamInitialPositionBracket() -> String? { + let round = initialMatch()?.roundAndMatchTitle() + if let round { + return round + } + return nil + } + + func teamInitialPositionGroupStage() -> String? { + let groupStage = self.groupStageObject() + let group = groupStage?.groupStageTitle(.title) + var groupPositionLabel: String? = nil + if let finalPosition = groupStage?.finalPosition(ofTeam: self) { + groupPositionLabel = (finalPosition + 1).ordinalFormatted() + } else if let groupStagePosition { + groupPositionLabel = "\(groupStagePosition + 1)" + } + + if let group { + if let groupPositionLabel { + return [group, "#\(groupPositionLabel)"].joined(separator: " ") + } else { + return group + } + } + return nil + } + + func qualifiedStatus(hideBracketStatus: Bool = false) -> String? { + let teamInitialPositionBracket = teamInitialPositionBracket() + let groupStageTitle = teamInitialPositionGroupStage() + + let base: String? = qualified ? "Qualifié" : nil + if let groupStageTitle, let teamInitialPositionBracket, hideBracketStatus == false { + return [base, groupStageTitle, ">", teamInitialPositionBracket].compactMap({ $0 }).joined(separator: " ") + } else if let groupStageTitle { + return [base, groupStageTitle].compactMap({ $0 }).joined(separator: " ") + } else if hideBracketStatus == false { + return teamInitialPositionBracket } - return values.joined(separator: " -> ") + + return nil } func insertOnServer() { diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index 07feb15..b529584 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -1612,7 +1612,7 @@ defer { var _groupStages = [GroupStage]() for index in 0.. some View { + let selectedSortedTeams = tournament.selectedSortedTeams() ForEach(teams) { team in if searchField.isEmpty || team.contains(searchField) { Button { @@ -134,15 +136,10 @@ struct TeamPickerView: View { // presentTeamPickerView = false // } } label: { - VStack(alignment: .leading) { - if let roundAndMatchTitle = team.bracketMatchTitleAndQualifiedStatus() { - Text(roundAndMatchTitle) - .font(.headline) - .frame(maxWidth: .infinity, alignment: .leading) - } - TeamRowView(team: team) - } - .contentShape(Rectangle()) + let teamIndex = team.index(in: selectedSortedTeams) + TeamRowView(team: team, teamIndex: teamIndex) + .environment(\.isEditingTournamentSeed, .constant(false)) + .contentShape(Rectangle()) } .frame(maxWidth: .infinity) .buttonStyle(.plain) diff --git a/PadelClub/Views/Team/TeamRowView.swift b/PadelClub/Views/Team/TeamRowView.swift index bb32774..13b5ee0 100644 --- a/PadelClub/Views/Team/TeamRowView.swift +++ b/PadelClub/Views/Team/TeamRowView.swift @@ -9,7 +9,6 @@ import SwiftUI struct TeamRowView: View { @EnvironmentObject var dataStore: DataStore - @Environment(\.isEditingTournamentSeed) private var isEditingTournamentSeed var team: TeamRegistration var teamPosition: TeamPosition? = nil @@ -22,9 +21,7 @@ struct TeamRowView: View { TeamWeightView(team: team, teamPosition: teamPosition, teamIndex: teamIndex) } label: { VStack(alignment: .leading) { - if isEditingTournamentSeed.wrappedValue == false { - TeamHeadlineView(team: team) - } + TeamHeadlineView(team: team) TeamView(team: team) } if displayCallDate { @@ -78,23 +75,19 @@ struct TeamRowView: View { } struct TeamHeadlineView: View { + @Environment(\.isEditingTournamentSeed) private var isEditingTournamentSeed let team: TeamRegistration var body: some View { - HStack { - if let groupStage = team.groupStageObject() { - HStack { - Text(groupStage.groupStageTitle(.title)) - if let finalPosition = groupStage.finalPosition(ofTeam: team) { - Text((finalPosition + 1).ordinalFormatted()) - } - } - } else if let round = team.initialRound() { - Text(round.roundTitle(.wide)) - } - + VStack(alignment: .leading) { if let wildcardLabel = team.wildcardLabel() { - Text(wildcardLabel).italic().foregroundStyle(.red).font(.caption) + Text(wildcardLabel).italic().foregroundStyle(.logoRed).font(.caption) + } + + if let qualifiedStatus = team.qualifiedStatus(hideBracketStatus: isEditingTournamentSeed.wrappedValue == true) { + Text(qualifiedStatus) + .font(.caption) + .foregroundStyle(.secondary) } } } diff --git a/PadelClub/Views/Tournament/Screen/AddTeamView.swift b/PadelClub/Views/Tournament/Screen/AddTeamView.swift index 5ebb60e..09a12d0 100644 --- a/PadelClub/Views/Tournament/Screen/AddTeamView.swift +++ b/PadelClub/Views/Tournament/Screen/AddTeamView.swift @@ -216,6 +216,7 @@ struct AddTeamView: View { let first = strings.first ?? "" handlePasteString(first) } + .disabled(_limitPlayerCount()) .foregroundStyle(.master) .labelStyle(.titleAndIcon) .buttonBorderShape(.capsule) @@ -236,6 +237,7 @@ struct AddTeamView: View { } label: { Label("Coller", systemImage: "doc.on.clipboard").labelStyle(.iconOnly) } + .disabled(_limitPlayerCount()) .foregroundStyle(.master) .labelStyle(.iconOnly) .buttonBorderShape(.capsule) @@ -258,12 +260,20 @@ struct AddTeamView: View { tournament.unsortedPlayers() } + private func _limitPlayerCount() -> Bool { + if tournament.isAnimation() { + return false + } + return _currentSelection().count >= tournament.significantPlayerCount() + } + @ViewBuilder private func _managementView() -> some View { Section { RowButtonView("Ajouter via la base fédérale") { presentPlayerSearch = true } + .disabled(_limitPlayerCount()) } footer: { if let rankSourceDate = tournament.rankSourceDate { Text("Cherchez dans la base fédérale de \(rankSourceDate.monthYearFormatted), vous y trouverez tous les joueurs ayant participé à au moins un tournoi dans les 12 derniers mois.") @@ -288,6 +298,7 @@ struct AddTeamView: View { presentPlayerCreation = true } } + .disabled(_limitPlayerCount()) } footer: { Text("Si le joueur n'a pas encore de licence ou n'a pas encore participé à une compétition, vous pouvez le créer vous-même.") } @@ -541,6 +552,10 @@ struct AddTeamView: View { // } else { // Text("Préparation de l'équipe") } + } footer: { + if _limitPlayerCount() { + Text("Taille maximum de l'équipe atteinte, supprimer un joueur pour pouvoir en rajouter un autre").foregroundStyle(.logoRed) + } } diff --git a/PadelClub/Views/Tournament/Screen/Components/TournamentStatusView.swift b/PadelClub/Views/Tournament/Screen/Components/TournamentStatusView.swift index 23bdad9..2d3ce23 100644 --- a/PadelClub/Views/Tournament/Screen/Components/TournamentStatusView.swift +++ b/PadelClub/Views/Tournament/Screen/Components/TournamentStatusView.swift @@ -49,14 +49,15 @@ struct TournamentStatusView: View { let event = tournament.eventObject() let isLastTournament = event?.tournaments.count == 1 - tournament.isDeleted = true - - try dataStore.tournaments.addOrUpdate(instance: tournament) - - if let event, isLastTournament { - try dataStore.events.delete(instance: event) + if tournament.onlineTeams().isEmpty == false { + tournament.isDeleted = true + try dataStore.tournaments.addOrUpdate(instance: tournament) } else { - try dataStore.tournaments.delete(instance: tournament) + if let event, isLastTournament { + try dataStore.events.delete(instance: event) + } else { + try dataStore.tournaments.delete(instance: tournament) + } } if eventDismiss == false || isLastTournament { navigation.path = NavigationPath() diff --git a/PadelClub/Views/Tournament/Screen/TableStructureView.swift b/PadelClub/Views/Tournament/Screen/TableStructureView.swift index 960179f..027c00f 100644 --- a/PadelClub/Views/Tournament/Screen/TableStructureView.swift +++ b/PadelClub/Views/Tournament/Screen/TableStructureView.swift @@ -81,12 +81,7 @@ struct TableStructureView: View { Text(structurePreset.localizedDescriptionStructurePresetTitle()) } .onChange(of: structurePreset) { - teamCount = structurePreset.tableDimension() + structurePreset.teamsInQualifiers() - structurePreset.qualifiedPerGroupStage() * structurePreset.groupStageCount() - groupStageCount = structurePreset.groupStageCount() - teamsPerGroupStage = structurePreset.teamsPerGroupStage() - qualifiedPerGroupStage = structurePreset.qualifiedPerGroupStage() - groupStageAdditionalQualified = 0 - buildWildcards = tournament.level.wildcardArePossible() + _updatePreset() } } @@ -293,8 +288,27 @@ struct TableStructureView: View { Section { RowButtonView("Remise-à-zéro", role: .destructive) { + tournament.removeWildCards() tournament.deleteGroupStages() tournament.deleteStructure() + + if structurePreset != .manual { + structurePreset = PadelTournamentStructurePreset.manual + } else { + _updatePreset() + } + + tournament.teamCount = teamCount + tournament.groupStageCount = groupStageCount + tournament.teamsPerGroupStage = teamsPerGroupStage + tournament.qualifiedPerGroupStage = qualifiedPerGroupStage + tournament.groupStageAdditionalQualified = groupStageAdditionalQualified + + do { + try dataStore.tournaments.addOrUpdate(instance: tournament) + } catch { + Logger.error(error) + } } } } @@ -443,11 +457,12 @@ struct TableStructureView: View { tournament.groupStageAdditionalQualified = groupStageAdditionalQualified if rebuildEverything { - tournament.deleteAndBuildEverything(preset: structurePreset) + tournament.removeWildCards() if structurePreset.hasWildcards(), buildWildcards { tournament.addWildCardIfNeeded(structurePreset.wildcardBrackets(), .bracket) tournament.addWildCardIfNeeded(structurePreset.wildcardQualifiers(), .groupStage) } + tournament.deleteAndBuildEverything(preset: structurePreset) } else if (rebuildEverything == false && requirements.contains(.groupStage)) { tournament.deleteGroupStages() tournament.buildGroupStages() @@ -466,6 +481,15 @@ struct TableStructureView: View { } } + private func _updatePreset() { + teamCount = structurePreset.tableDimension() + structurePreset.teamsInQualifiers() - structurePreset.qualifiedPerGroupStage() * structurePreset.groupStageCount() + groupStageCount = structurePreset.groupStageCount() + teamsPerGroupStage = structurePreset.teamsPerGroupStage() + qualifiedPerGroupStage = structurePreset.qualifiedPerGroupStage() + groupStageAdditionalQualified = 0 + buildWildcards = tournament.level.wildcardArePossible() + } + private func _verifyValueIntegrity() { if teamCount > 128 { teamCount = 128