parent
59df5a2dd4
commit
de41de7418
@ -0,0 +1,104 @@ |
|||||||
|
// |
||||||
|
// FederalDataViewModel.swift |
||||||
|
// PadelClub |
||||||
|
// |
||||||
|
// Created by Razmig Sarkissian on 30/04/2024. |
||||||
|
// |
||||||
|
|
||||||
|
import SwiftUI |
||||||
|
import LeStorage |
||||||
|
|
||||||
|
@Observable |
||||||
|
class FederalDataViewModel { |
||||||
|
static let shared = FederalDataViewModel() |
||||||
|
|
||||||
|
var federalTournaments: [FederalTournament] = [] |
||||||
|
var levels: Set<TournamentLevel> = Set() |
||||||
|
var categories: Set<TournamentCategory> = Set() |
||||||
|
var ageCategories: Set<FederalTournamentAge> = Set() |
||||||
|
var selectedClubs: Set<String> = Set() |
||||||
|
var id: UUID = UUID() |
||||||
|
|
||||||
|
func filterStatus() -> String { |
||||||
|
var labels: [String] = [] |
||||||
|
labels.append(contentsOf: levels.map { $0.localizedLabel() }) |
||||||
|
labels.append(contentsOf: categories.map { $0.localizedLabel() }) |
||||||
|
labels.append(contentsOf: ageCategories.map { $0.localizedLabel() }) |
||||||
|
let clubNames = selectedClubs.compactMap { codeClub in |
||||||
|
let club: Club? = Store.main.filter(isIncluded: { $0.code == codeClub }).first |
||||||
|
return club?.clubTitle(.short) |
||||||
|
} |
||||||
|
|
||||||
|
labels.append(contentsOf: clubNames) |
||||||
|
return labels.joined(separator: ", ") |
||||||
|
} |
||||||
|
|
||||||
|
func selectedClub() -> Club? { |
||||||
|
if selectedClubs.isEmpty == false { |
||||||
|
return Store.main.filter(isIncluded: { $0.code == selectedClubs.first! }).first |
||||||
|
} else { |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func removeFilters() { |
||||||
|
levels.removeAll() |
||||||
|
categories.removeAll() |
||||||
|
ageCategories.removeAll() |
||||||
|
selectedClubs.removeAll() |
||||||
|
id = UUID() |
||||||
|
} |
||||||
|
|
||||||
|
func areFiltersEnabled() -> Bool { |
||||||
|
(levels.isEmpty && categories.isEmpty && ageCategories.isEmpty && selectedClubs.isEmpty) == false |
||||||
|
} |
||||||
|
|
||||||
|
var filteredFederalTournaments: [FederalTournament] { |
||||||
|
federalTournaments.filter({ tournament in |
||||||
|
(levels.isEmpty || tournament.tournaments.anySatisfy({ levels.contains($0.level) })) |
||||||
|
&& |
||||||
|
(categories.isEmpty || tournament.tournaments.anySatisfy({ categories.contains($0.category) })) |
||||||
|
&& |
||||||
|
(ageCategories.isEmpty || tournament.tournaments.anySatisfy({ ageCategories.contains($0.age) })) |
||||||
|
&& |
||||||
|
(selectedClubs.isEmpty || selectedClubs.contains(tournament.codeClub!)) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
func isTournamentValidForFilters(_ tournament: Tournament) -> Bool { |
||||||
|
let firstPart = (levels.isEmpty || levels.contains(tournament.level)) |
||||||
|
&& |
||||||
|
(categories.isEmpty || categories.contains(tournament.category)) |
||||||
|
&& |
||||||
|
(ageCategories.isEmpty || ageCategories.contains(tournament.age)) |
||||||
|
|
||||||
|
if let codeClub = tournament.club()?.code { |
||||||
|
return firstPart && (selectedClubs.isEmpty || selectedClubs.contains(codeClub)) |
||||||
|
} else { |
||||||
|
return firstPart |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func isFederalTournamentValidForFilters(_ tournament: FederalTournament, build: any TournamentBuildHolder) -> Bool { |
||||||
|
(levels.isEmpty || levels.contains(build.level)) |
||||||
|
&& |
||||||
|
(categories.isEmpty || categories.contains(build.category)) |
||||||
|
&& |
||||||
|
(ageCategories.isEmpty || ageCategories.contains(build.age)) |
||||||
|
&& |
||||||
|
(selectedClubs.isEmpty || selectedClubs.contains(tournament.codeClub!)) |
||||||
|
} |
||||||
|
|
||||||
|
func gatherTournaments(clubs: [Club], startDate: Date, endDate: Date? = nil) async throws { |
||||||
|
try await clubs.filter { $0.code != nil }.concurrentForEach { club in |
||||||
|
let newTournaments = try await NetworkFederalService.shared.getClubFederalTournaments(page: 0, tournaments: [], club: club.name, codeClub: club.code!, startDate: startDate, endDate: endDate) |
||||||
|
|
||||||
|
newTournaments.forEach { tournament in |
||||||
|
if self.federalTournaments.contains(where: { $0.id == tournament.id }) == false { |
||||||
|
self.federalTournaments.append(tournament) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
@ -0,0 +1,147 @@ |
|||||||
|
// |
||||||
|
// TournamentFilterView.swift |
||||||
|
// PadelClub |
||||||
|
// |
||||||
|
// Created by Razmig Sarkissian on 29/04/2024. |
||||||
|
// |
||||||
|
|
||||||
|
import SwiftUI |
||||||
|
|
||||||
|
struct TournamentFilterView: View { |
||||||
|
@EnvironmentObject var dataStore: DataStore |
||||||
|
@Environment(\.dismiss) private var dismiss |
||||||
|
@State private var levels: Set<TournamentLevel> |
||||||
|
@State private var categories: Set<TournamentCategory> |
||||||
|
@State private var ageCategories: Set<FederalTournamentAge> |
||||||
|
@State private var selectedClubs: Set<String> |
||||||
|
var federalDataViewModel: FederalDataViewModel |
||||||
|
|
||||||
|
init(federalDataViewModel: FederalDataViewModel) { |
||||||
|
self.federalDataViewModel = federalDataViewModel |
||||||
|
_levels = State(wrappedValue: federalDataViewModel.levels) |
||||||
|
_categories = State(wrappedValue: federalDataViewModel.categories) |
||||||
|
_ageCategories = State(wrappedValue: federalDataViewModel.ageCategories) |
||||||
|
_selectedClubs = State(wrappedValue: federalDataViewModel.selectedClubs) |
||||||
|
} |
||||||
|
|
||||||
|
var body: some View { |
||||||
|
NavigationView { |
||||||
|
Form { |
||||||
|
Section { |
||||||
|
ForEach(dataStore.clubs.filter({ $0.code != nil })) { club in |
||||||
|
LabeledContent { |
||||||
|
Button { |
||||||
|
if selectedClubs.contains(club.code!) { |
||||||
|
selectedClubs.remove(club.code!) |
||||||
|
} else { |
||||||
|
selectedClubs.insert(club.code!) |
||||||
|
} |
||||||
|
} label: { |
||||||
|
if selectedClubs.contains(club.code!) { |
||||||
|
Image(systemName: "checkmark.circle.fill") |
||||||
|
} |
||||||
|
} |
||||||
|
} label: { |
||||||
|
Text(club.clubTitle()) |
||||||
|
} |
||||||
|
} |
||||||
|
} header: { |
||||||
|
Text("Clubs") |
||||||
|
} |
||||||
|
Section { |
||||||
|
ForEach(TournamentLevel.allCases) { level in |
||||||
|
LabeledContent { |
||||||
|
Button { |
||||||
|
if levels.contains(level) { |
||||||
|
levels.remove(level) |
||||||
|
} else { |
||||||
|
levels.insert(level) |
||||||
|
} |
||||||
|
} label: { |
||||||
|
if levels.contains(level) { |
||||||
|
Image(systemName: "checkmark.circle.fill") |
||||||
|
} |
||||||
|
} |
||||||
|
} label: { |
||||||
|
Text(level.localizedLabel()) |
||||||
|
} |
||||||
|
} |
||||||
|
} header: { |
||||||
|
Text("Niveaux") |
||||||
|
} |
||||||
|
|
||||||
|
Section { |
||||||
|
ForEach(TournamentCategory.allCases) { category in |
||||||
|
LabeledContent { |
||||||
|
Button { |
||||||
|
if categories.contains(category) { |
||||||
|
categories.remove(category) |
||||||
|
} else { |
||||||
|
categories.insert(category) |
||||||
|
} |
||||||
|
} label: { |
||||||
|
if categories.contains(category) { |
||||||
|
Image(systemName: "checkmark.circle.fill") |
||||||
|
} |
||||||
|
} |
||||||
|
} label: { |
||||||
|
Text(category.localizedLabel()) |
||||||
|
} |
||||||
|
} |
||||||
|
} header: { |
||||||
|
Text("Catégories") |
||||||
|
} |
||||||
|
|
||||||
|
Section { |
||||||
|
ForEach(FederalTournamentAge.allCases) { category in |
||||||
|
LabeledContent { |
||||||
|
Button { |
||||||
|
if ageCategories.contains(category) { |
||||||
|
ageCategories.remove(category) |
||||||
|
} else { |
||||||
|
ageCategories.insert(category) |
||||||
|
} |
||||||
|
} label: { |
||||||
|
if ageCategories.contains(category) { |
||||||
|
Image(systemName: "checkmark.circle.fill") |
||||||
|
} |
||||||
|
} |
||||||
|
} label: { |
||||||
|
Text(category.localizedLabel()) |
||||||
|
} |
||||||
|
} |
||||||
|
} header: { |
||||||
|
Text("Catégories d'âge") |
||||||
|
} |
||||||
|
} |
||||||
|
.toolbar { |
||||||
|
ToolbarItem(placement: .topBarLeading) { |
||||||
|
if federalDataViewModel.areFiltersEnabled() { |
||||||
|
Button("Tout retirer", role: .cancel) { |
||||||
|
federalDataViewModel.removeFilters() |
||||||
|
dismiss() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
ToolbarItem(placement: .topBarTrailing) { |
||||||
|
ButtonValidateView { |
||||||
|
federalDataViewModel.levels = levels |
||||||
|
federalDataViewModel.categories = categories |
||||||
|
federalDataViewModel.ageCategories = ageCategories |
||||||
|
federalDataViewModel.selectedClubs = selectedClubs |
||||||
|
federalDataViewModel.id = UUID() |
||||||
|
dismiss() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.headerProminence(.increased) |
||||||
|
.navigationTitle("Filtres") |
||||||
|
.navigationBarTitleDisplayMode(.inline) |
||||||
|
.toolbarBackground(.visible, for: .navigationBar) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#Preview { |
||||||
|
TournamentFilterView(federalDataViewModel: FederalDataViewModel()) |
||||||
|
} |
||||||
Loading…
Reference in new issue