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