sync2
Raz 1 year ago
parent 0352fffc4d
commit 4f3aec3e19
  1. 26
      PadelClub.xcodeproj/project.pbxproj
  2. 6
      PadelClub/Data/Tournament.swift
  3. 4
      PadelClub/Extensions/String+Extensions.swift
  4. 53
      PadelClub/Utils/FileImportManager.swift
  5. 6
      PadelClub/Utils/PadelRule.swift
  6. 2
      PadelClub/Utils/Tips.swift
  7. 4
      PadelClub/Views/Cashier/Event/EventSettingsView.swift
  8. 2
      PadelClub/Views/Cashier/Event/TournamentConfiguratorView.swift
  9. 1
      PadelClub/Views/GroupStage/Components/GroupStageSettingsView.swift
  10. 4
      PadelClub/Views/Team/EditingTeamView.swift
  11. 18
      PadelClub/Views/Tournament/FileImportView.swift
  12. 3
      PadelClub/Views/Tournament/Screen/AddTeamView.swift
  13. 17
      PadelClub/Views/Tournament/Screen/BroadcastView.swift
  14. 40
      PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift
  15. 17
      PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift
  16. 2
      PadelClub/Views/Tournament/Screen/TableStructureView.swift

@ -743,6 +743,7 @@
FFB1C98B2C10255100B154A7 /* TournamentBroadcastRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB1C98A2C10255100B154A7 /* TournamentBroadcastRowView.swift */; };
FFB9C8712BBADDE200A0EF4F /* Selectable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB9C8702BBADDE200A0EF4F /* Selectable.swift */; };
FFB9C8752BBADDF700A0EF4F /* SeedInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB9C8742BBADDF700A0EF4F /* SeedInterval.swift */; };
FFBA2D2D2CA2CE9E00D5BBDD /* CodingContainer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C33F752C9B1EC5006316DE /* CodingContainer+Extensions.swift */; };
FFBF065C2BBD2657009D6715 /* GroupStageTeamView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBF065B2BBD2657009D6715 /* GroupStageTeamView.swift */; };
FFBF065E2BBD8040009D6715 /* MatchListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBF065D2BBD8040009D6715 /* MatchListView.swift */; };
FFBF06602BBD9F6D009D6715 /* NavigationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBF065F2BBD9F6D009D6715 /* NavigationViewModel.swift */; };
@ -2671,6 +2672,7 @@
FF4CBFF82C996C0600151637 /* TabItemModifier.swift in Sources */,
FF4CBFF92C996C0600151637 /* DeferredViewModifier.swift in Sources */,
FF4CBFFA2C996C0600151637 /* TournamentScheduleView.swift in Sources */,
FFBA2D2D2CA2CE9E00D5BBDD /* CodingContainer+Extensions.swift in Sources */,
FF4CBFFB2C996C0600151637 /* MatchFormatStorageView.swift in Sources */,
FF4CBFFC2C996C0600151637 /* UmpireView.swift in Sources */,
FF4CBFFD2C996C0600151637 /* User.swift in Sources */,
@ -3132,7 +3134,7 @@
CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
@ -3155,7 +3157,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.12;
MARKETING_VERSION = 1.0.13;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -3176,7 +3178,7 @@
CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
DEVELOPMENT_TEAM = BQ3Y44M3Q6;
@ -3198,7 +3200,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.12;
MARKETING_VERSION = 1.0.13;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -3291,7 +3293,7 @@
CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
CURRENT_PROJECT_VERSION = 2;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
@ -3313,7 +3315,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.10;
MARKETING_VERSION = 1.0.13;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -3333,7 +3335,7 @@
CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
CURRENT_PROJECT_VERSION = 2;
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
DEVELOPMENT_TEAM = BQ3Y44M3Q6;
@ -3354,7 +3356,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.10;
MARKETING_VERSION = 1.0.13;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -3375,7 +3377,7 @@
CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
@ -3397,7 +3399,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.9;
MARKETING_VERSION = 1.0.13;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub.beta;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -3417,7 +3419,7 @@
CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
DEVELOPMENT_TEAM = BQ3Y44M3Q6;
@ -3438,7 +3440,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.9;
MARKETING_VERSION = 1.0.13;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub.beta;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

