fix search stuff

sync2
Raz 9 months ago
parent 8a5db5921a
commit 4e5dc3ea12
  1. 146
      PadelClub/ViewModel/SearchViewModel.swift
  2. 8
      PadelClub/Views/Navigation/Agenda/EventListView.swift
  3. 2
      PadelClub/Views/Round/RoundView.swift
  4. 48
      PadelClub/Views/Shared/SelectablePlayerListView.swift
  5. 2
      PadelClub/Views/Tournament/Screen/TournamentRankView.swift
  6. 2
      PadelClub/Views/Tournament/TournamentBuildView.swift
  7. 2
      PadelClub/Views/Tournament/TournamentView.swift

@ -89,8 +89,31 @@ class SearchViewModel: ObservableObject, Identifiable {
return nil return nil
} }
func shouldIncludeSearchTextPredicate() -> Bool {
if allowMultipleSelection {
return true
}
if allowSingleSelection {
return true
}
if tokens.isEmpty == false || hideAssimilation || selectedAgeCategory != .unlisted {
return true
}
return dataSet == .national && searchText.isEmpty == false && (tokens.isEmpty == true && hideAssimilation == false && selectedAgeCategory == .unlisted)
}
func showIndex() -> Bool { func showIndex() -> Bool {
if (dataSet == .national || dataSet == .ligue) { return isFiltering() } if dataSet == .national {
if searchText.isEmpty == false && (tokens.isEmpty == true && hideAssimilation == false && selectedAgeCategory == .unlisted) {
return false
} else {
return isFiltering()
}
}
if (dataSet == .ligue) { return isFiltering() }
if filterOption == .all { return isFiltering() } if filterOption == .all { return isFiltering() }
return true return true
} }
@ -149,66 +172,85 @@ class SearchViewModel: ObservableObject, Identifiable {
} }
} }
func searchTextPredicate() -> NSPredicate? {
var predicates : [NSPredicate] = []
let allowedCharacterSet = CharacterSet.alphanumerics.union(.whitespaces)
let canonicalVersionWithoutPunctuation = searchText.canonicalVersion.components(separatedBy: allowedCharacterSet.inverted).joined().trimmed
if canonicalVersionWithoutPunctuation.isEmpty == false {
let wordsPredicates = wordsPredicates()
if let wordsPredicates {
predicates.append(wordsPredicates)
} else {
predicates.append(NSPredicate(format: "license contains[cd] %@", canonicalVersionWithoutPunctuation))
}
predicates.append(NSPredicate(format: "canonicalFullName contains[cd] %@", canonicalVersionWithoutPunctuation))
let components = canonicalVersionWithoutPunctuation.split(separator: " ")
let pattern = components.joined(separator: ".*")
let predicate = NSPredicate(format: "canonicalFullName MATCHES[c] %@", pattern)
predicates.append(predicate)
}
if predicates.isEmpty {
return nil
}
return NSCompoundPredicate(orPredicateWithSubpredicates: predicates)
}
func orPredicate() -> NSPredicate? { func orPredicate() -> NSPredicate? {
var predicates : [NSPredicate] = [] var predicates : [NSPredicate] = []
let allowedCharacterSet = CharacterSet.alphanumerics.union(.whitespaces) let allowedCharacterSet = CharacterSet.alphanumerics.union(.whitespaces)
let canonicalVersionWithoutPunctuation = searchText.canonicalVersion.components(separatedBy: allowedCharacterSet.inverted).joined().trimmed let canonicalVersionWithoutPunctuation = searchText.canonicalVersion.components(separatedBy: allowedCharacterSet.inverted).joined().trimmed
let canonicalVersionWithPunctuation = searchText.canonicalVersionWithPunctuation.trimmed let canonicalVersionWithPunctuation = searchText.canonicalVersionWithPunctuation.trimmed
switch tokens.first {
case .none: if tokens.isEmpty {
if canonicalVersionWithoutPunctuation.isEmpty == false { if shouldIncludeSearchTextPredicate(), canonicalVersionWithoutPunctuation.isEmpty == false {
let wordsPredicates = wordsPredicates() if let searchTextPredicate = searchTextPredicate() {
if let wordsPredicates { predicates.append(searchTextPredicate)
predicates.append(wordsPredicates)
} else {
predicates.append(NSPredicate(format: "license contains[cd] %@", canonicalVersionWithoutPunctuation))
} }
predicates.append(NSPredicate(format: "canonicalFullName contains[cd] %@", canonicalVersionWithoutPunctuation))
let components = canonicalVersionWithoutPunctuation.split(separator: " ")
let pattern = components.joined(separator: ".*")
let predicate = NSPredicate(format: "canonicalFullName MATCHES[c] %@", pattern)
predicates.append(predicate)
} }
case .ligue: }
if canonicalVersionWithoutPunctuation.isEmpty { for token in tokens {
predicates.append(NSPredicate(format: "ligueName == nil")) switch token {
} else { case .ligue:
predicates.append(NSPredicate(format: "ligueName contains[cd] %@", canonicalVersionWithoutPunctuation)) if canonicalVersionWithoutPunctuation.isEmpty {
} predicates.append(NSPredicate(format: "ligueName == nil"))
case .club: } else {
if canonicalVersionWithoutPunctuation.isEmpty { predicates.append(NSPredicate(format: "ligueName contains[cd] %@", canonicalVersionWithoutPunctuation))
predicates.append(NSPredicate(format: "clubName == nil")) }
} else { case .club:
predicates.append(NSPredicate(format: "clubName contains[cd] %@", canonicalVersionWithoutPunctuation)) if canonicalVersionWithoutPunctuation.isEmpty {
} predicates.append(NSPredicate(format: "clubName == nil"))
case .rankMoreThan: } else {
if canonicalVersionWithoutPunctuation.isEmpty || Int(canonicalVersionWithoutPunctuation) == 0 { predicates.append(NSPredicate(format: "clubName contains[cd] %@", canonicalVersionWithoutPunctuation))
predicates.append(NSPredicate(format: "rank == 0")) }
} else { case .rankMoreThan:
predicates.append(NSPredicate(format: "rank >= %@", canonicalVersionWithoutPunctuation)) if canonicalVersionWithoutPunctuation.isEmpty || Int(canonicalVersionWithoutPunctuation) == 0 {
} predicates.append(NSPredicate(format: "rank == 0"))
case .rankLessThan: } else {
if canonicalVersionWithoutPunctuation.isEmpty || Int(canonicalVersionWithoutPunctuation) == 0 { predicates.append(NSPredicate(format: "rank >= %@", canonicalVersionWithoutPunctuation))
predicates.append(NSPredicate(format: "rank == 0")) }
} else { case .rankLessThan:
predicates.append(NSPredicate(format: "rank <= %@", canonicalVersionWithoutPunctuation)) if canonicalVersionWithoutPunctuation.isEmpty || Int(canonicalVersionWithoutPunctuation) == 0 {
} predicates.append(NSPredicate(format: "rank == 0"))
case .rankBetween: } else {
let values = canonicalVersionWithPunctuation.components(separatedBy: ",") predicates.append(NSPredicate(format: "rank <= %@", canonicalVersionWithoutPunctuation))
if canonicalVersionWithPunctuation.isEmpty || values.count != 2 { }
predicates.append(NSPredicate(format: "rank == 0")) case .rankBetween:
} else { let values = canonicalVersionWithPunctuation.components(separatedBy: ",")
predicates.append(NSPredicate(format: "rank BETWEEN {%@,%@}", values.first!, values.last!)) if canonicalVersionWithPunctuation.isEmpty || values.count != 2 {
} predicates.append(NSPredicate(format: "rank == 0"))
case .age: } else {
if canonicalVersionWithoutPunctuation.isEmpty || Int(canonicalVersionWithoutPunctuation) == 0 { predicates.append(NSPredicate(format: "rank BETWEEN {%@,%@}", values.first!, values.last!))
predicates.append(NSPredicate(format: "birthYear == 0")) }
} else if let birthYear = Int(canonicalVersionWithoutPunctuation) { case .age:
predicates.append(NSPredicate(format: "birthYear == %@", birthYear.formattedAsRawString())) if canonicalVersionWithoutPunctuation.isEmpty || Int(canonicalVersionWithoutPunctuation) == 0 {
predicates.append(NSPredicate(format: "birthYear == 0"))
} else if let birthYear = Int(canonicalVersionWithoutPunctuation) {
predicates.append(NSPredicate(format: "birthYear == %@", birthYear.formattedAsRawString()))
}
} }
} }
if predicates.isEmpty { if predicates.isEmpty {
return nil return nil
} }

@ -102,7 +102,7 @@ struct EventListView: View {
Logger.error(error) Logger.error(error)
} }
} label: { } label: {
Text("Les afficher tous sur Padel Club") Text("Afficher ces tournois sur Padel Club")
} }
Button { Button {
pcTournaments.forEach { tournament in pcTournaments.forEach { tournament in
@ -114,11 +114,13 @@ struct EventListView: View {
Logger.error(error) Logger.error(error)
} }
} label: { } label: {
Text("Les masquer tous sur Padel Club") Text("Masquer ces tournois sur Padel Club")
} }
} label: { } label: {
Text("Options") Text("Gérer la visibilité sur Padel Club")
.font(.caption)
.underline()
} }
} }

