fix search
fix import file
fix padding
club_update
Raz 1 year ago
parent 6dfa2c8236
commit 0f6e41773c
  1. 4
      PadelClub.xcodeproj/project.pbxproj
  2. 7
      PadelClub/Data/Tournament.swift
  3. 28
      PadelClub/Utils/FileImportManager.swift
  4. 48
      PadelClub/Utils/PadelRule.swift
  5. 6
      PadelClub/ViewModel/SearchViewModel.swift
  6. 6
      PadelClub/Views/Club/ClubSearchView.swift
  7. 2
      PadelClub/Views/Club/ClubsView.swift
  8. 11
      PadelClub/Views/Navigation/Agenda/ActivityView.swift
  9. 1
      PadelClub/Views/Planning/CourtAvailabilitySettingsView.swift
  10. 1
      PadelClub/Views/Planning/PlanningView.swift
  11. 10
      PadelClub/Views/Shared/SelectablePlayerListView.swift
  12. 49
      PadelClub/Views/Tournament/FileImportView.swift
  13. 5
      PadelClub/Views/Tournament/Screen/AddTeamView.swift
  14. 4
      PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift

@ -1935,7 +1935,7 @@
CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 99;
CURRENT_PROJECT_VERSION = 103;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
@ -1985,7 +1985,7 @@
CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 99;
CURRENT_PROJECT_VERSION = 103;
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
DEVELOPMENT_TEAM = BQ3Y44M3Q6;

