From 901cd4e6724564fdcc93fe9a00077fed2f752447 Mon Sep 17 00:00:00 2001 From: Raz Date: Mon, 28 Apr 2025 09:21:42 +0200 Subject: [PATCH] small fixes add deadlines access --- PadelClub/Data/Tournament.swift | 17 +++-- PadelClub/Utils/PadelRule.swift | 66 ++++++++++++++++--- .../ViewModel/FederalDataViewModel.swift | 2 +- .../Event/TournamentConfiguratorView.swift | 2 +- .../Agenda/TournamentLookUpView.swift | 4 +- .../Player/Components/PlayerPopoverView.swift | 4 +- .../Views/Shared/TournamentFilterView.swift | 2 +- .../Views/Tournament/Screen/AddTeamView.swift | 6 ++ .../TournamentGeneralSettingsView.swift | 8 +++ .../TournamentLevelPickerView.swift | 2 +- .../Shared/TournamentCellView.swift | 15 +++-- .../Views/Tournament/TournamentView.swift | 22 +++++-- 12 files changed, 118 insertions(+), 32 deletions(-) diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index 6c7abc1..9c32551 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -1304,9 +1304,9 @@ defer { } } let displayStyleCategory = hideSenior ? .short : displayStyle - var levelCategory = [tournamentLevel.localizedLevelLabel(displayStyle), tournamentCategory.localizedLabel(displayStyle)] + var levelCategory = [tournamentLevel.localizedLevelLabel(displayStyle), tournamentCategory.localizedCategoryLabel(displayStyle, ageCategory: federalAgeCategory)] if displayStyle == .short { - levelCategory = [tournamentLevel.localizedLevelLabel(displayStyle) + tournamentCategory.localizedLabel(displayStyle)] + levelCategory = [tournamentLevel.localizedLevelLabel(displayStyle) + tournamentCategory.localizedCategoryLabel(displayStyle, ageCategory: federalAgeCategory)] } let array = levelCategory + [federalTournamentAge.localizedFederalAgeLabel(displayStyleCategory)] let title: String = array.filter({ $0.isEmpty == false }).joined(separator: " ") @@ -1322,7 +1322,7 @@ defer { case .unlisted, .championship: return tournamentLevel.localizedLevelLabel(.short) default: - return tournamentLevel.localizedLevelLabel(.short) + tournamentCategory.localizedLabel(.short) + return tournamentLevel.localizedLevelLabel(.short) + tournamentCategory.localizedCategoryLabel(.short, ageCategory: federalAgeCategory) } } @@ -2370,6 +2370,15 @@ defer { // MARK: - Status func shouldTournamentBeOver() async -> Bool { + if hasEnded() { + return true + } + if hasStarted() == false { + return false + } + if hasStarted(), self.startDate.timeIntervalSinceNow > -3600*24 { + return false + } if tournamentStore?.store.fileCollectionsAllLoaded() == false { return false } @@ -2569,7 +2578,7 @@ extension Tournament: FederalTournamentHolder { func subtitleLabel(forBuild build: any TournamentBuildHolder) -> String { if isAnimation() { if displayAgeAndCategory(forBuild: build) == false { - return [build.category.localizedLabel(), build.age.localizedFederalAgeLabel()].filter({ $0.isEmpty == false }).joined(separator: " ") + return [build.category.localizedCategoryLabel(ageCategory: build.age), build.age.localizedFederalAgeLabel()].filter({ $0.isEmpty == false }).joined(separator: " ") } else if name != nil { return build.level.localizedLevelLabel(.title) } else { diff --git a/PadelClub/Utils/PadelRule.swift b/PadelClub/Utils/PadelRule.swift index 3a2a534..55b3d08 100644 --- a/PadelClub/Utils/PadelRule.swift +++ b/PadelClub/Utils/PadelRule.swift @@ -48,7 +48,7 @@ struct TournamentBuild: TournamentBuildHolder, Hashable, Codable, Identifiable { } var identifier: String { - level.localizedLevelLabel()+":"+category.localizedLabel()+":"+age.localizedFederalAgeLabel() + level.localizedLevelLabel()+":"+category.localizedCategoryLabel(ageCategory: age)+":"+age.localizedFederalAgeLabel() } func computedLabel(_ displayStyle: DisplayStyle = .wide) -> String { @@ -57,11 +57,11 @@ struct TournamentBuild: TournamentBuildHolder, Hashable, Codable, Identifiable { } func localizedLabel(_ displayStyle: DisplayStyle = .wide) -> String { - level.localizedLevelLabel(displayStyle) + " " + category.localizedLabel(displayStyle) + level.localizedLevelLabel(displayStyle) + " " + category.localizedCategoryLabel(displayStyle, ageCategory: age) } func localizedTitle(_ displayStyle: DisplayStyle = .wide) -> String { - level.localizedLevelLabel(displayStyle) + " " + category.localizedLabel(displayStyle) + level.localizedLevelLabel(displayStyle) + " " + category.localizedCategoryLabel(displayStyle, ageCategory: age) } func localizedAge(_ displayStyle: DisplayStyle = .wide) -> String { @@ -257,13 +257,13 @@ enum FederalTournamentAge: Int, Hashable, Codable, CaseIterable, Identifiable { case .unlisted: return displayStyle == .title ? "Aucune" : "" case .a11_12: - return "11/12 ans" + return "U12" case .a13_14: - return "13/14 ans" + return "U14" case .a15_16: - return "15/16 ans" + return "U16" case .a17_18: - return "17/18 ans" + return "U18" case .senior: return displayStyle == .short ? "" : "Senior" case .a45: @@ -298,6 +298,27 @@ enum FederalTournamentAge: Int, Hashable, Codable, CaseIterable, Identifiable { return age >= 55 } } + + func isChildCategory() -> Bool { + switch self { + case .unlisted: + return false + case .a11_12: + return true + case .a13_14: + return true + case .a15_16: + return true + case .a17_18: + return true + case .senior: + return false + case .a45: + return false + case .a55: + return false + } + } } enum TournamentLevel: Int, Hashable, Codable, CaseIterable, Identifiable { @@ -395,6 +416,15 @@ enum TournamentLevel: Int, Hashable, Codable, CaseIterable, Identifiable { } } + func haveDeadlines() -> Bool { + switch self { + case .p500, .p1000, .p1500, .p2000: + return true + default: + return false + } + } + func minimumPlayerRank(category: TournamentCategory, ageCategory: FederalTournamentAge) -> Int { switch self { case .p25: @@ -909,26 +939,46 @@ enum TournamentCategory: Int, Hashable, Codable, CaseIterable, Identifiable { } } - func localizedLabel(_ displayStyle: DisplayStyle = .wide) -> String { + func localizedCategoryLabel(_ displayStyle: DisplayStyle = .wide, ageCategory: FederalTournamentAge? = nil) -> String { switch self { case .unlisted: return displayStyle == .title ? "Aucune" : "" case .men: switch displayStyle { case .title: + if ageCategory?.isChildCategory() == true { + return "Garçons" + } return "Hommes" case .wide: + if ageCategory?.isChildCategory() == true { + return "Garçons" + } return "Hommes" case .short: + if ageCategory?.isChildCategory() == true { + return "G" + } + return "H" } case .women: switch displayStyle { case .title: + if ageCategory?.isChildCategory() == true { + return "Filles" + } return "Dames" case .wide: + if ageCategory?.isChildCategory() == true { + return "Filles" + } return "Dames" case .short: + if ageCategory?.isChildCategory() == true { + return "F" + } + return "D" } case .mix: diff --git a/PadelClub/ViewModel/FederalDataViewModel.swift b/PadelClub/ViewModel/FederalDataViewModel.swift index 1394587..ad8a560 100644 --- a/PadelClub/ViewModel/FederalDataViewModel.swift +++ b/PadelClub/ViewModel/FederalDataViewModel.swift @@ -27,7 +27,7 @@ class FederalDataViewModel { func filterStatus() -> String { var labels: [String] = [] labels.append(contentsOf: levels.map { $0.localizedLevelLabel() }.formatList()) - labels.append(contentsOf: categories.map { $0.localizedLabel() }.formatList()) + labels.append(contentsOf: categories.map { $0.localizedCategoryLabel() }.formatList()) labels.append(contentsOf: ageCategories.map { $0.localizedFederalAgeLabel() }.formatList()) let clubNames = selectedClubs.compactMap { codeClub in let club: Club? = DataStore.shared.clubs.first(where: { $0.code == codeClub }) diff --git a/PadelClub/Views/Cashier/Event/TournamentConfiguratorView.swift b/PadelClub/Views/Cashier/Event/TournamentConfiguratorView.swift index 30ec0f6..faa6b7d 100644 --- a/PadelClub/Views/Cashier/Event/TournamentConfiguratorView.swift +++ b/PadelClub/Views/Cashier/Event/TournamentConfiguratorView.swift @@ -41,7 +41,7 @@ struct TournamentConfigurationView: View { } Picker(selection: $tournament.federalCategory, label: Text("Catégorie")) { ForEach(TournamentCategory.allCases) { type in - Text(type.localizedLabel(.title)).tag(type) + Text(type.localizedCategoryLabel(.title, ageCategory: tournament.federalAgeCategory)).tag(type) } } Picker(selection: $tournament.federalAgeCategory, label: Text("Limite d'âge")) { diff --git a/PadelClub/Views/Navigation/Agenda/TournamentLookUpView.swift b/PadelClub/Views/Navigation/Agenda/TournamentLookUpView.swift index 8ebd7ee..699f6f1 100644 --- a/PadelClub/Views/Navigation/Agenda/TournamentLookUpView.swift +++ b/PadelClub/Views/Navigation/Agenda/TournamentLookUpView.swift @@ -371,7 +371,7 @@ struct TournamentLookUpView: View { NavigationLink { List([TournamentCategory.men, TournamentCategory.women, TournamentCategory.mix], selection: $appSettings.tournamentCategories) { type in - Text(type.localizedLabel()) + Text(type.localizedCategoryLabel()) } .navigationTitle("Catégories") .environment(\.editMode, Binding.constant(EditMode.active)) @@ -456,7 +456,7 @@ struct TournamentLookUpView: View { if dataStore.appSettings.tournamentCategories.isEmpty || dataStore.appSettings.tournamentCategories.count == TournamentCategory.allCases.count { Text("Toutes les catégories") } else { - Text(categories.map({ $0.localizedLabel() }).joined(separator: ", ")) + Text(categories.map({ $0.localizedCategoryLabel() }).joined(separator: ", ")) } } diff --git a/PadelClub/Views/Player/Components/PlayerPopoverView.swift b/PadelClub/Views/Player/Components/PlayerPopoverView.swift index f51de04..ccad7b1 100644 --- a/PadelClub/Views/Player/Components/PlayerPopoverView.swift +++ b/PadelClub/Views/Player/Components/PlayerPopoverView.swift @@ -125,11 +125,11 @@ struct PlayerPopoverView: View { TextField("Licence", text: $license) .focused($licenseIsFocused) .textInputAutocapitalization(.never) - .keyboardType(.numberPad) + .keyboardType(.alphabet) .submitLabel(.next) .onSubmit { license = license.trimmedMultiline - if requiredField.contains(.license) { + if license.isEmpty == false { if license.isLicenseNumber { amountIsFocused = true } else { diff --git a/PadelClub/Views/Shared/TournamentFilterView.swift b/PadelClub/Views/Shared/TournamentFilterView.swift index 3686aff..c926192 100644 --- a/PadelClub/Views/Shared/TournamentFilterView.swift +++ b/PadelClub/Views/Shared/TournamentFilterView.swift @@ -85,7 +85,7 @@ struct TournamentFilterView: View { } } } label: { - Text(category.localizedLabel(.wide)) + Text(category.localizedCategoryLabel(.wide)) } } } header: { diff --git a/PadelClub/Views/Tournament/Screen/AddTeamView.swift b/PadelClub/Views/Tournament/Screen/AddTeamView.swift index e91d8f4..40c0cff 100644 --- a/PadelClub/Views/Tournament/Screen/AddTeamView.swift +++ b/PadelClub/Views/Tournament/Screen/AddTeamView.swift @@ -179,6 +179,12 @@ struct AddTeamView: View { createdPlayerIds.insert(newPlayer.id) } } contentUnavailableAction: { searchViewModel in + searchViewModel.selectedPlayers.forEach { player in + let newPlayer = PlayerRegistration(importedPlayer: player) + newPlayer.setComputedRank(in: tournament) + createdPlayers.insert(newPlayer) + createdPlayerIds.insert(newPlayer.id) + } presentPlayerSearch = false selectionSearchField = searchViewModel.searchText } diff --git a/PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift b/PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift index 4d74239..621ca55 100644 --- a/PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift +++ b/PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift @@ -46,6 +46,14 @@ struct TournamentGeneralSettingsView: View { .multilineTextAlignment(.trailing) .frame(maxWidth: .infinity) .focused($focusedField, equals: ._entryFee) + .onChange(of: focusedField) { + if focusedField == ._entryFee { + DispatchQueue.main.async { + UIApplication.shared.sendAction(#selector(UIResponder.selectAll(_:)), to: nil, from: nil, for: nil) + } + } + } + } label: { Text("Inscription") } diff --git a/PadelClub/Views/Tournament/Screen/Components/TournamentLevelPickerView.swift b/PadelClub/Views/Tournament/Screen/Components/TournamentLevelPickerView.swift index 524a65a..beeb89e 100644 --- a/PadelClub/Views/Tournament/Screen/Components/TournamentLevelPickerView.swift +++ b/PadelClub/Views/Tournament/Screen/Components/TournamentLevelPickerView.swift @@ -36,7 +36,7 @@ struct TournamentLevelPickerView: View { Picker(selection: $tournament.tournamentCategory, label: Text("Catégorie")) { ForEach(TournamentCategory.allCases) { type in - Text(type.localizedLabel(.title)).tag(type) + Text(type.localizedCategoryLabel(.title, ageCategory: tournament.federalAgeCategory)).tag(type) } } diff --git a/PadelClub/Views/Tournament/Shared/TournamentCellView.swift b/PadelClub/Views/Tournament/Shared/TournamentCellView.swift index eaa9b28..88ccd5d 100644 --- a/PadelClub/Views/Tournament/Shared/TournamentCellView.swift +++ b/PadelClub/Views/Tournament/Shared/TournamentCellView.swift @@ -97,6 +97,10 @@ struct TournamentCellView: View { } } } + .task(priority: .background) { + self.shouldTournamentBeOver = await tournament.shouldTournamentBeOver() + } + .id(tournament.lastTeamRefresh) } else { Text(tournament.clubLabel()).lineLimit(1) .font(.caption) @@ -108,7 +112,7 @@ struct TournamentCellView: View { .truncationMode(.tail) if displayStyle == .wide, tournament.displayAgeAndCategory(forBuild: build) { VStack(alignment: .leading, spacing: 0) { - Text(build.category.localizedLabel()) + Text(build.category.localizedCategoryLabel(ageCategory: build.age)) Text(build.age.localizedFederalAgeLabel()) } .font(.caption) @@ -120,7 +124,7 @@ struct TournamentCellView: View { } else if tournament.isCanceled { Text("Annulé".uppercased()) .capsule(foreground: .white, background: .logoRed) - } else if shouldTournamentBeOver { + } else if shouldTournamentBeOver, tournament.hasEnded() == false { Image(systemName: "clock.badge.questionmark").foregroundStyle(.logoRed) } else if let teamCount { Text(teamCount.formatted()) @@ -154,16 +158,13 @@ struct TournamentCellView: View { Spacer() if let tournament = tournament as? Tournament, tournament.isCanceled == false { VStack(alignment: .trailing) { - if shouldTournamentBeOver { + if shouldTournamentBeOver, tournament.hasEnded() == false { Text("à clôturer ?") .foregroundStyle(.logoRed) } else if let teamCount { let hasStarted = tournament.inscriptionClosed() || tournament.hasStarted() let word = hasStarted ? "équipe" : "inscription" Text(word + teamCount.pluralSuffix) - .task(priority: .background) { - self.shouldTournamentBeOver = await tournament.shouldTournamentBeOver() - } } let value: Int = tournament.onlineTeams().count if value > 0 { @@ -173,7 +174,7 @@ struct TournamentCellView: View { } } } else { - Text(build.category.localizedLabel()) + Text(build.category.localizedCategoryLabel(ageCategory: build.age)) Text(build.age.localizedFederalAgeLabel()) } } diff --git a/PadelClub/Views/Tournament/TournamentView.swift b/PadelClub/Views/Tournament/TournamentView.swift index 9e0d4ff..74fa700 100644 --- a/PadelClub/Views/Tournament/TournamentView.swift +++ b/PadelClub/Views/Tournament/TournamentView.swift @@ -211,8 +211,8 @@ struct TournamentView: View { if tournament.isCanceled == false { ToolbarItem(placement: .topBarTrailing) { Menu { - - #if DEBUG + +#if DEBUG Button { do { try self.tournament.payIfNecessary() @@ -222,8 +222,8 @@ struct TournamentView: View { } label: { Label("Payer le tournoi", systemImage: "dollarsign.circle.fill") } - #endif - +#endif + if presentationContext == .agenda { Button { navigation.openTournamentInOrganizer(tournament) @@ -232,7 +232,7 @@ struct TournamentView: View { } Divider() } - + NavigationLink(value: Screen.event) { Text("Réglages de l'événement") } @@ -244,6 +244,18 @@ struct TournamentView: View { Text("Convocations") } + if tournament.tournamentLevel.haveDeadlines() { + NavigationLink { + List { + TournamentDeadlinesView(tournament: tournament) + } + .toolbarBackground(.visible, for: .navigationBar) + .navigationTitle("Rappel des délais") + } label: { + Text("Rappel des délais") + } + } + NavigationLink(value: Screen.structure) { LabelStructure() }