@ -262,7 +262,7 @@ struct RoundView: View {
.foregroundStyle(.green) .foregroundStyle(.green)
} }
} label: { } label: {
Text("Classement final des équipes") Text("Classement final")
if tournament.publishRankings == false { if tournament.publishRankings == false {
Text("Vérifiez le classement avant de publier").foregroundStyle(.logoRed) Text("Vérifiez le classement avant de publier").foregroundStyle(.logoRed)
} }

@ -337,6 +337,21 @@ struct MySearchView: View {
_searchViewModel = ObservedObject(wrappedValue: searchViewModel) _searchViewModel = ObservedObject(wrappedValue: searchViewModel)
_players = FetchRequest<ImportedPlayer>(sortDescriptors: searchViewModel.sortDescriptors(), predicate: searchViewModel.predicate()) _players = FetchRequest<ImportedPlayer>(sortDescriptors: searchViewModel.sortDescriptors(), predicate: searchViewModel.predicate())
} }
func searchedPlayers() -> [ImportedPlayer] {
if searchViewModel.searchText.isEmpty {
return Array(players)
}
if let searchPredicate = searchViewModel.searchTextPredicate() {
let filteredPlayers = players.filter { player in
searchPredicate.evaluate(with: player)
}
return filteredPlayers
}
return Array(players)
}
var body: some View { var body: some View {
playersView playersView
@ -371,8 +386,6 @@ struct MySearchView: View {
@ViewBuilder @ViewBuilder
var playersView: some View { var playersView: some View {
let showProgression = true
let showFemaleInMaleAssimilation = searchViewModel.showFemaleInMaleAssimilation
if searchViewModel.allowMultipleSelection { if searchViewModel.allowMultipleSelection {
List(selection: $searchViewModel.selectedPlayers) { List(selection: $searchViewModel.selectedPlayers) {
if searchViewModel.filterSelectionEnabled { if searchViewModel.filterSelectionEnabled {
@ -423,7 +436,7 @@ struct MySearchView: View {
} }
} }
.id(UUID()) .id(UUID())
} else { } else if searchViewModel.shouldIncludeSearchTextPredicate() {
Section { Section {
ForEach(players.indices, id: \.self) { index in ForEach(players.indices, id: \.self) { index in
let player = players[index] let player = players[index]
@ -435,26 +448,45 @@ struct MySearchView: View {
} }
} }
.id(UUID()) .id(UUID())
} else {
let filteredPlayers = searchedPlayers()
Section {
ForEach(filteredPlayers.indices, id: \.self) { index in
let player = filteredPlayers[index]
let realIndex = searchViewModel.showIndex() ? players.firstIndex(of: player) : nil
let computedIndex = realIndex != nil ? realIndex! + 1 : nil
ImportedPlayerView(player: player, index: computedIndex, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation, showProgression: true)
}
} header: {
if filteredPlayers.isEmpty == false {
headerView()
}
}
.id(UUID())
} }
} else { } else {
let filteredPlayers = searchedPlayers()
Section { Section {
ForEach(players.indices, id: \.self) { index in ForEach(filteredPlayers.indices, id: \.self) { index in
let player = players[index] let player = filteredPlayers[index]
let realIndex = searchViewModel.showIndex() ? players.firstIndex(of: player) : nil
let computedIndex = realIndex != nil ? realIndex! + 1 : nil
if searchViewModel.allowSingleSelection { if searchViewModel.allowSingleSelection {
Button { Button {
searchViewModel.selectedPlayers.insert(player) searchViewModel.selectedPlayers.insert(player)
} label: { } label: {
ImportedPlayerView(player: player, index: searchViewModel.showIndex() ? (index + 1) : nil, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation, showProgression: true) ImportedPlayerView(player: player, index: computedIndex, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation, showProgression: true)
.contentShape(Rectangle()) .contentShape(Rectangle())
} }
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.buttonStyle(.plain) .buttonStyle(.plain)
} else { } else {
ImportedPlayerView(player: player, index: searchViewModel.showIndex() ? (index + 1) : nil, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation, showProgression: true) ImportedPlayerView(player: player, index: computedIndex, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation, showProgression: true)
} }
} }
} header: { } header: {
if players.isEmpty == false { if filteredPlayers.isEmpty == false {
headerView() headerView()
} }
} }

@ -71,7 +71,7 @@ struct TournamentRankView: View {
} footer: { } footer: {
if let url = tournament.shareURL(.rankings) { if let url = tournament.shareURL(.rankings) {
Link(destination: url) { Link(destination: url) {
Text("Voir la page des classements sur Padel Club") Text("Voir les classements sur Padel Club")
} }
} }
} }

@ -124,7 +124,7 @@ struct TournamentBuildView: View {
.foregroundStyle(.green) .foregroundStyle(.green)
} }
} label: { } label: {
Text("Classement final des équipes") Text("Classement final")
if tournament.publishRankings == false { if tournament.publishRankings == false {
Text("Vérifiez le classement avant de publier").foregroundStyle(.logoRed) Text("Vérifiez le classement avant de publier").foregroundStyle(.logoRed)
} }

@ -247,7 +247,7 @@ struct TournamentView: View {
.foregroundStyle(.green) .foregroundStyle(.green)
} }
} label: { } label: {
Text("Classement final des équipes") Text("Classement final")
if tournament.publishRankings == false { if tournament.publishRankings == false {
Text("Vérifiez le classement avant de publier").foregroundStyle(.logoRed) Text("Vérifiez le classement avant de publier").foregroundStyle(.logoRed)
} }

Loading…
Cancel
Save