@ -1368,7 +1368,12 @@ defer {
if tournamentLevel == .unlisted, displayStyle == .title, let name {
return name
}
return [tournamentLevel.localizedLabel(displayStyle) + " " + tournamentCategory.localizedLabel(), displayStyle == .wide ? name : nil].compactMap({ $0 }).joined(separator: " - ")
let title: String = [tournamentLevel.localizedLabel(displayStyle), tournamentCategory.localizedLabel(displayStyle), federalTournamentAge.localizedLabel(displayStyle)].joined(separator: " ")
if displayStyle == .wide, let name {
return [title, name].joined(separator: " - ")
} else {
return title
}
}
func localizedTournamentType() -> String {

@ -101,13 +101,15 @@ class FileImportManager {
let players: Set<PlayerRegistration>
let weight: Int
let tournamentCategory: TournamentCategory
let tournamentAgeCategory: FederalTournamentAge
let previousTeam: TeamRegistration?
var registrationDate: Date? = nil
var name: String? = nil
init(players: [PlayerRegistration], tournamentCategory: TournamentCategory, previousTeam: TeamRegistration?, registrationDate: Date? = nil, name: String? = nil, tournament: Tournament) {
init(players: [PlayerRegistration], tournamentCategory: TournamentCategory, tournamentAgeCategory: FederalTournamentAge, previousTeam: TeamRegistration?, registrationDate: Date? = nil, name: String? = nil, tournament: Tournament) {
self.players = Set(players)
self.tournamentCategory = tournamentCategory
self.tournamentAgeCategory = tournamentAgeCategory
self.name = name
self.previousTeam = previousTeam
if players.count < 2 {
@ -247,6 +249,11 @@ class FileImportManager {
}
}
let ageCategory = dataOne[1]
var tournamentAgeCategory: FederalTournamentAge {
FederalTournamentAge.allCases.first(where: { $0.importingRawValue.canonicalVersion == ageCategory.canonicalVersion }) ?? .senior
}
let resultOne = Array(dataOne.dropFirst(3).dropLast())
let resultTwo = Array(dataTwo.dropFirst(3).dropLast())
let sexUnknown: Bool = (resultOne.last?.hasPrefix(FileImportManager.FFT_ASSIMILATION_WOMAN_IN_MAN) == true) || (resultTwo.last?.hasPrefix(FileImportManager.FFT_ASSIMILATION_WOMAN_IN_MAN) == true)
@ -268,7 +275,7 @@ class FileImportManager {
case .mix: return 1
}
}
if tournamentCategory == tournament.tournamentCategory || checkingCategoryDisabled {
if (tournamentCategory == tournament.tournamentCategory && tournamentAgeCategory == tournament.federalTournamentAge) || checkingCategoryDisabled {
let playerOne = PlayerRegistration(federalData: Array(resultOne[0...7]), sex: sexPlayerOne, sexUnknown: sexUnknown)
playerOne?.setComputedRank(in: tournament)
let playerTwo = PlayerRegistration(federalData: Array(resultTwo[0...7]), sex: sexPlayerTwo, sexUnknown: sexUnknown)
@ -276,7 +283,7 @@ class FileImportManager {
let players = [playerOne, playerTwo].compactMap({ $0 })
if players.isEmpty == false {
let team = TeamHolder(players: players, tournamentCategory: tournamentCategory, previousTeam: tournament.findTeam(players), tournament: tournament)
let team = TeamHolder(players: players, tournamentCategory: tournamentCategory, tournamentAgeCategory: tournamentAgeCategory, previousTeam: tournament.findTeam(players), tournament: tournament)
results.append(team)
}
}
@ -302,7 +309,14 @@ class FileImportManager {
return .men
}
}
if tournamentCategory == tournament.tournamentCategory || checkingCategoryDisabled {
let ageCategory = data[1]
var tournamentAgeCategory: FederalTournamentAge {
FederalTournamentAge.allCases.first(where: { $0.importingRawValue.canonicalVersion == ageCategory.canonicalVersion }) ?? .senior
}
if (tournamentCategory == tournament.tournamentCategory && tournamentAgeCategory == tournament.federalTournamentAge) || checkingCategoryDisabled {
let result = Array(data.dropFirst(3).dropLast())
var sexPlayerOne : Int {
@ -330,7 +344,7 @@ class FileImportManager {
let players = [playerOne, playerTwo].compactMap({ $0 })
if players.isEmpty == false {
let team = TeamHolder(players: players, tournamentCategory: tournamentCategory, previousTeam: tournament.findTeam(players), tournament: tournament)
let team = TeamHolder(players: players, tournamentCategory: tournamentCategory, tournamentAgeCategory: tournamentAgeCategory, previousTeam: tournament.findTeam(players), tournament: tournament)
results.append(team)
}
}
@ -378,7 +392,7 @@ class FileImportManager {
return nil
}
let team = TeamHolder(players: registeredPlayers, tournamentCategory: tournament.tournamentCategory, previousTeam: tournament.findTeam(registeredPlayers), registrationDate: registrationDate, tournament: tournament)
let team = TeamHolder(players: registeredPlayers, tournamentCategory: tournament.tournamentCategory, tournamentAgeCategory: tournament.federalTournamentAge, previousTeam: tournament.findTeam(registeredPlayers), registrationDate: registrationDate, tournament: tournament)
results.append(team)
}
}
@ -412,7 +426,7 @@ class FileImportManager {
return player
}
return TeamHolder(players: players, tournamentCategory: .men, previousTeam: nil, name: teamName, tournament: tournament)
return TeamHolder(players: players, tournamentCategory: .men, tournamentAgeCategory: .senior, previousTeam: nil, name: teamName, tournament: tournament)
}
return results
}

@ -170,6 +170,27 @@ enum FederalTournamentAge: Int, Hashable, Codable, CaseIterable, Identifiable {
self.init(rawValue: value)
}
var importingRawValue: String {
switch self {
case .unlisted:
return "Senior"
case .a11_12:
return "11/12 ans"
case .a13_14:
return "13/14 ans"
case .a15_16:
return "15/16 ans"
case .a17_18:
return "17/18 ans"
case .senior:
return "Senior"
case .a45:
return "45 ans"
case .a55:
return "55 ans"
}
}
static func mostRecent(inTournaments tournaments: [Tournament]) -> Self {
return tournaments.first?.federalTournamentAge ?? .senior
}
@ -777,11 +798,32 @@ enum TournamentCategory: Int, Hashable, Codable, CaseIterable, Identifiable {
case .unlisted:
return displayStyle == .title ? "Aucune" : ""
case .men:
return displayStyle != .short ? "Hommes" : "H"
switch displayStyle {
case .title:
return "DH"
case .wide:
return "Hommes"
case .short:
return "H"
}
case .women:
return displayStyle != .short ? "Dames" : "D"
switch displayStyle {
case .title:
return "DD"
case .wide:
return "Dames"
case .short:
return "D"
}
case .mix:
return displayStyle != .short ? "Mixte" : "MX"
switch displayStyle {
case .title:
return "MX"
case .wide:
return "Mixte"
case .short:
return "MX"
}
}
}

@ -128,7 +128,7 @@ class SearchViewModel: ObservableObject, Identifiable {
}
func words() -> [String] {
return searchText.canonicalVersion.trimmed.components(separatedBy: .whitespaces)
return searchText.canonicalVersionWithPunctuation.trimmed.components(separatedBy: .whitespaces)
}
func wordsPredicates() -> NSPredicate? {
@ -159,6 +159,10 @@ class SearchViewModel: ObservableObject, Identifiable {
predicates.append(NSPredicate(format: "license contains[cd] %@", canonicalVersionWithoutPunctuation))
}
predicates.append(NSPredicate(format: "canonicalFullName contains[cd] %@", canonicalVersionWithoutPunctuation))
let components = canonicalVersionWithoutPunctuation.split(separator: " ").sorted()
let pattern = components.joined(separator: ".*")
let predicate = NSPredicate(format: "canonicalFullName MATCHES[c] %@", pattern)
predicates.append(predicate)
}
case .ligue:
if canonicalVersionWithoutPunctuation.isEmpty {

@ -140,6 +140,7 @@ struct ClubSearchView: View {
RowButtonView("D'accord") {
locationManager.lastError = nil
}
.padding(.horizontal)
}
} else if clubMarkers.isEmpty == false && searching == false && _filteredClubs().isEmpty {
ContentUnavailableView.search(text: searchedCity)
@ -171,6 +172,7 @@ struct ClubSearchView: View {
locationManager.requestLocation()
}
}
.padding(.horizontal)
}
if error != nil {
@ -182,11 +184,13 @@ struct ClubSearchView: View {
RowButtonView("Chercher une ville ou un code postal") {
searchPresented = true
}
.padding(.horizontal)
if searchAttempted {
RowButtonView("Créer un club manuellement") {
newClub = club ?? Club.newEmptyInstance()
}
.padding(.horizontal)
}
}
}

@ -159,9 +159,11 @@ struct ClubsView: View {
RowButtonView("Créer un nouveau club", systemImage: "plus.circle.fill") {
newClub = Club.newEmptyInstance()
}
.padding(.horizontal)
RowButtonView("Chercher un club", systemImage: "magnifyingglass.circle.fill") {
presentClubSearchView = true
}
.padding(.horizontal)
}
}

@ -109,15 +109,14 @@ struct ActivityView: View {
RowButtonView("D'accord.") {
self.error = nil
}
.padding(.horizontal)
}
.padding()
} else if isGatheringFederalTournaments {
ProgressView()
} else {
if tournaments.isEmpty && viewStyle == .list {
if searchText.isEmpty == false {
ContentUnavailableView.search(text: searchText)
.padding()
} else if federalDataViewModel.areFiltersEnabled() {
ContentUnavailableView {
Text("Aucun résultat")
@ -127,11 +126,10 @@ struct ActivityView: View {
RowButtonView("supprimer le filtre") {
federalDataViewModel.removeFilters()
}
.padding(.horizontal)
}
.padding()
} else {
_dataEmptyView()
.padding()
}
}
}
@ -320,10 +318,13 @@ struct ActivityView: View {
RowButtonView("Créer un nouvel événement") {
newTournament = Tournament.newEmptyInstance()
}
.padding(.horizontal)
RowButtonView("Importer via Tenup") {
navigation.agendaDestination = .tenup
}
.padding(.horizontal)
SupportButtonView(contentIsUnavailable: true)
.padding(.horizontal)
}
}
@ -345,6 +346,7 @@ struct ActivityView: View {
RowButtonView("Choisir mes clubs") {
presentClubSearchView = true
}
.padding()
}
} else {
ContentUnavailableView {
@ -356,6 +358,7 @@ struct ActivityView: View {
NetworkFederalService.shared.formId = ""
_gatherFederalTournaments()
}
.padding()
}
}
}

@ -114,6 +114,7 @@ struct CourtAvailabilitySettingsView: View {
endDate = tournament.startDate.addingTimeInterval(5400)
showingPopover = true
}
.padding(.horizontal)
}
}
}

@ -79,6 +79,7 @@ struct PlanningView: View {
RowButtonView("Horaire intelligent") {
selectedScheduleDestination = nil
}
.padding(.horizontal)
}
}
}

