fix issue with team selection

enhance visibility in score editing
add the seed 3/4 specific management in 1/8e
add new fields
limit all text input to suit the server side rules
paca_championship
Raz 1 year ago
parent f174ccfe57
commit 87b46d7ccb
  1. 28
      PadelClub/Data/PlayerRegistration.swift
  2. 65
      PadelClub/Data/Tournament.swift
  3. 31
      PadelClub/Views/Calling/BracketCallingView.swift
  4. 2
      PadelClub/Views/Calling/TeamsCallingView.swift
  5. 2
      PadelClub/Views/Cashier/Event/EventSettingsView.swift
  6. 6
      PadelClub/Views/Club/CourtView.swift
  7. 2
      PadelClub/Views/GroupStage/Components/GroupStageSettingsView.swift
  8. 6
      PadelClub/Views/Match/MatchDetailView.swift
  9. 16
      PadelClub/Views/Player/PlayerDetailView.swift
  10. 67
      PadelClub/Views/Round/RoundView.swift
  11. 12
      PadelClub/Views/Score/EditScoreView.swift
  12. 2
      PadelClub/Views/Team/CoachListView.swift
  13. 2
      PadelClub/Views/Team/EditingTeamView.swift
  14. 3
      PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift
  15. 2
      PadelClub/Views/Tournament/Screen/TournamentCallView.swift
  16. 4
      PadelClubTests/ServerDataTests.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

@ -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<CodingKeys>) 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 }

@ -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 {

@ -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 {

@ -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
}

@ -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)

@ -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()

@ -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 {

@ -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: {

@ -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()
}

@ -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)

@ -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 {

@ -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 {

@ -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

@ -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))

@ -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 {

Loading…
Cancel
Save