From 4f3aec3e19340046a1661827813aa9e573882c43 Mon Sep 17 00:00:00 2001 From: Raz Date: Tue, 24 Sep 2024 15:56:33 +0200 Subject: [PATCH] v1.0.13 b3 --- PadelClub.xcodeproj/project.pbxproj | 26 +++--- PadelClub/Data/Tournament.swift | 8 +- PadelClub/Extensions/String+Extensions.swift | 4 + PadelClub/Utils/FileImportManager.swift | 53 +++++++++-- PadelClub/Utils/PadelRule.swift | 6 +- PadelClub/Utils/Tips.swift | 2 +- .../Cashier/Event/EventSettingsView.swift | 4 +- .../Event/TournamentConfiguratorView.swift | 2 +- .../Components/GroupStageSettingsView.swift | 1 + PadelClub/Views/Team/EditingTeamView.swift | 6 +- .../Views/Tournament/FileImportView.swift | 18 +++- .../Views/Tournament/Screen/AddTeamView.swift | 3 +- .../Tournament/Screen/BroadcastView.swift | 65 ++++++-------- .../TournamentGeneralSettingsView.swift | 40 ++++----- .../Screen/InscriptionManagerView.swift | 89 +++++++++++-------- .../Screen/TableStructureView.swift | 2 +- 16 files changed, 199 insertions(+), 130 deletions(-) diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index bc4d6c4..4ee6389 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -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 = ""; diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index cab2239..f7a6da1 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -1387,8 +1387,12 @@ defer { } func tournamentTitle(_ displayStyle: DisplayStyle = .wide) -> String { - if tournamentLevel == .unlisted, displayStyle == .title, let name { - return 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 { diff --git a/PadelClub/Extensions/String+Extensions.swift b/PadelClub/Extensions/String+Extensions.swift index 98567e7..ee29135 100644 --- a/PadelClub/Extensions/String+Extensions.swift +++ b/PadelClub/Extensions/String+Extensions.swift @@ -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) } diff --git a/PadelClub/Utils/FileImportManager.swift b/PadelClub/Utils/FileImportManager.swift index 7ee5ced..67f4fb2 100644 --- a/PadelClub/Utils/FileImportManager.swift +++ b/PadelClub/Utils/FileImportManager.swift @@ -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 } + } + } +} + diff --git a/PadelClub/Utils/PadelRule.swift b/PadelClub/Utils/PadelRule.swift index 7e6f922..8a069d4 100644 --- a/PadelClub/Utils/PadelRule.swift +++ b/PadelClub/Utils/PadelRule.swift @@ -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: diff --git a/PadelClub/Utils/Tips.swift b/PadelClub/Utils/Tips.swift index ae4c3c8..1366b39 100644 --- a/PadelClub/Utils/Tips.swift +++ b/PadelClub/Utils/Tips.swift @@ -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 { diff --git a/PadelClub/Views/Cashier/Event/EventSettingsView.swift b/PadelClub/Views/Cashier/Event/EventSettingsView.swift index 58b5428..d2f7d9c 100644 --- a/PadelClub/Views/Cashier/Event/EventSettingsView.swift +++ b/PadelClub/Views/Cashier/Event/EventSettingsView.swift @@ -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") { diff --git a/PadelClub/Views/Cashier/Event/TournamentConfiguratorView.swift b/PadelClub/Views/Cashier/Event/TournamentConfiguratorView.swift index dfffa60..65ecfc3 100644 --- a/PadelClub/Views/Cashier/Event/TournamentConfiguratorView.swift +++ b/PadelClub/Views/Cashier/Event/TournamentConfiguratorView.swift @@ -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")) { diff --git a/PadelClub/Views/GroupStage/Components/GroupStageSettingsView.swift b/PadelClub/Views/GroupStage/Components/GroupStageSettingsView.swift index 948dfa6..6713281 100644 --- a/PadelClub/Views/GroupStage/Components/GroupStageSettingsView.swift +++ b/PadelClub/Views/GroupStage/Components/GroupStageSettingsView.swift @@ -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 diff --git a/PadelClub/Views/Team/EditingTeamView.swift b/PadelClub/Views/Team/EditingTeamView.swift index 7e5f4be..782e996 100644 --- a/PadelClub/Views/Team/EditingTeamView.swift +++ b/PadelClub/Views/Team/EditingTeamView.swift @@ -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 { diff --git a/PadelClub/Views/Tournament/FileImportView.swift b/PadelClub/Views/Tournament/FileImportView.swift index c6644ff..e9ef5d5 100644 --- a/PadelClub/Views/Tournament/FileImportView.swift +++ b/PadelClub/Views/Tournament/FileImportView.swift @@ -85,11 +85,18 @@ struct FileImportView: View { @State private var presentFormatHelperView: Bool = false @State private var validatedTournamentIds: Set = 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()) } diff --git a/PadelClub/Views/Tournament/Screen/AddTeamView.swift b/PadelClub/Views/Tournament/Screen/AddTeamView.swift index cd0f484..005d7e1 100644 --- a/PadelClub/Views/Tournament/Screen/AddTeamView.swift +++ b/PadelClub/Views/Tournament/Screen/AddTeamView.swift @@ -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) diff --git a/PadelClub/Views/Tournament/Screen/BroadcastView.swift b/PadelClub/Views/Tournament/Screen/BroadcastView.swift index 661f69e..2ded795 100644 --- a/PadelClub/Views/Tournament/Screen/BroadcastView.swift +++ b/PadelClub/Views/Tournament/Screen/BroadcastView.swift @@ -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,32 +268,34 @@ struct BroadcastView: View { } } .toolbar(content: { - ToolbarItem(placement: .topBarTrailing) { - Menu { - Section { - let links : [PageLink] = [.teams, .summons, .groupStages, .matches, .rankings, .broadcast, .clubBroadcast] - Picker(selection: $pageLink) { - ForEach(links) { pageLink in - Text(pageLink.localizedLabel()).tag(pageLink) + if StoreCenter.main.userId != nil, tournament.isPrivate == false, tournament.club() != nil { + ToolbarItem(placement: .topBarTrailing) { + Menu { + Section { + let links : [PageLink] = [.teams, .summons, .groupStages, .matches, .rankings, .broadcast, .clubBroadcast] + Picker(selection: $pageLink) { + ForEach(links) { pageLink in + Text(pageLink.localizedLabel()).tag(pageLink) + } + } label: { + Text("Choisir la page à partager") } - } label: { - Text("Choisir la page à partager") + .pickerStyle(.menu) + actionForURL(title: "Partager la page '" + pageLink.localizedLabel() + "'", url: tournament.shareURL(pageLink)) + } header: { + Text("Lien du tournoi à partager") } - .pickerStyle(.menu) - actionForURL(title: "Partager la page '" + pageLink.localizedLabel() + "'", url: tournament.shareURL(pageLink)) - } header: { - Text("Lien du tournoi à partager") - } - - Section { - let club = tournament.club() - actionForURL(title: (club == nil) ? "Aucun club indiqué pour ce tournoi" : club!.clubTitle(), description: "Page du club", url: club?.shareURL()) - actionForURL(title: "Padel Club", url: URLs.main.url) - } header: { - Text("Autres liens") + + Section { + let club = tournament.club() + actionForURL(title: (club == nil) ? "Aucun club indiqué pour ce tournoi" : club!.clubTitle(), description: "Page du club", url: club?.shareURL()) + actionForURL(title: "Padel Club", url: URLs.main.url) + } header: { + Text("Autres liens") + } + } label: { + Label("Partager les liens", systemImage: "square.and.arrow.up") } - } label: { - Label("Partager les liens", systemImage: "square.and.arrow.up") } } }) @@ -320,15 +317,7 @@ struct BroadcastView: View { _save() } } - - 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 }) { diff --git a/PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift b/PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift index 35afb65..49de144 100644 --- a/PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift +++ b/PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift @@ -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 { diff --git a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift index 353fd7e..16ddaf8 100644 --- a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift +++ b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift @@ -231,7 +231,7 @@ struct InscriptionManagerView: View { _setHash() }) { NavigationStack { - FileImportView() + FileImportView(defaultFileProvider: tournament.isAnimation() ? .custom : .frenchFederation) } .tint(.master) } @@ -308,44 +308,52 @@ struct InscriptionManagerView: View { .symbolVariant(filterMode == .all ? .none : .fill) } Menu { - if tournament.inscriptionClosed() == false { - Menu { - _sortingTypePickerView() - } label: { - Text("Méthode de sélection") - Text(tournament.teamSorting.localizedLabel()) - } - Divider() - rankingDateSourcePickerView(showDateInLabel: true) - - Divider() - Button { - tournament.lockRegistration() - _save() - } label: { - Label("Clôturer", systemImage: "lock") - } - Divider() - _sharingTeamsMenuView() - Button { - presentImportView = true - } label: { - Label("Importer beach-padel", systemImage: "square.and.arrow.down") - } - Link(destination: URLs.beachPadel.url) { - Label("beach-padel.app.fft.fr", systemImage: "safari") + if tournament.isAnimation() == false { + if tournament.inscriptionClosed() == false { + Menu { + _sortingTypePickerView() + } label: { + Text("Méthode de sélection") + Text(tournament.teamSorting.localizedLabel()) + } + Divider() + rankingDateSourcePickerView(showDateInLabel: true) + + Divider() + Button { + tournament.lockRegistration() + _save() + } label: { + Label("Clôturer", systemImage: "lock") + } + Divider() + _sharingTeamsMenuView() + Button { + presentImportView = true + } label: { + Label("Importer beach-padel", systemImage: "square.and.arrow.down") + } + Link(destination: URLs.beachPadel.url) { + Label("beach-padel.app.fft.fr", systemImage: "safari") + } + } else { + + _sharingTeamsMenuView() + + Divider() + + Button { + tournament.unlockRegistration() + _save() + } label: { + Label("Ré-ouvrir", systemImage: "lock.open") + } } } else { - - _sharingTeamsMenuView() - - Divider() - Button { - tournament.unlockRegistration() - _save() + presentImportView = true } label: { - Label("Ré-ouvrir", systemImage: "lock.open") + Label("Importer un fichier", systemImage: "square.and.arrow.down") } } } label: { @@ -438,8 +446,11 @@ struct InscriptionManagerView: View { if presentSearch == false { _informationView() - _rankHandlerView() - _relatedTips() + + 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") } } } diff --git a/PadelClub/Views/Tournament/Screen/TableStructureView.swift b/PadelClub/Views/Tournament/Screen/TableStructureView.swift index 6ca1e6c..460fd28 100644 --- a/PadelClub/Views/Tournament/Screen/TableStructureView.swift +++ b/PadelClub/Views/Tournament/Screen/TableStructureView.swift @@ -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") }