diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index dc6fd3f..c7ee99f 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -1919,7 +1919,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 14; + CURRENT_PROJECT_VERSION = 15; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; @@ -1957,7 +1957,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 14; + CURRENT_PROJECT_VERSION = 15; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; diff --git a/PadelClub/Data/GroupStage.swift b/PadelClub/Data/GroupStage.swift index 7be2fdb..941900b 100644 --- a/PadelClub/Data/GroupStage.swift +++ b/PadelClub/Data/GroupStage.swift @@ -78,13 +78,20 @@ class GroupStage: ModelObject, Storable { _removeMatches() var _matches = [Match]() + var _teamScores = [TeamScore]() + for i in 0..<_numberOfMatchesToBuild() { let newMatch = Match(groupStage: id, index: i, matchFormat: matchFormat, name: localizedMatchUpLabel(for: i)) - newMatch.updateTeamScores() + _teamScores.append(contentsOf: newMatch.createTeamScores()) _matches.append(newMatch) } - try? DataStore.shared.matches.addOrUpdate(contentOfs: _matches) + do { + try DataStore.shared.matches.addOrUpdate(contentOfs: _matches) + try DataStore.shared.teamScores.addOrUpdate(contentOfs: _teamScores) + } catch { + Logger.error(error) + } } func playedMatches() -> [Match] { diff --git a/PadelClub/Data/Match.swift b/PadelClub/Data/Match.swift index bb10814..4c9bff4 100644 --- a/PadelClub/Data/Match.swift +++ b/PadelClub/Data/Match.swift @@ -442,11 +442,16 @@ class Match: ModelObject, Storable { _loserMatch()?.resetTeamScores() } - func updateTeamScores() { - resetTeamScores() + func createTeamScores() -> [TeamScore] { let teamOne = team(.one) let teamTwo = team(.two) let teams = [teamOne, teamTwo].compactMap({ $0 }).map { TeamScore(match: id, team: $0) } + return teams + } + + func updateTeamScores() { + resetTeamScores() + let teams = createTeamScores() do { try DataStore.shared.teamScores.addOrUpdate(contentOfs: teams) } catch { diff --git a/PadelClub/Data/TeamRegistration.swift b/PadelClub/Data/TeamRegistration.swift index 22bee3a..1fbe1be 100644 --- a/PadelClub/Data/TeamRegistration.swift +++ b/PadelClub/Data/TeamRegistration.swift @@ -198,6 +198,10 @@ class TeamRegistration: ModelObject, Storable { [name, playersPasteData(), formattedInscriptionDate()].compactMap({ $0 }).joined(separator: "\n") } + var computedRegistrationDate: Date { + registrationDate ?? .distantFuture + } + func formattedInscriptionDate() -> String? { if let registrationDate { return "Inscrit le " + registrationDate.formatted(.dateTime.weekday().day().month().hour().minute()) diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index d1dd8bd..956012a 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -1138,7 +1138,7 @@ class Tournament : ModelObject, Storable { return "placer \(availableQualifiedTeams.count) qualifié" + availableQualifiedTeams.count.pluralSuffix } if let round = getActiveRound() { - return [round.roundTitle(), round.roundStatus()].joined(separator: " ") + return [round.roundTitle(.short), round.roundStatus()].joined(separator: " ") } else { return "à construire" } diff --git a/PadelClub/Utils/PadelRule.swift b/PadelClub/Utils/PadelRule.swift index 6151765..e595111 100644 --- a/PadelClub/Utils/PadelRule.swift +++ b/PadelClub/Utils/PadelRule.swift @@ -1506,13 +1506,19 @@ enum RoundRule { return roundName(fromRoundIndex: roundIndex) } - static func roundName(fromRoundIndex roundIndex: Int) -> String { + static func roundName(fromRoundIndex roundIndex: Int, displayStyle: DisplayStyle = .wide) -> String { switch roundIndex { case 0: return "Finale" case 1: + if displayStyle == .short { + return "Demi" + } return "Demi-finale" case 2: + if displayStyle == .short { + return "Quart" + } return "Quart de finale" default: return "\(Int(pow(2.0, Double(roundIndex))))ème" diff --git a/PadelClub/Views/Components/Labels.swift b/PadelClub/Views/Components/Labels.swift index eb1471c..5d2ed00 100644 --- a/PadelClub/Views/Components/Labels.swift +++ b/PadelClub/Views/Components/Labels.swift @@ -30,3 +30,9 @@ struct LabelDelete: View { Label("Effacer", systemImage: "trash") } } + +struct LabelFilter: View { + var body: some View { + Label("Filtrer", systemImage: "line.3.horizontal.decrease.circle") + } +} diff --git a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift index d2cf5d8..0c9a994 100644 --- a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift +++ b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift @@ -34,7 +34,40 @@ struct InscriptionManagerView: View { @State private var autoSelect: Bool = false @State private var teamsHash: Int? @State private var presentationCount: Int = 0 + @State private var filterMode: FilterMode = .all + @State private var sortingMode: SortingMode = .teamWeight + @State private var byDecreasingOrdering: Bool = false + enum SortingMode: Int, Identifiable, CaseIterable { + var id: Int { self.rawValue } + case registrationDate + case teamWeight + + func localizedLabel() -> String { + switch self { + case .registrationDate: + return "Date d'inscription" + case .teamWeight: + return "Poids d'équipe" + } + } + } + + enum FilterMode: Int, Identifiable, CaseIterable { + var id: Int { self.rawValue } + case all + case walkOut + + func localizedLabel() -> String { + switch self { + case .all: + return "Toutes les équipes" + case .walkOut: + return "Voir les WOs" + } + } + } + let slideToDeleteTip = SlideToDeleteTip() let inscriptionManagerWomanRankTip = InscriptionManagerWomanRankTip() let fileTip = InscriptionManagerFileInputTip() @@ -167,7 +200,29 @@ struct InscriptionManagerView: View { } } } else { - ToolbarItem(placement: .navigationBarTrailing) { + ToolbarItemGroup(placement: .navigationBarTrailing) { + Menu { + Picker(selection: $filterMode) { + ForEach(FilterMode.allCases) { + Text($0.localizedLabel()).tag($0) + } + } label: { + } + Picker(selection: $sortingMode) { + ForEach(SortingMode.allCases) { + Text($0.localizedLabel()).tag($0) + } + } label: { + } + + Picker(selection: $byDecreasingOrdering) { + Text("Croissant").tag(false) + Text("Décroissant").tag(true) + } label: { + } + } label: { + LabelFilter() + } Menu { if tournament.inscriptionClosed() == false { Menu { @@ -233,9 +288,27 @@ struct InscriptionManagerView: View { createdPlayerIds.isEmpty == false || editedTeam != nil || pasteString != nil } + private func _getTeams(from sortedTeams: [TeamRegistration]) -> [TeamRegistration] { + var teams = sortedTeams + if filterMode == .walkOut { + teams = teams.filter({ $0.walkOut }) + } + + if sortingMode == .registrationDate { + teams = teams.sorted(by: \.computedRegistrationDate) + } + + if byDecreasingOrdering { + return teams.reversed() + } else { + return teams + } + } + private func _teamRegisteredView() -> some View { List { - let unfilteredTeams = tournament.sortedTeams() + let sortedTeams = tournament.sortedTeams() + let unfilteredTeams = _getTeams(from: sortedTeams) if presentSearch == false { _rankHandlerView() @@ -273,7 +346,7 @@ struct InscriptionManagerView: View { } ForEach(teams) { team in - let teamIndex = team.index(in: unfilteredTeams) + let teamIndex = team.index(in: sortedTeams) Section { TeamDetailView(team: team) } header: { diff --git a/PadelClub/Views/Tournament/TournamentBuildView.swift b/PadelClub/Views/Tournament/TournamentBuildView.swift index 787a151..8749b6a 100644 --- a/PadelClub/Views/Tournament/TournamentBuildView.swift +++ b/PadelClub/Views/Tournament/TournamentBuildView.swift @@ -28,7 +28,7 @@ struct TournamentBuildView: View { } label: { Text("Poules") if tournament.shouldVerifyGroupStage { - Text("Veuillez vérifier les poules").foregroundStyle(.logoRed) + Text("Vérifier les poules").foregroundStyle(.logoRed) } } } @@ -41,7 +41,7 @@ struct TournamentBuildView: View { } label: { Text("Tableau") if tournament.shouldVerifyBracket { - Text("Veuillez vérifier la tableau").foregroundStyle(.logoRed) + Text("Vérifier la tableau").foregroundStyle(.logoRed) } } }