@ -1387,8 +1387,12 @@ defer {
}
func tournamentTitle(_ displayStyle: DisplayStyle = .wide) -> String {
if tournamentLevel == .unlisted, displayStyle == .title, let name {
if tournamentLevel == .unlisted, displayStyle == .title {
if let name {
return name
} else {
return tournamentLevel.localizedLabel(.title)
}
}
let title: String = [tournamentLevel.localizedLabel(displayStyle), tournamentCategory.localizedLabel(displayStyle), federalTournamentAge.localizedLabel(displayStyle)].joined(separator: " ")
if displayStyle == .wide, let name {

@ -13,6 +13,10 @@ extension String {
return (self.count > length) ? self.prefix(length) + trailing : self
}
func prefixTrimmed(_ length: Int) -> String {
String(trimmed.prefix(length))
}
var trimmed: String {
replaceCharactersFromSet(characterSet: .newlines, replacementString: " ").trimmingCharacters(in: .whitespacesAndNewlines)
}

@ -434,27 +434,29 @@ class FileImportManager {
let fetchRequest = ImportedPlayer.fetchRequest()
let federalContext = PersistenceController.shared.localContainer.viewContext
let results: [TeamHolder] = lines.chunked(into: 2).map { team in
let results: [TeamHolder] = lines.chunked(byParameterAt: 1).map { team in
var teamName: String? = nil
let players = team.map { player in
let data = player.components(separatedBy: separator)
let lastName : String = data[safe: 2]?.trimmed ?? ""
let firstName : String = data[safe: 3]?.trimmed ?? ""
let lastName : String = data[safe: 2]?.prefixTrimmed(50) ?? ""
let firstName : String = data[safe: 3]?.prefixTrimmed(50) ?? ""
let sex: PlayerRegistration.PlayerSexType = data[safe: 0] == "f" ? PlayerRegistration.PlayerSexType.female : PlayerRegistration.PlayerSexType.male
if data[safe: 1]?.trimmed != nil {
teamName = data[safe: 1]?.trimmed
}
let phoneNumber : String? = data[safe: 4]?.trimmed
let email : String? = data[safe: 5]?.trimmed
let phoneNumber : String? = data[safe: 4]?.trimmed.replaceCharactersFromSet(characterSet: .whitespacesAndNewlines).prefixTrimmed(15)
let email : String? = data[safe: 5]?.prefixTrimmed(50)
let rank : Int? = data[safe: 6]?.trimmed.toInt()
let licenceId : String? = data[safe: 7]?.trimmed
let club : String? = data[safe: 8]?.trimmed
let licenceId : String? = data[safe: 7]?.prefixTrimmed(50)
let club : String? = data[safe: 8]?.prefixTrimmed(200)
let predicate = NSPredicate(format: "firstName like[cd] %@ && lastName like[cd] %@", firstName, lastName)
fetchRequest.predicate = predicate
let found = try? federalContext.fetch(fetchRequest).first
if let found, autoSearch {
let player = PlayerRegistration(importedPlayer: found)
player.setComputedRank(in: tournament)
player.email = email
player.phoneNumber = phoneNumber
return player
} else {
let player = PlayerRegistration(firstName: firstName, lastName: lastName, licenceId: licenceId, rank: rank, sex: sex, clubName: club, phoneNumber: phoneNumber, email: email)
@ -465,8 +467,43 @@ class FileImportManager {
}
}
return TeamHolder(players: players, tournamentCategory: .men, tournamentAgeCategory: .senior, previousTeam: nil, name: teamName, tournament: tournament)
return TeamHolder(players: players, tournamentCategory: tournament.tournamentCategory, tournamentAgeCategory: tournament.federalTournamentAge, previousTeam: nil, name: teamName, tournament: tournament)
}
return results
}
}
extension Array where Element == String {
/// Groups the array of CSV lines based on the same value at the specified column index.
/// If no key is found, it defaults to chunking the array into groups of 2 lines.
/// - Parameter index: The index of the CSV column to group by.
/// - Returns: An array of arrays, where each inner array contains lines grouped by the CSV parameter or by default chunks of 2.
func chunked(byParameterAt index: Int) -> [[String]] {
var groups: [String: [String]] = [:]
for line in self {
let columns = line.split(separator: ";", omittingEmptySubsequences: false).map { String($0) }
if index < columns.count {
let key = columns[index]
if groups[key] == nil {
groups[key] = []
}
groups[key]?.append(line)
} else {
// Handle out-of-bounds by continuing
print("Warning: Index \(index) out of bounds for line: \(line)")
return [[]]
}
}
// If no valid groups found, chunk into groups of 2 lines
if groups.isEmpty {
return self.chunked(into: 2)
} else {
// Append groups by parameter value, converting groups.values into an array of arrays
return groups.map { $0.value }
}
}
}

@ -837,7 +837,7 @@ enum TournamentCategory: Int, Hashable, Codable, CaseIterable, Identifiable {
case .men:
switch displayStyle {
case .title:
return "DH"
return "Hommes"
case .wide:
return "Hommes"
case .short:
@ -846,7 +846,7 @@ enum TournamentCategory: Int, Hashable, Codable, CaseIterable, Identifiable {
case .women:
switch displayStyle {
case .title:
return "DD"
return "Dames"
case .wide:
return "Dames"
case .short:
@ -855,7 +855,7 @@ enum TournamentCategory: Int, Hashable, Codable, CaseIterable, Identifiable {
case .mix:
switch displayStyle {
case .title:
return "MX"
return "Mixte"
case .wide:
return "Mixte"
case .short:

@ -430,7 +430,7 @@ struct CreateAccountTip: Tip {
Action(id: ActionKey.createAccount.rawValue, title: "Créer votre compte")
//todo
//Action(id: ActionKey.learnMore.rawValue, title: "En savoir plus")
Action(id: ActionKey.accessPadelClubWebPage.rawValue, title: "Jeter un oeil au site Padel Club")
Action(id: ActionKey.accessPadelClubWebPage.rawValue, title: "Voir le site Padel Club")
}
enum ActionKey: String {

@ -46,12 +46,14 @@ struct EventSettingsView: View {
var body: some View {
Form {
Section {
TextField("Description de l'événement", text: $eventName, axis: .vertical)
TextField("Nom de l'événement", text: $eventName, axis: .vertical)
.lineLimit(2)
.keyboardType(.alphabet)
.multilineTextAlignment(.leading)
.frame(maxWidth: .infinity)
.focused($textFieldIsFocus)
} header: {
Text("Nom de l'événement")
} footer: {
if eventName.isEmpty == false {
FooterButtonView("effacer le nom") {

@ -40,7 +40,7 @@ struct TournamentConfigurationView: View {
}
Picker(selection: $tournament.federalCategory, label: Text("Catégorie")) {
ForEach(TournamentCategory.allCases) { type in
Text(type.localizedLabel(.wide)).tag(type)
Text(type.localizedLabel(.title)).tag(type)
}
}
Picker(selection: $tournament.federalAgeCategory, label: Text("Limite d'âge")) {

@ -37,6 +37,7 @@ struct GroupStageSettingsView: View {
Section {
TextField("Nom de la poule", text: $groupStageName)
.keyboardType(.alphabet)
.submitLabel(.done)
.frame(maxWidth: .infinity)
.onSubmit {
groupStageName = groupStageName.trimmed

@ -137,7 +137,9 @@ struct EditingTeamView: View {
})) {
Text("Forfait")
}
}
Section {
TextField("Nom de l'équipe", text: $name)
.autocorrectionDisabled()
.keyboardType(.alphabet)
@ -153,6 +155,8 @@ struct EditingTeamView: View {
_save()
}
} header: {
Text("Nom de l'équipe")
}
Section {

@ -85,11 +85,18 @@ struct FileImportView: View {
@State private var presentFormatHelperView: Bool = false
@State private var validatedTournamentIds: Set<String> = Set()
init(defaultFileProvider: FileImportManager.FileProvider = .frenchFederation) {
_fileProvider = .init(wrappedValue: defaultFileProvider)
}
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
private func filteredTeams(tournament: Tournament) -> [FileImportManager.TeamHolder] {
if tournament.isAnimation() {
return teams.sorted(by: \.weight)
}
return teams.filter { $0.tournamentCategory == tournament.tournamentCategory && $0.tournamentAgeCategory == tournament.federalTournamentAge }.sorted(by: \.weight)
}
@ -309,10 +316,14 @@ struct FileImportView: View {
LabeledContent {
Text(_filteredTeams.count.formatted())
} label: {
Text("Équipe\(_filteredTeams.count.pluralSuffix) \(tournament.tournamentCategory.importingRawValue) \(tournament.federalTournamentAge.importingRawValue) détectée\(_filteredTeams.count.pluralSuffix)")
if tournament.isAnimation() {
Text("Équipe\(_filteredTeams.count.pluralSuffix) détectée\(_filteredTeams.count.pluralSuffix)")
} else {
Text("Équipe\(_filteredTeams.count.pluralSuffix) \(tournament.tournamentCategory.importingRawValue) \(tournament.federalTournamentAge.importingRawValue.lowercased()) détectée\(_filteredTeams.count.pluralSuffix)")
}
}
} footer: {
if previousTeams.isEmpty == false {
if previousTeams.isEmpty == false, tournament.isAnimation() == false {
Text("La liste ci-dessous n'est qu'une indication d'évolution par rapport au seul poids d'équipe. Cela ne tient pas compte des dates d'inscriptions, WCs et autres éléments.").foregroundStyle(.logoRed)
}
}
@ -535,6 +546,9 @@ struct FileImportView: View {
Section {
HStack {
VStack(alignment: .leading) {
if let teamName = team.name {
Text(teamName).foregroundStyle(.secondary)
}
ForEach(team.players.sorted(by: \.computedRank)) {
Text($0.playerLabel())
}

@ -258,6 +258,7 @@ struct AddTeamView: View {
}
private func _isDuplicate() -> Bool {
if tournament.isAnimation() { return false }
let ids : [String?] = _currentSelectionIds()
if tournament.selectedSortedTeams().anySatisfy({ $0.containsExactlyPlayerLicenses(ids) }) {
return true
@ -391,7 +392,7 @@ struct AddTeamView: View {
ForEach(createdPlayerIds.sorted(), id: \.self) { id in
if let p = createdPlayers.first(where: { $0.id == id }) {
VStack(alignment: .leading, spacing: 0) {
if let player = unsortedPlayers.first(where: { $0.licenceId == p.licenceId }), editedTeam?.includes(player: player) == false {
if let player = unsortedPlayers.first(where: { ($0.licenceId == p.licenceId && $0.licenceId != nil) }), editedTeam?.includes(player: player) == true {
Text("Déjà inscrit !").foregroundStyle(.logoRed).bold()
}
PlayerView(player: p).tag(p.id)

@ -42,7 +42,7 @@ struct BroadcastView: View {
navigation.selectedTab = .umpire
}
RowButtonView("Jeter un oeil au site Padel Club") {
RowButtonView("Voir le site Padel Club") {
UIApplication.shared.open(URLs.main.url)
}
}
@ -104,12 +104,7 @@ struct BroadcastView: View {
Section {
Toggle(isOn: $tournament.isPrivate) {
Text("Tournoi privé")
if (tournament.isPrivate && Guard.main.purchasedTransactions.isEmpty) {
Text("Vous devez disposer d'une offre pour rendre publique ce tournoi.")
.foregroundStyle(.logoRed)
}
}
.disabled(_disablePrivateToggle())
} footer: {
let verb : String = tournament.isPrivate ? "est" : "sera"
let footerString = " Le tournoi \(verb) masqué sur le site [Padel Club](\(URLs.main.rawValue))"
@ -273,6 +268,7 @@ struct BroadcastView: View {
}
}
.toolbar(content: {
if StoreCenter.main.userId != nil, tournament.isPrivate == false, tournament.club() != nil {
ToolbarItem(placement: .topBarTrailing) {
Menu {
Section {
@ -301,6 +297,7 @@ struct BroadcastView: View {
Label("Partager les liens", systemImage: "square.and.arrow.up")
}
}
}
})
.headerProminence(.increased)
.navigationTitle("Publication")
@ -321,14 +318,6 @@ struct BroadcastView: View {
}
}
private func _disablePrivateToggle() -> Bool {
#if DEBUG
return false
#else
return (tournament.isPrivate && Guard.main.purchasedTransactions.isEmpty)
#endif
}
private func _save() {
do {
if [tournament.publishTeams, tournament.publishSummons, tournament.publishBrackets, tournament.publishGroupStages].anySatisfy({ $0 == true }) {

@ -28,6 +28,26 @@ struct TournamentGeneralSettingsView: View {
Section {
TournamentDatePickerView()
TournamentDurationManagerView()
LabeledContent {
TextField(tournament.isFree() ? "Gratuite" : "Inscription", value: $entryFee, format: .currency(code: Locale.current.currency?.identifier ?? "EUR"))
.keyboardType(.decimalPad)
.multilineTextAlignment(.trailing)
.frame(maxWidth: .infinity)
.focused($focusedField, equals: ._entryFee)
} label: {
Text("Inscription")
}
}
Section {
TextField("Nom du tournoi", text: $tournamentName, axis: .vertical)
.lineLimit(2)
.frame(maxWidth: .infinity)
.keyboardType(.alphabet)
.focused($focusedField, equals: ._name)
} header: {
Text("Nom du tournoi")
}
Section {
@ -70,26 +90,6 @@ struct TournamentGeneralSettingsView: View {
Text(tournament.loserBracketMode.localizedLoserBracketModeDescription())
}
}
Section {
LabeledContent {
TextField(tournament.isFree() ? "Gratuite" : "Inscription", value: $entryFee, format: .currency(code: Locale.current.currency?.identifier ?? "EUR"))
.keyboardType(.decimalPad)
.multilineTextAlignment(.trailing)
.frame(maxWidth: .infinity)
.focused($focusedField, equals: ._entryFee)
} label: {
Text("Inscription")
}
}
Section {
TextField("Nom du tournoi", text: $tournamentName, axis: .vertical)
.lineLimit(2)
.frame(maxWidth: .infinity)
.keyboardType(.alphabet)
.focused($focusedField, equals: ._name)
}
}
.toolbarBackground(.visible, for: .navigationBar)
.toolbar {

@ -231,7 +231,7 @@ struct InscriptionManagerView: View {
_setHash()
}) {
NavigationStack {
FileImportView()
FileImportView(defaultFileProvider: tournament.isAnimation() ? .custom : .frenchFederation)
}
.tint(.master)
}
@ -308,6 +308,7 @@ struct InscriptionManagerView: View {
.symbolVariant(filterMode == .all ? .none : .fill)
}
Menu {
if tournament.isAnimation() == false {
if tournament.inscriptionClosed() == false {
Menu {
_sortingTypePickerView()
@ -348,6 +349,13 @@ struct InscriptionManagerView: View {
Label("Ré-ouvrir", systemImage: "lock.open")
}
}
} else {
Button {
presentImportView = true
} label: {
Label("Importer un fichier", systemImage: "square.and.arrow.down")
}
}
} label: {
if tournament.inscriptionClosed() == false {
LabelOptions()
@ -438,9 +446,12 @@ struct InscriptionManagerView: View {
if presentSearch == false {
_informationView()
if tournament.isAnimation() == false {
_rankHandlerView()
_relatedTips()
}
}
let teams = searchField.isEmpty ? filteredTeams : filteredTeams.filter({ $0.contains(searchField.canonicalVersion) })
@ -650,7 +661,7 @@ struct InscriptionManagerView: View {
.listRowSeparator(.hidden)
let registrationIssues = tournament.registrationIssues()
if registrationIssues > 0 {
if tournament.isAnimation() == false, registrationIssues > 0 {
NavigationLink {
InscriptionInfoView()
.environment(tournament)
@ -660,7 +671,7 @@ struct InscriptionManagerView: View {
.foregroundStyle(.logoRed)
.fontWeight(.bold)
} label: {
Text("Problèmes détéctés")
Text("Problèmes détectés")
}
}
}

@ -74,7 +74,7 @@ struct TableStructureView: View {
}
LabeledContent {
StepperView(count: $qualifiedPerGroupStage, minimum: 1, maximum: (teamsPerGroupStage-1))
StepperView(count: $qualifiedPerGroupStage, minimum: 0, maximum: (teamsPerGroupStage-1))
} label: {
Text("Qualifiés par poule")
}

Loading…
Cancel
Save