From 50ed16e99eba4633a3f7f02b8c20a54fe7bb5c0f Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Mon, 3 Jun 2024 16:02:42 +0200 Subject: [PATCH 1/4] fix club stuff --- PadelClub/Data/User.swift | 2 +- PadelClub/Views/Club/ClubDetailView.swift | 6 +- PadelClub/Views/Club/ClubsView.swift | 80 +++++++++++++---------- PadelClub/Views/Navigation/MainView.swift | 2 +- 4 files changed, 51 insertions(+), 39 deletions(-) diff --git a/PadelClub/Data/User.swift b/PadelClub/Data/User.swift index efd04c8..332fcd4 100644 --- a/PadelClub/Data/User.swift +++ b/PadelClub/Data/User.swift @@ -90,7 +90,7 @@ class User: ModelObject, UserBase, Storable { } func createdClubsObjectsNotFavorite() -> [Club] { - return Store.main.filter(isIncluded: { ($0.creator == id) || clubs.contains($0.id) == false }) + return Store.main.filter(isIncluded: { ($0.creator == id) && clubs.contains($0.id) == false }) } func saveMatchFormatsDefaultDuration(_ matchFormat: MatchFormat, estimatedDuration: Int) { diff --git a/PadelClub/Views/Club/ClubDetailView.swift b/PadelClub/Views/Club/ClubDetailView.swift index 257493c..62572df 100644 --- a/PadelClub/Views/Club/ClubDetailView.swift +++ b/PadelClub/Views/Club/ClubDetailView.swift @@ -17,6 +17,7 @@ struct ClubDetailView: View { @State private var zipCode: String @State private var selectedCourt: Court? @Bindable var club: Club + @State private var clubDeleted: Bool = false var displayContext: DisplayContext var selection: ((Club) -> ())? = nil @@ -217,9 +218,10 @@ struct ClubDetailView: View { Section { RowButtonView("Supprimer ce club", role: .destructive) { do { - try dataStore.clubs.deleteById(club.id) + clubDeleted = true dataStore.user.clubs.removeAll(where: { $0 == club.id }) self.dataStore.saveUser() + try dataStore.clubs.deleteById(club.id) dismiss() } catch { Logger.error(error) @@ -240,7 +242,7 @@ struct ClubDetailView: View { CourtView(court: court) } .onDisappear { - if displayContext == .edition { + if displayContext == .edition && clubDeleted == false { do { try dataStore.clubs.addOrUpdate(instance: club) } catch { diff --git a/PadelClub/Views/Club/ClubsView.swift b/PadelClub/Views/Club/ClubsView.swift index 7d4dc8d..862f897 100644 --- a/PadelClub/Views/Club/ClubsView.swift +++ b/PadelClub/Views/Club/ClubsView.swift @@ -28,31 +28,36 @@ struct ClubsView: View { var body: some View { List { let clubs : [Club] = dataStore.user.clubsObjects(includeCreated: false) - Section { - ForEach(clubs) { club in - if let selection { - Button { - selection(club) - dismiss() - } label: { - ClubRowView(club: club, displayContext: .selection) - .frame(maxWidth: .infinity) - } - .contentShape(Rectangle()) - .buttonStyle(.plain) - } else { - NavigationLink { - ClubDetailView(club: club, displayContext: club.hasBeenCreated(by: dataStore.user.id) ? .edition : .lockedForEditing) - } label: { - ClubRowView(club: club) + let onlyCreatedClubs : [Club] = dataStore.user.createdClubsObjectsNotFavorite() + + if clubs.isEmpty == false || onlyCreatedClubs.isEmpty == false { + Section { + if clubs.isEmpty && onlyCreatedClubs.isEmpty == false { + _contentUnavailable() + } + ForEach(clubs) { club in + if let selection { + Button { + selection(club) + dismiss() + } label: { + ClubRowView(club: club, displayContext: .selection) + .frame(maxWidth: .infinity) + } + .contentShape(Rectangle()) + .buttonStyle(.plain) + } else { + NavigationLink { + ClubDetailView(club: club, displayContext: club.hasBeenCreated(by: dataStore.user.id) ? .edition : .lockedForEditing) + } label: { + ClubRowView(club: club) + } } } + } header: { + Text("Clubs favoris") } - } header: { - Text("Clubs favoris") } - - let onlyCreatedClubs : [Club] = dataStore.user.createdClubsObjectsNotFavorite() if onlyCreatedClubs.isEmpty == false { Section { @@ -81,22 +86,11 @@ struct ClubsView: View { } } .overlay { - if dataStore.user.hasFavoriteClubsAndCreatedClubs() == false { - ContentUnavailableView { - Label("Aucun club", systemImage: "house.and.flag.fill") - } description: { - Text("Texte décrivant l'utilité d'un club et les features que cela apporte") - } actions: { - RowButtonView("Créer un nouveau club", systemImage: "plus.circle.fill") { - newClub = Club.newEmptyInstance() - } - RowButtonView("Chercher un club", systemImage: "magnifyingglass.circle.fill") { - presentClubSearchView = true - } - } + if dataStore.user.clubsObjects(includeCreated: true).isEmpty { + _contentUnavailable() } } - .navigationTitle(selection == nil ? "Mes clubs" : "Choisir un club") + .navigationTitle(selection == nil ? "Clubs favoris" : "Choisir un club") .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .navigationBar) .sheet(isPresented: presentClubCreationView) { @@ -141,6 +135,22 @@ struct ClubsView: View { } } } + + private func _contentUnavailable() -> some View { + ContentUnavailableView { + Label("Aucun club", systemImage: "house.and.flag.fill") + } description: { + Text("Avoir un club en favori permet d'accéder aux tournois enregistrés sur Tenup.") + } actions: { + RowButtonView("Créer un nouveau club", systemImage: "plus.circle.fill") { + newClub = Club.newEmptyInstance() + } + RowButtonView("Chercher un club", systemImage: "magnifyingglass.circle.fill") { + presentClubSearchView = true + } + } + + } } #Preview { diff --git a/PadelClub/Views/Navigation/MainView.swift b/PadelClub/Views/Navigation/MainView.swift index 9d41fb5..9695d3f 100644 --- a/PadelClub/Views/Navigation/MainView.swift +++ b/PadelClub/Views/Navigation/MainView.swift @@ -49,7 +49,7 @@ struct MainView: View { } var badgeText: Text? { - dataStore.user.username.isEmpty ? Text("!").font(.headline) : nil + Store.main.userId == nil ? Text("!").font(.headline) : nil } var body: some View { From 586c305ba73d92f4b93ee00537d46425a1c09b10 Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Mon, 3 Jun 2024 16:03:06 +0200 Subject: [PATCH 2/4] b35 --- PadelClub.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index 215bce4..368ae13 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -1939,7 +1939,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 34; + CURRENT_PROJECT_VERSION = 35; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; @@ -1977,7 +1977,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 34; + CURRENT_PROJECT_VERSION = 35; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; From c735c023bb66c04d05fc386e74f3c511865c7252 Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Mon, 3 Jun 2024 22:34:58 +0200 Subject: [PATCH 3/4] fix stuff --- PadelClub.xcodeproj/project.pbxproj | 4 +-- PadelClub/Data/User.swift | 4 +-- PadelClub/Extensions/String+Extensions.swift | 8 ++++-- PadelClub/Views/Club/ClubDetailView.swift | 2 +- PadelClub/Views/Club/ClubRowView.swift | 3 +- .../Navigation/Agenda/ActivityView.swift | 10 +++---- .../Navigation/Agenda/EventListView.swift | 2 +- .../Views/Tournament/FileImportView.swift | 28 ++++++++----------- .../Screen/InscriptionManagerView.swift | 19 +++++++------ 9 files changed, 41 insertions(+), 39 deletions(-) diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index 368ae13..2eae591 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -1939,7 +1939,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 35; + CURRENT_PROJECT_VERSION = 36; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; @@ -1977,7 +1977,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 35; + CURRENT_PROJECT_VERSION = 36; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; diff --git a/PadelClub/Data/User.swift b/PadelClub/Data/User.swift index 332fcd4..29de3e6 100644 --- a/PadelClub/Data/User.swift +++ b/PadelClub/Data/User.swift @@ -73,8 +73,8 @@ class User: ModelObject, UserBase, Storable { return "Sportivement,\n\(firstName) \(lastName), votre JAP." } - func hasClubs() -> Bool { - self.clubs.isEmpty == false + func hasTenupClubs() -> Bool { + self.clubsObjects().filter({ $0.code != nil }).isEmpty == false } func hasFavoriteClubsAndCreatedClubs() -> Bool { diff --git a/PadelClub/Extensions/String+Extensions.swift b/PadelClub/Extensions/String+Extensions.swift index 0398619..580830e 100644 --- a/PadelClub/Extensions/String+Extensions.swift +++ b/PadelClub/Extensions/String+Extensions.swift @@ -46,16 +46,18 @@ extension String { func acronym() -> String { let acronym = canonicalVersion.replaceCharactersFromSet(characterSet: .whitespacesAndNewlines) if acronym.count > 10 { - return concatenateFirstLetters() + return concatenateFirstLetters().uppercased() } else { - return acronym + return acronym.uppercased() } } func concatenateFirstLetters() -> String { // Split the input into sentences let sentences = self.components(separatedBy: .whitespacesAndNewlines) - + if sentences.count == 1 { + return String(self.prefix(10)) + } // Extract the first character of each sentence let firstLetters = sentences.compactMap { sentence -> Character? in let trimmedSentence = sentence.trimmingCharacters(in: .whitespacesAndNewlines) diff --git a/PadelClub/Views/Club/ClubDetailView.swift b/PadelClub/Views/Club/ClubDetailView.swift index 62572df..62081e7 100644 --- a/PadelClub/Views/Club/ClubDetailView.swift +++ b/PadelClub/Views/Club/ClubDetailView.swift @@ -59,7 +59,7 @@ struct ClubDetailView: View { .submitLabel( displayContext == .addition ? .next : .done) .onSubmit(of: .text) { if club.acronym.isEmpty { - club.acronym = club.name.canonicalVersion.replaceCharactersFromSet(characterSet: .whitespacesAndNewlines) + club.acronym = club.name.canonicalVersion.replaceCharactersFromSet(characterSet: .whitespacesAndNewlines).acronym() } if displayContext == .edition && city.isEmpty == true { diff --git a/PadelClub/Views/Club/ClubRowView.swift b/PadelClub/Views/Club/ClubRowView.swift index 3a3e2dc..0f7f2fd 100644 --- a/PadelClub/Views/Club/ClubRowView.swift +++ b/PadelClub/Views/Club/ClubRowView.swift @@ -13,13 +13,14 @@ struct ClubRowView: View { var body: some View { LabeledContent { + Text(club.acronym) // if displayContext == .edition { // Image(systemName: club.isFavorite() ? "star.fill" : "star") // .foregroundStyle(club.isFavorite() ? .green : .logoRed) // } } label: { + Text("Club") Text(club.name) - Text(club.acronym) } } } diff --git a/PadelClub/Views/Navigation/Agenda/ActivityView.swift b/PadelClub/Views/Navigation/Agenda/ActivityView.swift index f1e080b..bcbeaf3 100644 --- a/PadelClub/Views/Navigation/Agenda/ActivityView.swift +++ b/PadelClub/Views/Navigation/Agenda/ActivityView.swift @@ -121,14 +121,14 @@ struct ActivityView: View { } .task { if navigation.agendaDestination == .tenup - && dataStore.user.hasClubs() == true + && dataStore.user.hasTenupClubs() == true && federalDataViewModel.federalTournaments.isEmpty { _gatherFederalTournaments() } } .onChange(of: navigation.agendaDestination) { if navigation.agendaDestination == .tenup - && dataStore.user.hasClubs() == true + && dataStore.user.hasTenupClubs() == true && federalDataViewModel.federalTournaments.isEmpty { _gatherFederalTournaments() } @@ -192,7 +192,7 @@ struct ActivityView: View { .tint(.master) } .sheet(isPresented: $presentClubSearchView, onDismiss: { - if dataStore.user.hasClubs() == true { + if dataStore.user.hasTenupClubs() == true { federalDataViewModel.federalTournaments.removeAll() navigation.agendaDestination = .tenup } @@ -247,7 +247,7 @@ struct ActivityView: View { RowButtonView("Créer un nouvel événement") { newTournament = Tournament.newEmptyInstance() } - if dataStore.user.hasClubs() == false { + if dataStore.user.hasTenupClubs() == false { RowButtonView("Chercher l'un de vos clubs") { presentClubSearchView = true } @@ -268,7 +268,7 @@ struct ActivityView: View { } private func _tenupEmptyView() -> some View { - if dataStore.user.hasClubs() == false { + if dataStore.user.hasTenupClubs() == false { ContentUnavailableView { Label("Aucun tournoi", systemImage: "shield.slash") } description: { diff --git a/PadelClub/Views/Navigation/Agenda/EventListView.swift b/PadelClub/Views/Navigation/Agenda/EventListView.swift index 7cfcb48..7adadb5 100644 --- a/PadelClub/Views/Navigation/Agenda/EventListView.swift +++ b/PadelClub/Views/Navigation/Agenda/EventListView.swift @@ -53,7 +53,7 @@ struct EventListView: View { .headerProminence(.increased) .task { if navigation.agendaDestination == .tenup - && dataStore.user.hasClubs() == true + && dataStore.user.hasTenupClubs() == true && _tournaments.isEmpty { _gatherFederalTournaments(startDate: section) } diff --git a/PadelClub/Views/Tournament/FileImportView.swift b/PadelClub/Views/Tournament/FileImportView.swift index 5eb7799..87cafe6 100644 --- a/PadelClub/Views/Tournament/FileImportView.swift +++ b/PadelClub/Views/Tournament/FileImportView.swift @@ -104,17 +104,7 @@ struct FileImportView: View { } } } - - if validationInProgress { - Section { - LabeledContent { - ProgressView() - } label: { - Text("Mise à jour des équipes") - } - } - } - + if let errorMessage { Section { Text(errorMessage) @@ -157,7 +147,7 @@ struct FileImportView: View { Section { ContentUnavailableView("Aucune équipe détectée", systemImage: "person.2.slash") } - } else if didImport && validationInProgress == false { + } else if didImport { let _filteredTeams = filteredTeams let previousTeams = tournament.sortedTeams() @@ -232,18 +222,24 @@ struct FileImportView: View { } ToolbarItem(placement: .topBarTrailing) { - ButtonValidateView { - _validate() + if validationInProgress { + ProgressView() + } else { + ButtonValidateView { + validationInProgress = true + } + .disabled(teams.isEmpty) } - .disabled(teams.isEmpty) } } .interactiveDismissDisabled(validationInProgress) .disabled(validationInProgress) + .onChange(of: validationInProgress) { + _validate() + } } private func _validate() { - validationInProgress = true Task { let previousTeams = filteredTeams.compactMap({ $0.previousTeam }) diff --git a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift index d5b27a8..dbaa21b 100644 --- a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift +++ b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift @@ -152,14 +152,15 @@ struct InscriptionManagerView: View { } private func _handleHashDiff() async { - let newHash = _simpleHash(ids: tournament.selectedSortedTeams().map { $0.id }) - if let teamsHash, newHash != teamsHash { + let selectedSortedTeams = tournament.selectedSortedTeams() + let newHash = _simpleHash(ids: selectedSortedTeams.map { $0.id }) + if (self.teamsHash != nil && newHash != teamsHash!) || (self.teamsHash == nil && selectedSortedTeams.isEmpty == false) { self.teamsHash = newHash if self.tournament.shouldVerifyBracket == false || self.tournament.shouldVerifyGroupStage == false { self.tournament.shouldVerifyBracket = true self.tournament.shouldVerifyGroupStage = true - let waitingList = self.tournament.waitingListTeams(in: self.tournament.selectedSortedTeams()) + let waitingList = self.tournament.waitingListTeams(in: selectedSortedTeams) waitingList.forEach { team in if team.bracketPosition != nil || team.groupStagePosition != nil { team.resetPositions() @@ -181,10 +182,9 @@ struct InscriptionManagerView: View { _managementView() if _isEditingTeam() { _buildingTeamView() - } else if tournament.unsortedTeams().isEmpty { + } else if unfilteredTeams.isEmpty { _inscriptionTipsView() - } - if _isEditingTeam() == false { + } else { _teamRegisteredView() } } @@ -284,7 +284,9 @@ struct InscriptionManagerView: View { } .tint(.master) } - .sheet(isPresented: $presentImportView) { + .sheet(isPresented: $presentImportView, onDismiss: { + _getTeams() + }) { NavigationStack { FileImportView() } @@ -428,12 +430,13 @@ struct InscriptionManagerView: View { } private func _prepareTeams() { + #if DEBUG_TIME let start = Date() defer { let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000) print("func _prepareTeams", duration.formatted(.units(allowed: [.seconds, .milliseconds]))) } - + #endif sortedTeams = tournament.sortedTeams() var teams = sortedTeams From 0f2e8f69bd439a5de5b14f9309cc60df5349472b Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Mon, 3 Jun 2024 23:56:13 +0200 Subject: [PATCH 4/4] - fix save not called when no more seeds and edit mode auto-disabling - fix round and loser round addition not handling seed in upper match --- PadelClub.xcodeproj/project.pbxproj | 4 +-- PadelClub/Data/Match.swift | 4 +++ PadelClub/Views/Round/RoundSettingsView.swift | 28 +++++++++++++++++-- PadelClub/Views/Round/RoundView.swift | 4 +-- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index 2eae591..e21dc63 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -1939,7 +1939,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 36; + CURRENT_PROJECT_VERSION = 37; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; @@ -1977,7 +1977,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 36; + CURRENT_PROJECT_VERSION = 37; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; diff --git a/PadelClub/Data/Match.swift b/PadelClub/Data/Match.swift index 4b4d864..3a743b7 100644 --- a/PadelClub/Data/Match.swift +++ b/PadelClub/Data/Match.swift @@ -355,6 +355,10 @@ class Match: ModelObject, Storable { func followingMatch() -> Match? { guard let nextRoundId = roundObject?.nextRound()?.id else { return nil } + return getFollowingMatch(fromNextRoundId: nextRoundId) + } + + func getFollowingMatch(fromNextRoundId nextRoundId: String) -> Match? { return Store.main.filter(isIncluded: { $0.round == nextRoundId && $0.index == (index - 1) / 2 }).first } diff --git a/PadelClub/Views/Round/RoundSettingsView.swift b/PadelClub/Views/Round/RoundSettingsView.swift index eccbf35..cd1b35f 100644 --- a/PadelClub/Views/Round/RoundSettingsView.swift +++ b/PadelClub/Views/Round/RoundSettingsView.swift @@ -52,8 +52,30 @@ struct RoundSettingsView: View { let round = Round(tournament: tournament.id, index: roundIndex, matchFormat: tournament.matchFormat) let matchCount = RoundRule.numberOfMatches(forRoundIndex: roundIndex) let matchStartIndex = RoundRule.matchIndex(fromRoundIndex: roundIndex) - let matches = (0..