sync2
Raz 9 months ago
parent 6e31435840
commit 738b79bf9c
  1. 5
      PadelClub/Data/Federal/FederalTournamentHolder.swift
  2. 4
      PadelClub/Data/Tournament.swift
  3. 32
      PadelClub/ViewModel/SearchViewModel.swift
  4. 71
      PadelClub/Views/Navigation/Agenda/EventListView.swift
  5. 3
      PadelClub/Views/Tournament/Screen/AddTeamView.swift
  6. 17
      PadelClub/Views/Tournament/Screen/RegistrationSetupView.swift
  7. 4
      PadelClub/Views/Tournament/TournamentInscriptionView.swift

@ -19,14 +19,9 @@ protocol FederalTournamentHolder {
var dayPeriod: DayPeriod { get } var dayPeriod: DayPeriod { get }
func tournamentTitle(_ displayStyle: DisplayStyle, forBuild build: any TournamentBuildHolder) -> String func tournamentTitle(_ displayStyle: DisplayStyle, forBuild build: any TournamentBuildHolder) -> String
func displayAgeAndCategory(forBuild build: any TournamentBuildHolder) -> Bool func displayAgeAndCategory(forBuild build: any TournamentBuildHolder) -> Bool
func togglePrivate(isPrivate: Bool)
} }
extension FederalTournamentHolder { extension FederalTournamentHolder {
func togglePrivate(isPrivate: Bool) {
}
func durationLabel() -> String { func durationLabel() -> String {
switch dayDuration { switch dayDuration {
case 1: case 1:

@ -2680,10 +2680,6 @@ extension Tournament: Hashable {
} }
extension Tournament: FederalTournamentHolder { extension Tournament: FederalTournamentHolder {
func togglePrivate(isPrivate: Bool) {
self.isPrivate = isPrivate
}
func tournamentTitle(_ displayStyle: DisplayStyle, forBuild build: any TournamentBuildHolder) -> String { func tournamentTitle(_ displayStyle: DisplayStyle, forBuild build: any TournamentBuildHolder) -> String {
if isAnimation() { if isAnimation() {
if let name { if let name {

@ -356,6 +356,17 @@ class SearchViewModel: ObservableObject, Identifiable {
static func pastePredicate(pasteField: String, mostRecentDate: Date?, filterOption: PlayerFilterOption) -> NSPredicate? { static func pastePredicate(pasteField: String, mostRecentDate: Date?, filterOption: PlayerFilterOption) -> NSPredicate? {
var andPredicates = [NSPredicate]()
var orPredicates = [NSPredicate]()
let matches = pasteField.licencesFound()
let licensesPredicates = matches.map { NSPredicate(format: "license contains[cd] %@", $0) }
orPredicates = licensesPredicates
if matches.count == 2 {
return NSCompoundPredicate(orPredicateWithSubpredicates: orPredicates)
}
let allowedCharacterSet = CharacterSet.alphanumerics.union(.whitespaces) let allowedCharacterSet = CharacterSet.alphanumerics.union(.whitespaces)
// Remove all characters that are not in the allowedCharacterSet // Remove all characters that are not in the allowedCharacterSet
@ -369,14 +380,8 @@ class SearchViewModel: ObservableObject, Identifiable {
let textStrings: [String] = text.components(separatedBy: .whitespacesAndNewlines) let textStrings: [String] = text.components(separatedBy: .whitespacesAndNewlines)
let nonEmptyStrings: [String] = textStrings.compactMap { $0.isEmpty ? nil : $0 } let nonEmptyStrings: [String] = textStrings.compactMap { $0.isEmpty ? nil : $0 }
let nameComponents = nonEmptyStrings.filter({ $0 != "de" && $0 != "la" && $0 != "le" && $0.count > 1 }) let nameComponents = nonEmptyStrings.filter({ $0 != "de" && $0 != "la" && $0 != "le" && $0.count > 1 })
var andPredicates = [NSPredicate]()
var orPredicates = [NSPredicate]()
//self.wordsCount = nameComponents.count
if let slashPredicate = getSpecialSlashPredicate(inputString: pasteField) {
orPredicates.append(slashPredicate)
}
//self.wordsCount = nameComponents.count
if filterOption == .female { if filterOption == .female {
andPredicates.append(NSPredicate(format: "male == NO")) andPredicates.append(NSPredicate(format: "male == NO"))
} }
@ -385,12 +390,21 @@ class SearchViewModel: ObservableObject, Identifiable {
andPredicates.append(NSPredicate(format: "importDate == %@", mostRecentDate as CVarArg)) andPredicates.append(NSPredicate(format: "importDate == %@", mostRecentDate as CVarArg))
} }
if let slashPredicate = getSpecialSlashPredicate(inputString: pasteField) {
orPredicates.append(slashPredicate)
}
print("nameComponents", nameComponents.count)
if nameComponents.count < 50 {
if nameComponents.count > 1 { if nameComponents.count > 1 {
orPredicates.append(contentsOf: nameComponents.pairs().map { orPredicates.append(contentsOf: nameComponents.pairs().map {
return NSPredicate(format: "(firstName BEGINSWITH[cd] %@ AND lastName BEGINSWITH[cd] %@) OR (firstName BEGINSWITH[cd] %@ AND lastName BEGINSWITH[cd] %@)", $0, $1, $1, $0) }) return NSPredicate(format: "(firstName BEGINSWITH[cd] %@ AND lastName BEGINSWITH[cd] %@) OR (firstName BEGINSWITH[cd] %@ AND lastName BEGINSWITH[cd] %@)", $0, $1, $1, $0) })
} else { } else {
orPredicates.append(contentsOf: nameComponents.map { NSPredicate(format: "firstName contains[cd] %@ OR lastName contains[cd] %@", $0,$0) }) orPredicates.append(contentsOf: nameComponents.map { NSPredicate(format: "firstName contains[cd] %@ OR lastName contains[cd] %@", $0,$0) })
} }
}
let components = text.split(separator: " ") let components = text.split(separator: " ")
let pattern = components.joined(separator: ".*") let pattern = components.joined(separator: ".*")
@ -398,10 +412,6 @@ class SearchViewModel: ObservableObject, Identifiable {
let canonicalFullNamePredicate = NSPredicate(format: "canonicalFullName MATCHES[c] %@", pattern) let canonicalFullNamePredicate = NSPredicate(format: "canonicalFullName MATCHES[c] %@", pattern)
orPredicates.append(canonicalFullNamePredicate) orPredicates.append(canonicalFullNamePredicate)
let matches = pasteField.licencesFound()
let licensesPredicates = matches.map { NSPredicate(format: "license contains[cd] %@", $0) }
orPredicates = orPredicates + licensesPredicates
var predicate = NSCompoundPredicate(andPredicateWithSubpredicates: andPredicates) var predicate = NSCompoundPredicate(andPredicateWithSubpredicates: andPredicates)
if orPredicates.isEmpty == false { if orPredicates.isEmpty == false {

@ -92,9 +92,35 @@ struct EventListView: View {
private func _menuOptions(_ pcTournaments: [Tournament]) -> some View { private func _menuOptions(_ pcTournaments: [Tournament]) -> some View {
Menu { Menu {
_options(pcTournaments)
} label: {
Text("Options rapides pour ce mois")
.underline()
}
}
@ViewBuilder
private func _options(_ pcTournaments: [Tournament]) -> some View {
Section {
if pcTournaments.anySatisfy({ $0.isPrivate == true }) {
Button {
pcTournaments.forEach { tournament in
tournament.isPrivate = false
}
do {
try dataStore.tournaments.addOrUpdate(contentOfs: pcTournaments)
} catch {
Logger.error(error)
}
} label: {
Text("Afficher ce\(pcTournaments.count.pluralSuffix) tournoi\(pcTournaments.count.pluralSuffix) sur Padel Club")
}
}
if pcTournaments.anySatisfy({ $0.isPrivate == false }) {
Button { Button {
pcTournaments.forEach { tournament in pcTournaments.forEach { tournament in
tournament.togglePrivate(isPrivate: false) tournament.isPrivate = true
} }
do { do {
try dataStore.tournaments.addOrUpdate(contentOfs: pcTournaments) try dataStore.tournaments.addOrUpdate(contentOfs: pcTournaments)
@ -102,11 +128,19 @@ struct EventListView: View {
Logger.error(error) Logger.error(error)
} }
} label: { } label: {
Text("Afficher ces tournois sur Padel Club") Text("Masquer ce\(pcTournaments.count.pluralSuffix) tournoi\(pcTournaments.count.pluralSuffix) sur Padel Club")
}
}
} header: {
Text("Visibilité sur Padel Club")
} }
Divider()
if pcTournaments.anySatisfy({ $0.hasEnded() == false && $0.enableOnlineRegistration == false && $0.onlineRegistrationCanBeEnabled() }) || pcTournaments.anySatisfy({ $0.enableOnlineRegistration == true }) {
Section {
if pcTournaments.anySatisfy({ $0.hasEnded() == false && $0.enableOnlineRegistration == false && $0.onlineRegistrationCanBeEnabled() }) {
Button { Button {
pcTournaments.forEach { tournament in pcTournaments.forEach { tournament in
tournament.togglePrivate(isPrivate: true) tournament.enableOnlineRegistration = true
} }
do { do {
try dataStore.tournaments.addOrUpdate(contentOfs: pcTournaments) try dataStore.tournaments.addOrUpdate(contentOfs: pcTournaments)
@ -114,13 +148,27 @@ struct EventListView: View {
Logger.error(error) Logger.error(error)
} }
} label: { } label: {
Text("Masquer ces tournois sur Padel Club") Text("Activer l'inscription en ligne")
}
} }
if pcTournaments.anySatisfy({ $0.enableOnlineRegistration == true }) {
Button {
pcTournaments.forEach { tournament in
tournament.enableOnlineRegistration = false
}
do {
try dataStore.tournaments.addOrUpdate(contentOfs: pcTournaments)
} catch {
Logger.error(error)
}
} label: { } label: {
Text("Gérer la visibilité sur Padel Club") Text("Désactiver l'inscription en ligne")
.font(.caption) }
.underline() }
} header: {
Text("Inscription en ligne")
}
} }
} }
@ -160,13 +208,20 @@ struct EventListView: View {
NavigationLink(value: tournament) { NavigationLink(value: tournament) {
TournamentCellView(tournament: tournament, shouldTournamentBeOver: tournament.shouldTournamentBeOver()) TournamentCellView(tournament: tournament, shouldTournamentBeOver: tournament.shouldTournamentBeOver())
} }
.listRowView(isActive: tournament.enableOnlineRegistration, color: .green, hideColorVariation: true)
.contextMenu { .contextMenu {
if tournament.hasEnded() == false { if tournament.hasEnded() == false {
Button { Button {
navigation.openTournamentInOrganizer(tournament) navigation.openTournamentInOrganizer(tournament)
} label: { } label: {
Label("Voir dans le gestionnaire", systemImage: "line.diagonal.arrow") Label("Afficher dans le gestionnaire", systemImage: "line.diagonal.arrow")
} }
Divider()
_options([tournament])
} }
} }
#if DEBUG #if DEBUG

@ -620,15 +620,12 @@ struct AddTeamView: View {
return 1 return 1
} }
@MainActor
private func handlePasteString(_ first: String) { private func handlePasteString(_ first: String) {
if first.isEmpty == false { if first.isEmpty == false {
DispatchQueue.main.async {
fetchPlayers.nsPredicate = SearchViewModel.pastePredicate(pasteField: first, mostRecentDate: SourceFileManager.shared.mostRecentDateAvailable, filterOption: _filterOption()) fetchPlayers.nsPredicate = SearchViewModel.pastePredicate(pasteField: first, mostRecentDate: SourceFileManager.shared.mostRecentDateAvailable, filterOption: _filterOption())
fetchPlayers.nsSortDescriptors = [NSSortDescriptor(keyPath: \ImportedPlayer.rank, ascending: true)] fetchPlayers.nsSortDescriptors = [NSSortDescriptor(keyPath: \ImportedPlayer.rank, ascending: true)]
autoSelect = true autoSelect = true
} }
}
pasteString = first pasteString = first
editableTextField = first editableTextField = first
textHeight = Self._calculateHeight(text: first) textHeight = Self._calculateHeight(text: first)

@ -141,17 +141,18 @@ struct RegistrationSetupView: View {
} }
Section { Section {
Toggle(isOn: $targetTeamCountEnabled) { // Toggle(isOn: $targetTeamCountEnabled) {
Text("Activer une limite") // Text("Activer une limite")
} // }
//
if targetTeamCountEnabled { // if targetTeamCountEnabled {
// StepperView(count: $targetTeamCount, minimum: 4)
// }
StepperView(count: $targetTeamCount, minimum: 4) StepperView(count: $targetTeamCount, minimum: 4)
}
} header: { } header: {
Text("Paires admises") Text("Paires admises")
} footer: { } footer: {
Text("Si une limite de paire existe, les inscriptions seront indiqués en attente pour les joueurs au-délà de cette limite dans le cas où aucune limite de liste d'attente n'est active ou non atteinte. Dans le cas contraire, plus aucune inscription ne seront possibles.") Text("Les inscriptions seront indiqués en attente pour les joueurs au-délà de cette limite dans le cas où aucune limite de liste d'attente n'est active ou non atteinte. Dans le cas contraire, plus aucune inscription ne seront possibles.")
} }
Section { Section {
@ -160,7 +161,7 @@ struct RegistrationSetupView: View {
} }
if waitingListLimitEnabled { if waitingListLimitEnabled {
StepperView(count: $waitingListLimit, minimum: 1) StepperView(count: $waitingListLimit, minimum: 0)
} }
} header: { } header: {
Text("Liste d'attente") Text("Liste d'attente")

@ -21,6 +21,10 @@ struct TournamentInscriptionView: View {
Text("Gestion des inscriptions") Text("Gestion des inscriptions")
if let closedRegistrationDate = tournament.closedRegistrationDate { if let closedRegistrationDate = tournament.closedRegistrationDate {
Text("clôturé le " + closedRegistrationDate.formatted(date: .abbreviated, time: .shortened)) Text("clôturé le " + closedRegistrationDate.formatted(date: .abbreviated, time: .shortened))
} else if tournament.enableOnlineRegistration {
Text("Inscription en ligne activée")
} else if tournament.onlineRegistrationCanBeEnabled() {
Text("Inscription en ligne désactivée")
} }
} }
} }

Loading…
Cancel
Save