@ -436,17 +436,15 @@ struct MySearchView: View {
Text(searchViewModel.contentUnavailableMessage)
} actions: {
Button {
RowButtonView("Lancer une nouvelle recherche") {
searchViewModel.debouncableText = ""
} label: {
Text("lancer une nouvelle recherche")
}
.padding()
if let contentUnavailableAction {
Button {
RowButtonView("Créer \(searchViewModel.searchText)") {
contentUnavailableAction(searchViewModel)
} label: {
Text("créer \(searchViewModel.searchText)")
}
.padding()
}
}
}

@ -90,7 +90,7 @@ struct FileImportView: View {
}
private func filteredTeams(tournament: Tournament) -> [FileImportManager.TeamHolder] {
return teams.filter { $0.tournamentCategory == tournament.tournamentCategory }.sorted(by: \.weight)
return teams.filter { $0.tournamentCategory == tournament.tournamentCategory && $0.tournamentAgeCategory == tournament.federalTournamentAge }.sorted(by: \.weight)
}
private func _deleteTeams() async {
@ -149,7 +149,7 @@ struct FileImportView: View {
}
}
if let event = tournament.eventObject(), event.tenupId != nil, event.tournaments.count > 1, fileProvider == .frenchFederation {
if let event = tournament.eventObject(), event.tournaments.count > 1, fileProvider == .frenchFederation {
Section {
RowButtonView("Importer pour tous les tournois") {
multiImport = true
@ -230,7 +230,7 @@ struct FileImportView: View {
if filteredTeams.isEmpty && teams.isEmpty == false && multiImport == false {
@Bindable var tournament = tournament
Section {
Text("Aucune équipe \(tournament.tournamentCategory.importingRawValue) détectée mais \(teams.count) équipes sont dans le fichier")
Text("Aucune équipe \(tournament.tournamentCategory.importingRawValue) \(tournament.federalAgeCategory.importingRawValue) détectée mais \(teams.count) équipes sont dans le fichier")
Picker(selection: $tournament.tournamentCategory) {
ForEach([TournamentCategory.men, TournamentCategory.women, TournamentCategory.mix]) { category in
Text(category.importingRawValue).tag(category)
@ -250,6 +250,26 @@ struct FileImportView: View {
}
}
}
Picker(selection: $tournament.federalTournamentAge) {
ForEach(FederalTournamentAge.allCases) { ageCategory in
Text(ageCategory.importingRawValue).tag(ageCategory)
}
} label: {
Text("Modifier la catégorie d'âge")
}
.onChange(of: tournament.federalTournamentAge) {
_save()
Task {
if let fileContent {
do {
try await _startImport(fileContent: fileContent)
} catch {
errorMessage = error.localizedDescription
}
}
}
}
}
} else if teams.isEmpty && didImport == true {
Section {
@ -285,7 +305,7 @@ struct FileImportView: View {
LabeledContent {
Text(_filteredTeams.count.formatted())
} label: {
Text("Équipe\(_filteredTeams.count.pluralSuffix) \(tournament.tournamentCategory.importingRawValue) détectée\(_filteredTeams.count.pluralSuffix)")
Text("Équipe\(_filteredTeams.count.pluralSuffix) \(tournament.tournamentCategory.importingRawValue) \(tournament.federalTournamentAge.importingRawValue) détectée\(_filteredTeams.count.pluralSuffix)")
}
} footer: {
if previousTeams.isEmpty == false {
@ -444,6 +464,16 @@ struct FileImportView: View {
}
}
struct CombinedCategory: Identifiable, Hashable {
let tournamentCategory: TournamentCategory
let federalTournamentAge: FederalTournamentAge
var id: String {
return tournamentCategory.importingRawValue + federalTournamentAge.importingRawValue
}
}
private func _startImport(fileContent: String) async throws {
await MainActor.run {
errorMessage = nil
@ -454,15 +484,16 @@ struct FileImportView: View {
}
let event: Event? = tournament.eventObject()
if let event, event.tenupId != nil {
var categoriesDone: [TournamentCategory] = []
if let event, event.tournaments.count > 1 {
var categoriesDone: [CombinedCategory] = []
for someTournament in event.tournaments {
if categoriesDone.contains(someTournament.tournamentCategory) == false {
let combinedCategory = CombinedCategory(tournamentCategory: someTournament.tournamentCategory, federalTournamentAge: someTournament.federalTournamentAge)
if categoriesDone.contains(combinedCategory) == false {
let _teams = try await FileImportManager.shared.createTeams(from: fileContent, tournament: someTournament, fileProvider: fileProvider, checkingCategoryDisabled: false)
self.teams += _teams
categoriesDone.append(someTournament.tournamentCategory)
categoriesDone.append(combinedCategory)
} else {
errorMessage = "Attention, l'événement possède plusieurs tournois d'une même catégorie (homme, femme, mixte), Padel Club ne peut savoir quelle équipe appartient à quel tournoi."
errorMessage = "Attention, l'événement possède plusieurs tournois d'une même catégorie / âge, Padel Club ne peut savoir quelle équipe appartient à quel tournoi."
}
}
} else {

@ -215,6 +215,11 @@ struct AddTeamView: View {
orPredicates = nameComponents.map { NSPredicate(format: "firstName contains[cd] %@ OR lastName contains[cd] %@", $0,$0) }
}
let components = text.split(separator: " ").sorted()
let pattern = components.joined(separator: ".*")
let canonicalFullNamePredicate = NSPredicate(format: "canonicalFullName MATCHES[c] %@", pattern)
orPredicates.append(canonicalFullNamePredicate)
let matches = text.licencesFound()
let licensesPredicates = matches.map { NSPredicate(format: "license contains[cd] %@", $0) }
orPredicates = orPredicates + licensesPredicates

@ -224,10 +224,12 @@ struct InscriptionManagerView: View {
RowButtonView("Ajouter une équipe") {
presentAddTeamView = true
}
.padding(.horizontal)
RowButtonView("Importer un fichier") {
presentImportView = true
}
.padding(.horizontal)
}
.padding()
}

Loading…
Cancel
Save