parent
40fc73e6bf
commit
708e0aa481
@ -0,0 +1,637 @@ |
|||||||
|
// |
||||||
|
// TournamentLookUpView.swift |
||||||
|
// PadelClub |
||||||
|
// |
||||||
|
// Created by razmig on 08/09/2024. |
||||||
|
// |
||||||
|
|
||||||
|
import SwiftUI |
||||||
|
import CoreLocation |
||||||
|
import CoreLocationUI |
||||||
|
|
||||||
|
struct TournamentLookUpView: View { |
||||||
|
@Environment(FederalDataViewModel.self) var federalDataViewModel: FederalDataViewModel |
||||||
|
@StateObject var locationManager = LocationManager() |
||||||
|
@Environment(\.dismiss) private var dismiss |
||||||
|
|
||||||
|
@State private var searchField: String = "" |
||||||
|
@State private var sectionedTournaments: [String: [FederalTournament]] = [:] |
||||||
|
@State private var dayPeriod: DayPeriod = .all |
||||||
|
@State private var duration: Int = 3 |
||||||
|
|
||||||
|
@State var page: Int = 0 |
||||||
|
@State var total: Int = 0 |
||||||
|
|
||||||
|
@State private var tournamentCategories = Set<TournamentCategory.ID>() |
||||||
|
@State private var tournamentLevels = Set<TournamentLevel.ID>() |
||||||
|
@State private var tournamentAges = Set<FederalTournamentAge.ID>() |
||||||
|
@State private var tournamentTypes = Set<FederalTournamentType.ID>() |
||||||
|
@State private var searching: Bool = false |
||||||
|
@State private var startDate: Date = Date() |
||||||
|
@State private var endDate: Date = Calendar.current.date(byAdding: .month, value: 3, to: Date())! |
||||||
|
@AppStorage("lastCity") private var city: String = "" |
||||||
|
@State private var ligue: String = "" |
||||||
|
@AppStorage("lastDistance") private var distance: Double = 30 |
||||||
|
@AppStorage("lastSortingOption") private var sortingOption: String = "_DIST_" |
||||||
|
@State private var requestedToGetAllPages: Bool = false |
||||||
|
@AppStorage("lastNationalCup") private var nationalCup: Bool = false |
||||||
|
@State private var revealSearchParameters: Bool = true |
||||||
|
@State private var searchScope = FederalTournamentSearchScope.all |
||||||
|
|
||||||
|
var tournaments: [FederalTournament] { |
||||||
|
federalDataViewModel.searchedFederalTournaments |
||||||
|
} |
||||||
|
|
||||||
|
func canShowTournament(_ tournament: FederalTournament) -> Bool { |
||||||
|
guard tournament.dayDuration <= duration else { return false } |
||||||
|
guard (tournament.dayPeriod == dayPeriod && dayPeriod != .all) || dayPeriod == .all else { return false } |
||||||
|
if searchField.isEmpty { |
||||||
|
return true |
||||||
|
} else { |
||||||
|
return tournament.validForSearch(searchField, scope: searchScope) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
var body: some View { |
||||||
|
List { |
||||||
|
searchParametersView |
||||||
|
|
||||||
|
if tournaments.isEmpty == false && tournaments.count < total && total >= 200 && requestedToGetAllPages == false { |
||||||
|
Section { |
||||||
|
Text("Il y a beacoup de tournois pour cette requête, êtes-vous sûr de vouloir tout récupérer ? Sinon essayez d'affiner votre recherche.") |
||||||
|
Button { |
||||||
|
requestedToGetAllPages = true |
||||||
|
page += 1 |
||||||
|
searching = true |
||||||
|
Task { |
||||||
|
await getNewPage() |
||||||
|
searching = false |
||||||
|
buildSectionedData() |
||||||
|
} |
||||||
|
} label: { |
||||||
|
Label("Tout voir", systemImage: "arrow.down.circle") |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.toolbarBackground(.visible, for: .bottomBar, .navigationBar) |
||||||
|
.navigationTitle("Chercher un tournoi") |
||||||
|
.navigationBarTitleDisplayMode(.inline) |
||||||
|
.onChange(of: locationManager.city, perform: { newValue in |
||||||
|
if let newValue, city.isEmpty { |
||||||
|
city = newValue |
||||||
|
} |
||||||
|
}) |
||||||
|
.toolbarTitleDisplayMode(.large) |
||||||
|
.toolbar { |
||||||
|
ToolbarItem(placement: .bottomBar) { |
||||||
|
if revealSearchParameters { |
||||||
|
FooterButtonView("Lancer la recherche") { |
||||||
|
runSearch() |
||||||
|
} |
||||||
|
.disabled(searching) |
||||||
|
} else if searchField.isEmpty == false && searchScope != .all { |
||||||
|
let count = _totalVisibleEpreuves().count |
||||||
|
VStack { |
||||||
|
Text(searchField) |
||||||
|
.foregroundStyle(.secondary) |
||||||
|
Text(count.formatted() + " tournoi" + count.pluralSuffix) |
||||||
|
} |
||||||
|
.font(.caption) |
||||||
|
} else if searching { |
||||||
|
HStack(spacing: 20) { |
||||||
|
Spacer() |
||||||
|
ProgressView() |
||||||
|
if total > 0 { |
||||||
|
let percent = Double(tournaments.count) / Double(total) |
||||||
|
Text(percent.formatted(.percent.precision(.significantDigits(1...3))) + " en récupération de Tenup") |
||||||
|
.font(.caption) |
||||||
|
} |
||||||
|
Spacer() |
||||||
|
} |
||||||
|
} else { |
||||||
|
let count = _totalVisibleEpreuves().count |
||||||
|
Text(count.formatted() + " tournoi" + count.pluralSuffix) |
||||||
|
.font(.caption) |
||||||
|
} |
||||||
|
} |
||||||
|
ToolbarItem(placement: .topBarTrailing) { |
||||||
|
Menu { |
||||||
|
if tournaments.isEmpty == false { |
||||||
|
Section { |
||||||
|
let preview = SharePreview(Text("Ma recherche de tournois"), icon: Image("PadelClub_logo_fondclair_transparent")) |
||||||
|
ShareLink(item: renderedImage ?? Image(systemName: "photo"), preview: preview) { |
||||||
|
if renderedImage == nil { |
||||||
|
ProgressView() |
||||||
|
} else { |
||||||
|
Label("Par image (20max)", systemImage: "square.and.arrow.up") |
||||||
|
.labelStyle(.titleAndIcon) |
||||||
|
} |
||||||
|
} |
||||||
|
ShareLink(item: pastedTournaments) { |
||||||
|
Label("Par texte", systemImage: "square.and.arrow.up") |
||||||
|
.labelStyle(.titleAndIcon) |
||||||
|
} |
||||||
|
ShareLink(item: japList) { |
||||||
|
Label("JAP liste", systemImage: "square.and.arrow.up") |
||||||
|
.labelStyle(.titleAndIcon) |
||||||
|
} |
||||||
|
} header: { |
||||||
|
Text("Partager les résultats") |
||||||
|
} |
||||||
|
} |
||||||
|
Divider() |
||||||
|
Button { |
||||||
|
tournamentLevels = Set() |
||||||
|
tournamentCategories = Set() |
||||||
|
city = "" |
||||||
|
locationManager.location = nil |
||||||
|
locationManager.city = nil |
||||||
|
distance = 30 |
||||||
|
startDate = Date() |
||||||
|
endDate = Calendar.current.date(byAdding: .month, value: 3, to: Date())! |
||||||
|
sortingOption = "_DIST_" |
||||||
|
revealSearchParameters = true |
||||||
|
} label: { |
||||||
|
Text("Ré-initialiser la recherche") |
||||||
|
} |
||||||
|
} label: { |
||||||
|
Label("Options", systemImage: "ellipsis.circle") |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
var pastedTournaments: String { |
||||||
|
tournaments.map { $0.shareMessage }.joined() |
||||||
|
} |
||||||
|
|
||||||
|
var japList: String { |
||||||
|
Set(tournaments.map { $0.japMessage }).joined(separator: "\n") |
||||||
|
} |
||||||
|
|
||||||
|
private func isTypeLookedAfter(_ type: any TournamentBuildHolder) -> Bool { |
||||||
|
if levels.contains(where: { level in |
||||||
|
type.level == level |
||||||
|
}) || levels.isEmpty { |
||||||
|
if categories.contains(where: { category in |
||||||
|
type.category == category |
||||||
|
}) || categories.isEmpty { |
||||||
|
|
||||||
|
return true |
||||||
|
} |
||||||
|
} |
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Environment(\.displayScale) var displayScale |
||||||
|
@State private var renderedImage: Image? |
||||||
|
|
||||||
|
@MainActor |
||||||
|
func render() { |
||||||
|
let renderer = ImageRenderer(content: tournamentsView) |
||||||
|
renderer.scale = displayScale |
||||||
|
renderer.isOpaque = true |
||||||
|
if let uiImage = renderer.uiImage { |
||||||
|
renderedImage = Image(uiImage: uiImage) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@ViewBuilder |
||||||
|
private var tournamentsView: some View { |
||||||
|
let tournaments = tournaments.prefix(20) |
||||||
|
VStack { |
||||||
|
ForEach(tournaments.indices, id: \.self) { tournamentIndex in |
||||||
|
let tournament = tournaments[tournamentIndex] |
||||||
|
HStack(alignment: .center) { |
||||||
|
VStack(alignment: .leading) { |
||||||
|
Text(tournament.libelle ?? "unknown").font(.headline) |
||||||
|
if let club = tournament.nomClub { |
||||||
|
Text(club) |
||||||
|
.font(.footnote) |
||||||
|
.lineLimit(1) |
||||||
|
} |
||||||
|
} |
||||||
|
Spacer() |
||||||
|
VStack(alignment: .trailing) { |
||||||
|
if let startDate = tournament.dateDebut { |
||||||
|
Text(startDate.monthYearFormatted) |
||||||
|
HStack { |
||||||
|
Text(startDate.formatted(.dateTime.weekday())) |
||||||
|
Text(startDate.formatted(.dateTime.day())).font(.largeTitle) |
||||||
|
} |
||||||
|
} |
||||||
|
if let distance = tournament.distanceEnMetres { |
||||||
|
let measurement = Measurement(value: distance / 1000, unit: UnitLength.kilometers) |
||||||
|
Text(measurement.formatted()).font(.caption) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.padding() |
||||||
|
.foregroundColor(Color.black) |
||||||
|
.background { |
||||||
|
tournamentIndex%2 == 0 ? Color.mint : Color.cyan |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.padding() |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private var clubsFound: [String] { |
||||||
|
Set(tournaments.compactMap { $0.nomClub }).sorted() |
||||||
|
} |
||||||
|
|
||||||
|
private var liguesFound: [String] { |
||||||
|
Set(tournaments.compactMap { $0.nomLigue }).sorted() |
||||||
|
} |
||||||
|
|
||||||
|
private func runSearch() { |
||||||
|
revealSearchParameters = false |
||||||
|
total = 0 |
||||||
|
page = 0 |
||||||
|
federalDataViewModel.searchedFederalTournaments = [] |
||||||
|
searching = true |
||||||
|
requestedToGetAllPages = false |
||||||
|
renderedImage = nil |
||||||
|
federalDataViewModel.searchAttemptCount += 1 |
||||||
|
Task { |
||||||
|
await getNewPage() |
||||||
|
searching = false |
||||||
|
dismiss() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func buildSectionedData() { |
||||||
|
sectionedTournaments = FederalTournament.sectionedData(from: tournaments) |
||||||
|
} |
||||||
|
|
||||||
|
private var distanceLimit: Measurement<UnitLength> { |
||||||
|
distanceLimit(distance: distance) |
||||||
|
} |
||||||
|
|
||||||
|
private func distanceLimit(distance: Double) -> Measurement<UnitLength> { |
||||||
|
Measurement(value: distance, unit: .kilometers) |
||||||
|
} |
||||||
|
|
||||||
|
private var categories: [TournamentCategory] { |
||||||
|
tournamentCategories.compactMap { TournamentCategory(rawValue: $0) } |
||||||
|
} |
||||||
|
|
||||||
|
private var levels: [TournamentLevel] { |
||||||
|
tournamentLevels.compactMap { TournamentLevel(rawValue: $0) } |
||||||
|
} |
||||||
|
|
||||||
|
private var ages: [FederalTournamentAge] { |
||||||
|
tournamentAges.compactMap { FederalTournamentAge(rawValue: $0) } |
||||||
|
} |
||||||
|
|
||||||
|
private var types: [FederalTournamentType] { |
||||||
|
tournamentTypes.compactMap { FederalTournamentType(rawValue: $0) } |
||||||
|
} |
||||||
|
|
||||||
|
func getNewPage() async { |
||||||
|
do { |
||||||
|
if NetworkFederalService.shared.formId.isEmpty { |
||||||
|
await getNewBuildForm() |
||||||
|
} else { |
||||||
|
let commands = try await NetworkFederalService.shared.getAllFederalTournaments(sortingOption: sortingOption, page: page, startDate: startDate, endDate: endDate, city: city, distance: distance, categories: categories, levels: levels, lat: locationManager.location?.coordinate.latitude.formatted(.number.locale(Locale(identifier: "us"))), lng: locationManager.location?.coordinate.longitude.formatted(.number.locale(Locale(identifier: "us"))), ages: ages, types: types, nationalCup: nationalCup) |
||||||
|
let resultCommand = commands.first(where: { $0.results != nil }) |
||||||
|
if let newTournaments = resultCommand?.results?.items { |
||||||
|
newTournaments.forEach { ft in |
||||||
|
if tournaments.contains(where: { $0.id == ft.id }) == false { |
||||||
|
federalDataViewModel.searchedFederalTournaments.append(ft) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if let count = resultCommand?.results?.nb_results { |
||||||
|
print("count", count, total, tournaments.count, page) |
||||||
|
total = count |
||||||
|
|
||||||
|
if renderedImage == nil { |
||||||
|
render() |
||||||
|
} |
||||||
|
if tournaments.count < count && page < total / 30 { |
||||||
|
if total < 200 || requestedToGetAllPages { |
||||||
|
page += 1 |
||||||
|
await MainActor.run() { |
||||||
|
buildSectionedData() |
||||||
|
} |
||||||
|
await getNewPage() |
||||||
|
} |
||||||
|
} else { |
||||||
|
print("finished") |
||||||
|
} |
||||||
|
} else { |
||||||
|
print("total results not found") |
||||||
|
} |
||||||
|
} |
||||||
|
} catch { |
||||||
|
print("getNewPage", error) |
||||||
|
await getNewBuildForm() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func getNewBuildForm() async { |
||||||
|
do { |
||||||
|
try await NetworkFederalService.shared.getNewBuildForm() |
||||||
|
await getNewPage() |
||||||
|
} catch { |
||||||
|
print("getNewBuildForm", error) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@ViewBuilder |
||||||
|
var searchContollerView: some View { |
||||||
|
Section { |
||||||
|
Button { |
||||||
|
runSearch() |
||||||
|
} label: { |
||||||
|
HStack { |
||||||
|
Label("Chercher un tournoi", systemImage: "magnifyingglass") |
||||||
|
if searching { |
||||||
|
Spacer() |
||||||
|
ProgressView() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
Button { |
||||||
|
tournamentLevels = Set() |
||||||
|
tournamentCategories = Set() |
||||||
|
city = "" |
||||||
|
locationManager.location = nil |
||||||
|
locationManager.city = nil |
||||||
|
dayPeriod = .all |
||||||
|
duration = 3 |
||||||
|
distance = 30 |
||||||
|
startDate = Date() |
||||||
|
endDate = Calendar.current.date(byAdding: .month, value: 3, to: Date())! |
||||||
|
sortingOption = "_DIST_" |
||||||
|
revealSearchParameters = true |
||||||
|
} label: { |
||||||
|
Label("Ré-initialiser la recherche", systemImage: "xmark.circle") |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@ViewBuilder |
||||||
|
var searchParametersView: some View { |
||||||
|
Section { |
||||||
|
DatePicker("Début", selection: $startDate, displayedComponents: .date) |
||||||
|
DatePicker("Fin", selection: $endDate, displayedComponents: .date) |
||||||
|
|
||||||
|
Picker(selection: $duration) { |
||||||
|
Text("Aucune").tag(7) |
||||||
|
Text(1.formatted()).tag(1) |
||||||
|
Text(2.formatted()).tag(2) |
||||||
|
Text(3.formatted()).tag(3) |
||||||
|
} label: { |
||||||
|
Text("Durée max (en jours)") |
||||||
|
} |
||||||
|
|
||||||
|
Picker(selection: $dayPeriod) { |
||||||
|
Text("N'importe").tag(DayPeriod.all) |
||||||
|
Text("le weekend").tag(DayPeriod.weekend) |
||||||
|
Text("la semaine").tag(DayPeriod.week) |
||||||
|
} label: { |
||||||
|
Text("En semaine ou week-end") |
||||||
|
} |
||||||
|
|
||||||
|
HStack { |
||||||
|
TextField("Ville", text: $city) |
||||||
|
if let city = locationManager.city { |
||||||
|
Divider() |
||||||
|
Text(city).italic() |
||||||
|
} |
||||||
|
if locationManager.requestStarted { |
||||||
|
ProgressView() |
||||||
|
} else { |
||||||
|
LocationButton { |
||||||
|
locationManager.requestLocation() |
||||||
|
} |
||||||
|
.symbolVariant(.fill) |
||||||
|
.foregroundColor (Color.white) |
||||||
|
.cornerRadius (20) |
||||||
|
.font(.system(size: 12)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Picker(selection: $distance) { |
||||||
|
Text(distanceLimit(distance:30).formatted()).tag(30.0) |
||||||
|
Text(distanceLimit(distance:50).formatted()).tag(50.0) |
||||||
|
Text(distanceLimit(distance:60).formatted()).tag(60.0) |
||||||
|
Text(distanceLimit(distance:90).formatted()).tag(90.0) |
||||||
|
Text(distanceLimit(distance:150).formatted()).tag(150.0) |
||||||
|
Text(distanceLimit(distance:200).formatted()).tag(200.0) |
||||||
|
Text(distanceLimit(distance:400).formatted()).tag(400.0) |
||||||
|
Text("Aucune").tag(3000.0) |
||||||
|
} label: { |
||||||
|
Text("Distance max") |
||||||
|
} |
||||||
|
|
||||||
|
Picker(selection: $sortingOption) { |
||||||
|
Text("Distance").tag("_DIST_") |
||||||
|
Text("Date de début").tag("dateDebut+asc") |
||||||
|
Text("Date de fin").tag("dateFin+asc") |
||||||
|
} label: { |
||||||
|
Text("Trier par") |
||||||
|
} |
||||||
|
|
||||||
|
NavigationLink { |
||||||
|
List(TournamentCategory.allCases, selection: $tournamentCategories) { type in |
||||||
|
Text(type.localizedLabel()) |
||||||
|
} |
||||||
|
.navigationTitle("Catégories") |
||||||
|
.environment(\.editMode, Binding.constant(EditMode.active)) |
||||||
|
} label: { |
||||||
|
HStack { |
||||||
|
Text("Catégorie") |
||||||
|
Spacer() |
||||||
|
categoriesLabel |
||||||
|
.foregroundStyle(.secondary) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
NavigationLink { |
||||||
|
List(TournamentLevel.allCases, selection: $tournamentLevels) { type in |
||||||
|
Text(type.localizedLabel()) |
||||||
|
} |
||||||
|
.navigationTitle("Niveaux") |
||||||
|
.environment(\.editMode, Binding.constant(EditMode.active)) |
||||||
|
} label: { |
||||||
|
HStack { |
||||||
|
Text("Niveau") |
||||||
|
Spacer() |
||||||
|
levelsLabel |
||||||
|
.foregroundStyle(.secondary) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
NavigationLink { |
||||||
|
List(FederalTournamentAge.allCases, selection: $tournamentAges) { type in |
||||||
|
Text(type.localizedLabel()) |
||||||
|
} |
||||||
|
.navigationTitle("Limites d'âge") |
||||||
|
.environment(\.editMode, Binding.constant(EditMode.active)) |
||||||
|
} label: { |
||||||
|
HStack { |
||||||
|
Text("Limite d'âge") |
||||||
|
Spacer() |
||||||
|
if tournamentAges.isEmpty || tournamentAges.count == FederalTournamentAge.allCases.count { |
||||||
|
Text("Tous les âges") |
||||||
|
.foregroundStyle(.secondary) |
||||||
|
} else { |
||||||
|
Text(ages.map({ $0.localizedLabel()}).joined(separator: ", ")) |
||||||
|
.foregroundStyle(.secondary) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
NavigationLink { |
||||||
|
List(FederalTournamentType.allCases, selection: $tournamentTypes) { type in |
||||||
|
Text(type.localizedLabel()) |
||||||
|
} |
||||||
|
.navigationTitle("Types de tournoi") |
||||||
|
.environment(\.editMode, Binding.constant(EditMode.active)) |
||||||
|
} label: { |
||||||
|
HStack { |
||||||
|
Text("Type de tournoi") |
||||||
|
Spacer() |
||||||
|
if tournamentTypes.isEmpty || tournamentTypes.count == FederalTournamentType.allCases.count { |
||||||
|
Text("Tous les types") |
||||||
|
.foregroundStyle(.secondary) |
||||||
|
} else { |
||||||
|
Text(types.map({ $0.localizedLabel()}).joined(separator: ", ")) |
||||||
|
.foregroundStyle(.secondary) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Picker(selection: $nationalCup) { |
||||||
|
Text("N'importe").tag(false) |
||||||
|
Text("Uniquement").tag(true) |
||||||
|
} label: { |
||||||
|
Text("Circuit National Padel Cup") |
||||||
|
} |
||||||
|
} header: { |
||||||
|
Text("Critères de recherche") |
||||||
|
} |
||||||
|
.headerProminence(.increased) |
||||||
|
.disabled(searching) |
||||||
|
} |
||||||
|
|
||||||
|
var categoriesLabel: some View { |
||||||
|
if tournamentCategories.isEmpty || tournamentCategories.count == TournamentCategory.allCases.count { |
||||||
|
Text("Toutes les catégories") |
||||||
|
} else { |
||||||
|
Text(categories.map({ $0.localizedLabel() }).joined(separator: ", ")) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
var levelsLabel: some View { |
||||||
|
if tournamentLevels.isEmpty || tournamentLevels.count == TournamentLevel.allCases.count { |
||||||
|
Text("Tous les niveaux") |
||||||
|
} else { |
||||||
|
Text(levels.map({ $0.localizedLabel() }).joined(separator: ", ")) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@ViewBuilder |
||||||
|
var searchParametersSummaryView: some View { |
||||||
|
VStack(alignment: .leading) { |
||||||
|
HStack { |
||||||
|
Text("Lieu") |
||||||
|
Spacer() |
||||||
|
Text(city) |
||||||
|
if distance >= 3000 { |
||||||
|
Text("sans limite de distance") |
||||||
|
} else { |
||||||
|
Text("à moins de " + distanceLimit.formatted()) |
||||||
|
} |
||||||
|
} |
||||||
|
HStack { |
||||||
|
Text("Période") |
||||||
|
Spacer() |
||||||
|
Text("Du") |
||||||
|
Text(startDate.twoDigitsYearFormatted) |
||||||
|
Text("Au") |
||||||
|
Text(endDate.twoDigitsYearFormatted) |
||||||
|
} |
||||||
|
HStack { |
||||||
|
Text("Niveau") |
||||||
|
Spacer() |
||||||
|
levelsLabel |
||||||
|
} |
||||||
|
HStack { |
||||||
|
Text("Catégorie") |
||||||
|
Spacer() |
||||||
|
categoriesLabel |
||||||
|
} |
||||||
|
|
||||||
|
HStack { |
||||||
|
Text("Tri") |
||||||
|
Spacer() |
||||||
|
Text(sortingOptionLabel) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
var sortingOptionLabel: String { |
||||||
|
switch sortingOption { |
||||||
|
case "_DIST_": return "Distance" |
||||||
|
case "dateDebut+asc": return "Date de début" |
||||||
|
case "dateFin+asc": return "Date de fin" |
||||||
|
default: |
||||||
|
return "Distance" |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
func _totalVisibleTournaments(_ date: Date? = nil) -> [FederalTournament] { |
||||||
|
if let date { |
||||||
|
if let tournaments = sectionedTournaments[URL.importDateFormatter.string(from: date)] { |
||||||
|
let allTournaments = tournaments.filter({ canShowTournament($0) }).filter({ tournament in |
||||||
|
if tournament.tournaments.count > 1 { |
||||||
|
return tournament.tournaments.anySatisfy { isTypeLookedAfter($0) } |
||||||
|
} else { |
||||||
|
return true |
||||||
|
} |
||||||
|
}) |
||||||
|
return allTournaments |
||||||
|
} else { |
||||||
|
return [] |
||||||
|
} |
||||||
|
} else { |
||||||
|
let allTournaments = sectionedTournaments.values.flatMap({ $0 }).filter({ canShowTournament($0) }).filter({ tournament in |
||||||
|
if tournament.tournaments.count > 1 { |
||||||
|
return tournament.tournaments.anySatisfy { isTypeLookedAfter($0) } |
||||||
|
} else { |
||||||
|
return true |
||||||
|
} |
||||||
|
}) |
||||||
|
return allTournaments |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func _totalVisibleEpreuves(_ date: Date? = nil) -> [any TournamentBuildHolder] { |
||||||
|
if let date { |
||||||
|
if let tournaments = sectionedTournaments[URL.importDateFormatter.string(from: date)] { |
||||||
|
let allTournaments = tournaments |
||||||
|
.filter({ canShowTournament($0) }) |
||||||
|
.compactMap({ $0.tournaments }) |
||||||
|
.flatMap({ $0 }) |
||||||
|
.filter({ isTypeLookedAfter($0) }) |
||||||
|
return allTournaments |
||||||
|
} else { |
||||||
|
return [] |
||||||
|
} |
||||||
|
} else { |
||||||
|
let allTournaments = sectionedTournaments.values.flatMap({ $0 }) |
||||||
|
.filter({ canShowTournament($0) }) |
||||||
|
.compactMap({ $0.tournaments }) |
||||||
|
.flatMap({ $0 }) |
||||||
|
.filter({ isTypeLookedAfter($0) }) |
||||||
|
return allTournaments |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue