diff --git a/PadelClub/Data/PlayerRegistration.swift b/PadelClub/Data/PlayerRegistration.swift index 4ac2e11..f894a4f 100644 --- a/PadelClub/Data/PlayerRegistration.swift +++ b/PadelClub/Data/PlayerRegistration.swift @@ -62,29 +62,29 @@ final class PlayerRegistration: ModelObject, Storable { internal init(importedPlayer: ImportedPlayer) { self.teamRegistration = "" - self.firstName = (importedPlayer.firstName ?? "").trimmed.capitalized - self.lastName = (importedPlayer.lastName ?? "").trimmed.uppercased() - self.licenceId = importedPlayer.license ?? nil + self.firstName = (importedPlayer.firstName ?? "").prefixTrimmed(50).capitalized + self.lastName = (importedPlayer.lastName ?? "").prefixTrimmed(50).uppercased() + self.licenceId = importedPlayer.license?.prefixTrimmed(50) ?? nil self.rank = Int(importedPlayer.rank) self.sex = importedPlayer.male ? .male : .female self.tournamentPlayed = importedPlayer.tournamentPlayed self.points = importedPlayer.getPoints() - self.clubName = importedPlayer.clubName - self.ligueName = importedPlayer.ligueName - self.assimilation = importedPlayer.assimilation + self.clubName = importedPlayer.clubName?.prefixTrimmed(200) + self.ligueName = importedPlayer.ligueName?.prefixTrimmed(200) + self.assimilation = importedPlayer.assimilation?.prefixTrimmed(50) self.source = .frenchFederation - self.birthdate = importedPlayer.birthYear + self.birthdate = importedPlayer.birthYear?.prefixTrimmed(50) } internal init?(federalData: [String], sex: Int, sexUnknown: Bool) { let _lastName = federalData[0].trimmed.uppercased() let _firstName = federalData[1].trimmed.capitalized if _lastName.isEmpty && _firstName.isEmpty { return nil } - lastName = _lastName - firstName = _firstName - birthdate = federalData[2].formattedAsBirthdate() - licenceId = federalData[3] - clubName = federalData[4] + lastName = _lastName.prefixTrimmed(50) + firstName = _firstName.prefixTrimmed(50) + birthdate = federalData[2].formattedAsBirthdate().prefixTrimmed(50) + licenceId = federalData[3].prefixTrimmed(50) + clubName = federalData[4].prefixTrimmed(200) let stringRank = federalData[5] if stringRank.isEmpty { rank = nil @@ -93,11 +93,11 @@ final class PlayerRegistration: ModelObject, Storable { } let _email = federalData[6] if _email.isEmpty == false { - self.email = _email + self.email = _email.prefixTrimmed(50) } let _phoneNumber = federalData[7] if _phoneNumber.isEmpty == false { - self.phoneNumber = _phoneNumber + self.phoneNumber = _phoneNumber.prefixTrimmed(50) } source = .beachPadel diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index 285a7b9..7d66f8a 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -58,6 +58,8 @@ final class Tournament : ModelObject, Storable { var hidePointsEarned: Bool = false var publishRankings: Bool = false var loserBracketMode: LoserBracketMode = .automatic + var initialSeedRound: Int = 0 + var initialSeedCount: Int = 0 @ObservationIgnored var navigationPath: [Screen] = [] @@ -107,9 +109,12 @@ final class Tournament : ModelObject, Storable { case _hidePointsEarned = "hidePointsEarned" case _publishRankings = "publishRankings" case _loserBracketMode = "loserBracketMode" + case _initialSeedRound = "initialSeedRound" + case _initialSeedCount = "initialSeedCount" + } - internal init(event: String? = nil, name: String? = nil, startDate: Date = Date(), endDate: Date? = nil, creationDate: Date = Date(), isPrivate: Bool = false, groupStageFormat: MatchFormat? = nil, roundFormat: MatchFormat? = nil, loserRoundFormat: MatchFormat? = nil, groupStageSortMode: GroupStageOrderingMode, groupStageCount: Int = 4, rankSourceDate: Date? = nil, dayDuration: Int = 1, teamCount: Int = 24, teamSorting: TeamSortingType? = nil, federalCategory: TournamentCategory, federalLevelCategory: TournamentLevel, federalAgeCategory: FederalTournamentAge, closedRegistrationDate: Date? = nil, groupStageAdditionalQualified: Int = 0, courtCount: Int = 2, prioritizeClubMembers: Bool = false, qualifiedPerGroupStage: Int = 1, teamsPerGroupStage: Int = 4, entryFee: Double? = nil, additionalEstimationDuration: Int = 0, isDeleted: Bool = false, publishTeams: Bool = false, publishSummons: Bool = false, publishGroupStages: Bool = false, publishBrackets: Bool = false, shouldVerifyBracket: Bool = false, shouldVerifyGroupStage: Bool = false, hideTeamsWeight: Bool = false, publishTournament: Bool = false, hidePointsEarned: Bool = false, publishRankings: Bool = false, loserBracketMode: LoserBracketMode = .automatic) { + internal init(event: String? = nil, name: String? = nil, startDate: Date = Date(), endDate: Date? = nil, creationDate: Date = Date(), isPrivate: Bool = false, groupStageFormat: MatchFormat? = nil, roundFormat: MatchFormat? = nil, loserRoundFormat: MatchFormat? = nil, groupStageSortMode: GroupStageOrderingMode, groupStageCount: Int = 4, rankSourceDate: Date? = nil, dayDuration: Int = 1, teamCount: Int = 24, teamSorting: TeamSortingType? = nil, federalCategory: TournamentCategory, federalLevelCategory: TournamentLevel, federalAgeCategory: FederalTournamentAge, closedRegistrationDate: Date? = nil, groupStageAdditionalQualified: Int = 0, courtCount: Int = 2, prioritizeClubMembers: Bool = false, qualifiedPerGroupStage: Int = 1, teamsPerGroupStage: Int = 4, entryFee: Double? = nil, additionalEstimationDuration: Int = 0, isDeleted: Bool = false, publishTeams: Bool = false, publishSummons: Bool = false, publishGroupStages: Bool = false, publishBrackets: Bool = false, shouldVerifyBracket: Bool = false, shouldVerifyGroupStage: Bool = false, hideTeamsWeight: Bool = false, publishTournament: Bool = false, hidePointsEarned: Bool = false, publishRankings: Bool = false, loserBracketMode: LoserBracketMode = .automatic, initialSeedRound: Int = 0, initialSeedCount: Int = 0) { self.event = event self.name = name self.startDate = startDate @@ -148,6 +153,9 @@ final class Tournament : ModelObject, Storable { self.hidePointsEarned = hidePointsEarned self.publishRankings = publishRankings self.loserBracketMode = loserBracketMode + self.initialSeedRound = initialSeedRound + self.initialSeedCount = initialSeedCount + } required init(from decoder: Decoder) throws { @@ -193,6 +201,8 @@ final class Tournament : ModelObject, Storable { hidePointsEarned = try container.decodeIfPresent(Bool.self, forKey: ._hidePointsEarned) ?? false publishRankings = try container.decodeIfPresent(Bool.self, forKey: ._publishRankings) ?? false loserBracketMode = try container.decodeIfPresent(LoserBracketMode.self, forKey: ._loserBracketMode) ?? .automatic + initialSeedRound = try container.decodeIfPresent(Int.self, forKey: ._initialSeedRound) ?? 0 + initialSeedCount = try container.decodeIfPresent(Int.self, forKey: ._initialSeedCount) ?? 0 } fileprivate static let _numberFormatter: NumberFormatter = NumberFormatter() @@ -279,6 +289,8 @@ final class Tournament : ModelObject, Storable { try container.encode(hidePointsEarned, forKey: ._hidePointsEarned) try container.encode(publishRankings, forKey: ._publishRankings) try container.encode(loserBracketMode, forKey: ._loserBracketMode) + try container.encode(initialSeedRound, forKey: ._initialSeedRound) + try container.encode(initialSeedCount, forKey: ._initialSeedCount) } fileprivate func _encodePayment(container: inout KeyedEncodingContainer) throws { @@ -673,11 +685,15 @@ defer { if availableSeeds().isEmpty == false && roundIndex >= lastSeedRound() { if availableSeedGroup == SeedInterval(first: 1, last: 2) { return availableSeedGroup } - let availableSeeds = seeds(inSeedGroup: availableSeedGroup) let availableSeedSpot = availableSeedSpot(inRoundIndex: roundIndex) let availableSeedOpponentSpot = availableSeedOpponentSpot(inRoundIndex: roundIndex) + if availableSeedGroup == SeedInterval(first: 3, last: 4), availableSeedSpot.count == 6 { + print("availableSeedGroup == SeedInterval(first: 3, last: 4)") + return availableSeedGroup + } + if availableSeeds.count == availableSeedSpot.count && availableSeedGroup.count == availableSeeds.count { return availableSeedGroup } else if availableSeeds.count == availableSeedOpponentSpot.count && availableSeedGroup.count == availableSeedOpponentSpot.count { @@ -711,22 +727,35 @@ defer { let availableSeedOpponentSpot = availableSeedOpponentSpot(inRoundIndex: roundIndex) let availableSeeds = seeds(inSeedGroup: seedGroup) - if availableSeeds.count <= availableSeedSpot.count { - let spots = availableSeedSpot.shuffled() - for (index, seed) in availableSeeds.enumerated() { - seed.setSeedPosition(inSpot: spots[index], slot: nil, opposingSeeding: false) - } - } else if (availableSeeds.count <= availableSeedOpponentSpot.count && availableSeeds.count <= self.availableSeeds().count) { - - let spots = availableSeedOpponentSpot.shuffled() - for (index, seed) in availableSeeds.enumerated() { - seed.setSeedPosition(inSpot: spots[index], slot: nil, opposingSeeding: true) + if seedGroup == SeedInterval(first: 3, last: 4) { + print("availableSeedGroup == SeedInterval(first: 3, last: 4)") + if availableSeedSpot.count == 6 { + var spots = [Match]() + spots.append(availableSeedSpot[1]) + spots.append(availableSeedSpot[4]) + spots = spots.shuffled() + for (index, seed) in availableSeeds.enumerated() { + seed.setSeedPosition(inSpot: spots[index], slot: nil, opposingSeeding: false) + } } - } else if let chunks = seedGroup.chunks() { - if let chunk = chunks.first(where: { seedInterval in - seedInterval.first >= self.seededTeams().count - }) { - setSeeds(inRoundIndex: roundIndex, inSeedGroup: chunk) + } else { + if availableSeeds.count <= availableSeedSpot.count { + let spots = availableSeedSpot.shuffled() + for (index, seed) in availableSeeds.enumerated() { + seed.setSeedPosition(inSpot: spots[index], slot: nil, opposingSeeding: false) + } + } else if (availableSeeds.count <= availableSeedOpponentSpot.count && availableSeeds.count <= self.availableSeeds().count) { + + let spots = availableSeedOpponentSpot.shuffled() + for (index, seed) in availableSeeds.enumerated() { + seed.setSeedPosition(inSpot: spots[index], slot: nil, opposingSeeding: true) + } + } else if let chunks = seedGroup.chunks() { + if let chunk = chunks.first(where: { seedInterval in + seedInterval.first >= self.seededTeams().count + }) { + setSeeds(inRoundIndex: roundIndex, inSeedGroup: chunk) + } } } } @@ -829,7 +858,7 @@ defer { let wcBracket = _teams.filter { $0.wildCardBracket }.sorted(using: _currentSelectionSorting, order: .ascending) let groupStageSpots: Int = self.groupStageSpots() - var bracketSeeds: Int = min(teamCount, _completeTeams.count) - groupStageSpots - wcBracket.count + var bracketSeeds: Int = min(teamCount, _teams.count) - groupStageSpots - wcBracket.count var groupStageTeamCount: Int = groupStageSpots - wcGroupStage.count if groupStageTeamCount < 0 { groupStageTeamCount = 0 } if bracketSeeds < 0 { bracketSeeds = 0 } diff --git a/PadelClub/Views/Calling/BracketCallingView.swift b/PadelClub/Views/Calling/BracketCallingView.swift index 9aa7ec9..2c20386 100644 --- a/PadelClub/Views/Calling/BracketCallingView.swift +++ b/PadelClub/Views/Calling/BracketCallingView.swift @@ -6,10 +6,11 @@ // import SwiftUI +import LeStorage struct BracketCallingView: View { + @EnvironmentObject var dataStore: DataStore @Environment(Tournament.self) var tournament: Tournament - @State private var displayByMatch: Bool = true @State private var initialSeedRound: Int = 0 @State private var initialSeedCount: Int = 0 let tournamentRounds: [Round] @@ -19,9 +20,18 @@ struct BracketCallingView: View { let rounds = tournament.rounds() self.tournamentRounds = rounds self.teams = tournament.availableSeeds() - let index = rounds.count - 1 - _initialSeedRound = .init(wrappedValue: index) - _initialSeedCount = .init(wrappedValue: RoundRule.numberOfMatches(forRoundIndex: index)) + if tournament.initialSeedRound == 0, rounds.count > 0 { + let index = rounds.count - 1 + _initialSeedRound = .init(wrappedValue: index) + _initialSeedCount = .init(wrappedValue: RoundRule.numberOfMatches(forRoundIndex: index)) + } else if tournament.initialSeedRound < rounds.count { + _initialSeedRound = .init(wrappedValue: tournament.initialSeedRound) + _initialSeedCount = .init(wrappedValue: tournament.initialSeedCount) + } else if rounds.count > 0 { + let index = rounds.count - 1 + _initialSeedRound = .init(wrappedValue: index) + _initialSeedCount = .init(wrappedValue: RoundRule.numberOfMatches(forRoundIndex: index)) + } } var initialRound: Round { @@ -115,10 +125,23 @@ struct BracketCallingView: View { } } } + .onDisappear(perform: { + tournament.initialSeedCount = initialSeedCount + tournament.initialSeedRound = initialSeedRound + _save() + }) .headerProminence(.increased) .navigationTitle("Pré-convocation") } + private func _save() { + do { + try dataStore.tournaments.addOrUpdate(instance: tournament) + } catch { + Logger.error(error) + } + } + @ViewBuilder private func _roundView(round: Round, seeds: [TeamRegistration]) -> some View { List { diff --git a/PadelClub/Views/Calling/TeamsCallingView.swift b/PadelClub/Views/Calling/TeamsCallingView.swift index 2c9117a..1760e99 100644 --- a/PadelClub/Views/Calling/TeamsCallingView.swift +++ b/PadelClub/Views/Calling/TeamsCallingView.swift @@ -25,7 +25,7 @@ struct TeamsCallingView: View { Section { Text(label) } footer: { - Text("Vous pouvez indiquer si une équipe vous a confirmé sa convocation en appuyant sur 􀍡") + Text("Vous pouvez indiquer si une équipe vous a confirmé sa convocation en appuyant sur ") + Text(Image(systemName: "ellipsis.circle")) } Section { diff --git a/PadelClub/Views/Cashier/Event/EventSettingsView.swift b/PadelClub/Views/Cashier/Event/EventSettingsView.swift index cad0f0a..4186a8b 100644 --- a/PadelClub/Views/Cashier/Event/EventSettingsView.swift +++ b/PadelClub/Views/Cashier/Event/EventSettingsView.swift @@ -105,7 +105,7 @@ struct EventSettingsView: View { Button("Valider") { textFieldIsFocus = false if eventName.trimmed.isEmpty == false { - event.name = eventName.trimmed + event.name = eventName.prefixTrimmed(200) } else { event.name = nil } diff --git a/PadelClub/Views/Club/CourtView.swift b/PadelClub/Views/Club/CourtView.swift index c4e89f8..6b37fc8 100644 --- a/PadelClub/Views/Club/CourtView.swift +++ b/PadelClub/Views/Club/CourtView.swift @@ -30,9 +30,11 @@ struct CourtView: View { .multilineTextAlignment(.trailing) .frame(maxWidth: .infinity) .onSubmit { - court.name = name - if name.isEmpty { + let courtName = name.prefixTrimmed(50) + if courtName.isEmpty { court.name = nil + } else { + court.name = courtName } do { try dataStore.courts.addOrUpdate(instance: court) diff --git a/PadelClub/Views/GroupStage/Components/GroupStageSettingsView.swift b/PadelClub/Views/GroupStage/Components/GroupStageSettingsView.swift index 84b529e..ad0d943 100644 --- a/PadelClub/Views/GroupStage/Components/GroupStageSettingsView.swift +++ b/PadelClub/Views/GroupStage/Components/GroupStageSettingsView.swift @@ -42,7 +42,7 @@ struct GroupStageSettingsView: View { .submitLabel(.done) .frame(maxWidth: .infinity) .onSubmit { - groupStageName = groupStageName.trimmed + groupStageName = groupStageName.prefixTrimmed(200) if groupStageName.isEmpty == false { groupStage.name = groupStageName _save() diff --git a/PadelClub/Views/Match/MatchDetailView.swift b/PadelClub/Views/Match/MatchDetailView.swift index 471f914..24f19ae 100644 --- a/PadelClub/Views/Match/MatchDetailView.swift +++ b/PadelClub/Views/Match/MatchDetailView.swift @@ -36,6 +36,7 @@ struct MatchDetailView: View { @State private var presentFollowUpMatch: Bool = false @State private var dismissWhenPresentFollowUpMatchIsDismissed: Bool = false @State private var presentRanking: Bool = false + @State private var confirmScoreEdition: Bool = false var tournamentStore: TournamentStore { return match.tournamentStore @@ -182,7 +183,8 @@ struct MatchDetailView: View { } }) .sheet(item: $scoreType, onDismiss: { - if match.hasEnded() { + if match.hasEnded(), confirmScoreEdition { + confirmScoreEdition = false if match.index == 0, match.isGroupStage() == false, match.roundObject?.parent == nil { presentRanking = true } else if match.isGroupStage(), match.currentTournament()?.hasEnded() == true { @@ -193,7 +195,7 @@ struct MatchDetailView: View { } }) { scoreType in let matchDescriptor = MatchDescriptor(match: match) - EditScoreView(matchDescriptor: matchDescriptor) + EditScoreView(matchDescriptor: matchDescriptor, confirmScoreEdition: $confirmScoreEdition) .tint(.master) // switch scoreType { diff --git a/PadelClub/Views/Player/PlayerDetailView.swift b/PadelClub/Views/Player/PlayerDetailView.swift index 046cdc1..45cb3e7 100644 --- a/PadelClub/Views/Player/PlayerDetailView.swift +++ b/PadelClub/Views/Player/PlayerDetailView.swift @@ -41,7 +41,7 @@ struct PlayerDetailView: View { .multilineTextAlignment(.trailing) .frame(maxWidth: .infinity) .onSubmit(of: .text) { - player.lastName = player.lastName.trimmedMultiline + player.lastName = player.lastName.prefixTrimmed(50) _save() } } label: { @@ -54,7 +54,7 @@ struct PlayerDetailView: View { .multilineTextAlignment(.trailing) .frame(maxWidth: .infinity) .onSubmit(of: .text) { - player.firstName = player.firstName.trimmedMultiline + player.firstName = player.firstName.prefixTrimmed(50) _save() } } label: { @@ -120,7 +120,7 @@ struct PlayerDetailView: View { .autocorrectionDisabled() .frame(maxWidth: .infinity) .onSubmit(of: .text) { - player.licenceId = licenceId + player.licenceId = licenceId.prefixTrimmed(50) _save() } } label: { @@ -128,7 +128,7 @@ struct PlayerDetailView: View { CopyPasteButtonView(pasteValue: player.licenceId) PasteButtonView(text: $licenceId) .onChange(of: licenceId) { - player.licenceId = licenceId + player.licenceId = licenceId.prefixTrimmed(50) _save() } } label: { @@ -145,7 +145,7 @@ struct PlayerDetailView: View { .autocorrectionDisabled() .frame(maxWidth: .infinity) .onSubmit(of: .text) { - player.phoneNumber = phoneNumber + player.phoneNumber = phoneNumber.prefixTrimmed(50) _save() } } label: { @@ -153,7 +153,7 @@ struct PlayerDetailView: View { CopyPasteButtonView(pasteValue: player.phoneNumber) PasteButtonView(text: $phoneNumber) .onChange(of: phoneNumber) { - player.phoneNumber = phoneNumber + player.phoneNumber = phoneNumber.prefixTrimmed(50) _save() } } label: { @@ -170,7 +170,7 @@ struct PlayerDetailView: View { .autocorrectionDisabled() .frame(maxWidth: .infinity) .onSubmit(of: .text) { - player.email = email + player.email = email.prefixTrimmed(50) _save() } } label: { @@ -178,7 +178,7 @@ struct PlayerDetailView: View { CopyPasteButtonView(pasteValue: player.email) PasteButtonView(text: $email) .onChange(of: email) { - player.email = email + player.email = email.prefixTrimmed(50) _save() } } label: { diff --git a/PadelClub/Views/Round/RoundView.swift b/PadelClub/Views/Round/RoundView.swift index 5ed57c3..7f93335 100644 --- a/PadelClub/Views/Round/RoundView.swift +++ b/PadelClub/Views/Round/RoundView.swift @@ -73,10 +73,11 @@ struct RoundView: View { if disabledMatchesCount > 0 { let bracketTip = BracketEditTip(nextRoundName: upperRound.round.nextRound()?.roundTitle()) TipView(bracketTip).tipStyle(tint: .green, asSection: true) - - if upperRound.round.hasStarted() == false { + + let leftToPlay = (RoundRule.numberOfMatches(forRoundIndex: upperRound.round.index) - disabledMatchesCount) + + if upperRound.round.hasStarted() == false, leftToPlay >= 0 { Section { - let leftToPlay = (RoundRule.numberOfMatches(forRoundIndex: upperRound.round.index) - disabledMatchesCount) LabeledContent { Text(leftToPlay.formatted()) } label: { @@ -128,7 +129,7 @@ struct RoundView: View { RowButtonView("Placer \(availableSeedGroup.localizedInterval())" + ((availableSeedGroup.isFixed() == false) ? " au hasard" : "")) { Task { tournament.setSeeds(inRoundIndex: upperRound.round.index, inSeedGroup: availableSeedGroup) - _save() + _save(seeds: availableSeeds) } } } footer: { @@ -166,7 +167,8 @@ struct RoundView: View { team.setSeedPosition(inSpot: matchSpot, slot: nil, opposingSeeding: true) } } - _save() + + _save(seeds: [team]) } } } label: { @@ -193,7 +195,8 @@ struct RoundView: View { results.forEach { drawResult in team.setSeedPosition(inSpot: seedSpaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: false) } - _save() + + _save(seeds: [team]) } } } label: { @@ -216,7 +219,7 @@ struct RoundView: View { results.forEach { drawResult in team.setSeedPosition(inSpot: spaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: true) } - _save() + _save(seeds: [team]) } } } label: { @@ -300,17 +303,15 @@ struct RoundView: View { } .fullScreenCover(isPresented: showVisualDrawView) { if let availableSeedGroup = selectedSeedGroup { - let seeds = tournament.seeds(inSeedGroup: availableSeedGroup) - let opposingSeeding = seedSpaceLeft.isEmpty ? true : false - let availableSeedSpot = opposingSeeding ? spaceLeft : seedSpaceLeft + let seeds = _seeds(availableSeedGroup: availableSeedGroup) + let availableSeedSpot = _availableSeedSpot(availableSeedGroup: availableSeedGroup) NavigationStack { SpinDrawView(drawees: seeds, segments: availableSeedSpot, autoMode: true) { draws in Task { draws.forEach { drawResult in seeds[drawResult.drawee].setSeedPosition(inSpot: availableSeedSpot[drawResult.drawIndex], slot: nil, opposingSeeding: opposingSeeding) } - - _save() + _save(seeds: seeds) } } } @@ -331,17 +332,45 @@ struct RoundView: View { } } + private func _seeds(availableSeedGroup: SeedInterval) -> [TeamRegistration] { + tournament.seeds(inSeedGroup: availableSeedGroup) + } + + var opposingSeeding: Bool { + seedSpaceLeft.isEmpty ? true : false + } + + private func _availableSeedSpot(availableSeedGroup: SeedInterval) -> [Match] { + let spots = opposingSeeding ? spaceLeft : seedSpaceLeft + if availableSeedGroup == SeedInterval(first: 3, last: 4), spots.count == 6 { + var array = [Match]() + array.append(spots[1]) + array.append(spots[4]) + return array + } else { + return spots + } + } + + + private func _save(seeds: [TeamRegistration]) { + do { + try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: seeds) + } catch { + Logger.error(error) + } + + if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty { + self.isEditingTournamentSeed.wrappedValue = false + } + + _refreshNames() + } + private func _save() { -// do { -// try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: tournament.unsortedTeams()) -// } catch { -// Logger.error(error) -// } -// if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty { self.isEditingTournamentSeed.wrappedValue = false } - _refreshNames() } diff --git a/PadelClub/Views/Score/EditScoreView.swift b/PadelClub/Views/Score/EditScoreView.swift index a080a03..d30f20e 100644 --- a/PadelClub/Views/Score/EditScoreView.swift +++ b/PadelClub/Views/Score/EditScoreView.swift @@ -44,12 +44,13 @@ struct EditScoreView: View { @EnvironmentObject var dataStore: DataStore @ObservedObject var matchDescriptor: MatchDescriptor + @Binding var confirmScoreEdition: Bool @Environment(\.dismiss) private var dismiss @State private var showSetInputView: Bool = true @State private var showTieBreakInputView: Bool = false - let colorTeamOne: Color = .mint - let colorTeamTwo: Color = .cyan + let colorTeamOne: Color = .teal + let colorTeamTwo: Color = .indigo func walkout(_ team: TeamPosition) { self.matchDescriptor.match?.setWalkOut(team) @@ -83,7 +84,7 @@ struct EditScoreView: View { .bold() } } - .listRowView(isActive: teamOneSetupIsActive, color: .master, hideColorVariation: false) + .listRowView(isActive: teamOneSetupIsActive, color: colorTeamOne, hideColorVariation: false) HStack { Spacer() VStack(alignment: .trailing) { @@ -94,7 +95,7 @@ struct EditScoreView: View { } } } - .listRowView(isActive: teamTwoSetupIsActive, color: .master, hideColorVariation: false, alignment: .trailing) + .listRowView(isActive: teamTwoSetupIsActive, color: colorTeamTwo, hideColorVariation: false, alignment: .trailing) } footer: { HStack { Menu { @@ -133,7 +134,7 @@ struct EditScoreView: View { matchDescriptor.setDescriptors = Array(matchDescriptor.setDescriptors[0...index]) } } - .tint(.master) + .tint(getColor()) } if matchDescriptor.hasEnded { @@ -171,6 +172,7 @@ struct EditScoreView: View { } func save() { + self.confirmScoreEdition = true if let match = matchDescriptor.match { do { try match.tournamentStore.matches.addOrUpdate(instance: match) diff --git a/PadelClub/Views/Team/CoachListView.swift b/PadelClub/Views/Team/CoachListView.swift index 0a4ca87..bce29b4 100644 --- a/PadelClub/Views/Team/CoachListView.swift +++ b/PadelClub/Views/Team/CoachListView.swift @@ -26,7 +26,7 @@ struct CoachListView: View { .frame(maxWidth: .infinity) .submitLabel(.done) .onSubmit(of: .text) { - let trimmed = coachNames.trimmed + let trimmed = coachNames.prefixTrimmed(200) if trimmed.isEmpty { team.comment = nil } else { diff --git a/PadelClub/Views/Team/EditingTeamView.swift b/PadelClub/Views/Team/EditingTeamView.swift index 9949e67..133ff49 100644 --- a/PadelClub/Views/Team/EditingTeamView.swift +++ b/PadelClub/Views/Team/EditingTeamView.swift @@ -151,7 +151,7 @@ struct EditingTeamView: View { .frame(maxWidth: .infinity) .submitLabel(.done) .onSubmit(of: .text) { - let trimmed = name.trimmedMultiline + let trimmed = name.prefixTrimmed(200) if trimmed.isEmpty { team.name = nil } else { diff --git a/PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift b/PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift index f7096d1..1d8efa3 100644 --- a/PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift +++ b/PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift @@ -145,7 +145,8 @@ struct TournamentGeneralSettingsView: View { Spacer() Button("Valider") { if focusedField == ._name { - if tournamentName.trimmed.isEmpty { + let tournamentName = tournamentName.prefixTrimmed(200) + if tournamentName.isEmpty { tournament.name = nil } else { tournament.name = tournamentName diff --git a/PadelClub/Views/Tournament/Screen/TournamentCallView.swift b/PadelClub/Views/Tournament/Screen/TournamentCallView.swift index fd0db9d..16a9af1 100644 --- a/PadelClub/Views/Tournament/Screen/TournamentCallView.swift +++ b/PadelClub/Views/Tournament/Screen/TournamentCallView.swift @@ -103,7 +103,7 @@ struct TournamentCallView: View { self._selectedDestination = State(wrappedValue: .seeds(tournament)) } } - if tournament.availableSeeds().isEmpty == false { + if tournament.availableSeeds().isEmpty == false, tournament.rounds().count > 0 { destinations.append(.brackets(tournament)) if seededTeams.isEmpty { self._selectedDestination = State(wrappedValue: .brackets(tournament)) diff --git a/PadelClubTests/ServerDataTests.swift b/PadelClubTests/ServerDataTests.swift index 3947937..f1a988e 100644 --- a/PadelClubTests/ServerDataTests.swift +++ b/PadelClubTests/ServerDataTests.swift @@ -99,7 +99,7 @@ final class ServerDataTests: XCTestCase { return } - let tournament = Tournament(event: eventId, name: "RG Homme", startDate: Date(), endDate: nil, creationDate: Date(), isPrivate: false, groupStageFormat: MatchFormat.megaTie, roundFormat: MatchFormat.nineGames, loserRoundFormat: MatchFormat.nineGamesDecisivePoint, groupStageSortMode: GroupStageOrderingMode.snake, groupStageCount: 2, rankSourceDate: Date(), dayDuration: 5, teamCount: 3, teamSorting: TeamSortingType.rank, federalCategory: TournamentCategory.mix, federalLevelCategory: TournamentLevel.p1000, federalAgeCategory: FederalTournamentAge.a45, closedRegistrationDate: Date(), groupStageAdditionalQualified: 4, courtCount: 9, prioritizeClubMembers: true, qualifiedPerGroupStage: 1, teamsPerGroupStage: 2, entryFee: 30.0, additionalEstimationDuration: 5, isDeleted: true, publishTeams: true, publishSummons: true, publishGroupStages: true, publishBrackets: true, shouldVerifyBracket: true, shouldVerifyGroupStage: true, hideTeamsWeight: true, publishTournament: true, hidePointsEarned: true, publishRankings: true, loserBracketMode: .manual) + let tournament = Tournament(event: eventId, name: "RG Homme", startDate: Date(), endDate: nil, creationDate: Date(), isPrivate: false, groupStageFormat: MatchFormat.megaTie, roundFormat: MatchFormat.nineGames, loserRoundFormat: MatchFormat.nineGamesDecisivePoint, groupStageSortMode: GroupStageOrderingMode.snake, groupStageCount: 2, rankSourceDate: Date(), dayDuration: 5, teamCount: 3, teamSorting: TeamSortingType.rank, federalCategory: TournamentCategory.mix, federalLevelCategory: TournamentLevel.p1000, federalAgeCategory: FederalTournamentAge.a45, closedRegistrationDate: Date(), groupStageAdditionalQualified: 4, courtCount: 9, prioritizeClubMembers: true, qualifiedPerGroupStage: 1, teamsPerGroupStage: 2, entryFee: 30.0, additionalEstimationDuration: 5, isDeleted: true, publishTeams: true, publishSummons: true, publishGroupStages: true, publishBrackets: true, shouldVerifyBracket: true, shouldVerifyGroupStage: true, hideTeamsWeight: true, publishTournament: true, hidePointsEarned: true, publishRankings: true, loserBracketMode: .manual, initialSeedRound: 8, initialSeedCount: 4) let t = try await StoreCenter.main.service().post(tournament) assert(t.event == tournament.event) @@ -140,6 +140,8 @@ final class ServerDataTests: XCTestCase { assert(t.hidePointsEarned == tournament.hidePointsEarned) assert(t.publishRankings == tournament.publishRankings) assert(t.loserBracketMode == tournament.loserBracketMode) + assert(t.initialSeedCount == tournament.initialSeedCount) + assert(t.initialSeedRound == tournament.initialSeedRound) } func testGroupStage() async throws {