You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
8.1 KiB
188 lines
8.1 KiB
//
|
|
// CalendarView.swift
|
|
// PadelClub
|
|
//
|
|
// Created by Razmig Sarkissian on 01/03/2024.
|
|
//
|
|
|
|
import SwiftUI
|
|
import LeStorage
|
|
|
|
struct CalendarView: View {
|
|
@EnvironmentObject var dataStore: DataStore
|
|
@Environment(NavigationViewModel.self) var navigation: NavigationViewModel
|
|
@Environment(FederalDataViewModel.self) var federalDataViewModel: FederalDataViewModel
|
|
let date: Date
|
|
let tournaments: [FederalTournamentHolder]
|
|
let daysOfWeek = Date.capitalizedFirstLettersOfWeekdays
|
|
let columns = Array(repeating: GridItem(.flexible()), count: 7)
|
|
let color = Color.master
|
|
|
|
@State private var days: [Date] = []
|
|
@State private var counts = [Int : Int]()
|
|
@State private var newTournament: Tournament?
|
|
|
|
@ViewBuilder
|
|
var body: some View {
|
|
VStack {
|
|
HStack {
|
|
ForEach(daysOfWeek.indices, id: \.self) { index in
|
|
Text(daysOfWeek[index])
|
|
.fontWeight(.black)
|
|
.foregroundStyle(color)
|
|
.frame(maxWidth: .infinity)
|
|
}
|
|
}
|
|
LazyVGrid(columns: columns) {
|
|
ForEach(days, id: \.self) { day in
|
|
_dayView(day)
|
|
}
|
|
}
|
|
}
|
|
.sheet(item: $newTournament) { tournament in
|
|
EventCreationView(startingDate: tournament.startDate, tournaments: [tournament], selectedClub: federalDataViewModel.selectedClub())
|
|
.environment(navigation)
|
|
.tint(.master)
|
|
}
|
|
.onAppear {
|
|
days = date.calendarDisplayDays
|
|
setupCounts()
|
|
}
|
|
.onChange(of: date) {
|
|
days = date.calendarDisplayDays
|
|
setupCounts()
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private func _dayView(_ day: Date) -> some View {
|
|
if day.monthInt != date.monthInt {
|
|
Text("")
|
|
} else {
|
|
Menu {
|
|
Button("Créer un tournoi") {
|
|
let tournament = Tournament.newEmptyInstance()
|
|
tournament.startDate = day.atNine()
|
|
if federalDataViewModel.categories.isEmpty == false {
|
|
tournament.tournamentCategory = federalDataViewModel.categories.first!
|
|
}
|
|
if federalDataViewModel.levels.isEmpty == false {
|
|
tournament.tournamentLevel = federalDataViewModel.levels.first!
|
|
}
|
|
if federalDataViewModel.ageCategories.isEmpty == false {
|
|
tournament.federalTournamentAge = federalDataViewModel.ageCategories.first!
|
|
}
|
|
newTournament = tournament
|
|
}
|
|
|
|
Divider()
|
|
|
|
let tournamentsByDay = tournaments.filter { day.dayInt >= $0.startDate.dayInt && day.dayInt < $0.startDate.dayInt + $0.dayDuration }
|
|
ForEach(tournamentsByDay, id: \.holderId) { tournamentHolder in
|
|
if let tournament = tournamentHolder as? Tournament {
|
|
Section {
|
|
Button(tournament.tournamentTitle(.short)) {
|
|
navigation.path.append(tournament)
|
|
}
|
|
} header: {
|
|
Text("sur " + tournament.dayDuration.formatted() + " jour" + tournament.dayDuration.pluralSuffix)
|
|
}
|
|
} else if let tournament = tournamentHolder as? FederalTournament {
|
|
Menu {
|
|
ForEach(tournament.tournaments, id: \.id) { build in
|
|
if federalDataViewModel.isFederalTournamentValidForFilters(tournament, build: build) {
|
|
|
|
if navigation.agendaDestination == .around {
|
|
NavigationLink(build.buildHolderTitle()) {
|
|
TournamentSubscriptionView(federalTournament: tournament, build: build, user: dataStore.user)
|
|
}
|
|
} else {
|
|
Button(build.buildHolderTitle()) {
|
|
_createOrShow(federalTournament: tournament, existingTournament: event(forTournament: tournament)?.existingBuild(build), build: build)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} label: {
|
|
Text(tournament.clubLabel())
|
|
Text("sur " + tournament.dayDuration.formatted() + " jour" + tournament.dayDuration.pluralSuffix)
|
|
}
|
|
}
|
|
}
|
|
} label: {
|
|
Text(day.formatted(.dateTime.day()))
|
|
.fontWeight(.bold)
|
|
.foregroundStyle((counts[day.dayInt] != nil ? Color.white : Color.black))
|
|
.frame(maxWidth: .infinity, minHeight: 40)
|
|
.background(
|
|
Circle()
|
|
.foregroundStyle(
|
|
Date.now.startOfDay == day.startOfDay
|
|
? (counts[day.dayInt] != nil ? Color.logoRed : Color.green)
|
|
: (counts[day.dayInt] != nil ? Color.master : Color.beige)
|
|
)
|
|
)
|
|
.overlay(alignment: .bottomTrailing) {
|
|
if let count = counts[day.dayInt] {
|
|
Image(systemName: count <= 50 ? "\(count).circle.fill" : "plus.circle.fill")
|
|
.foregroundColor(.secondary)
|
|
.imageScale(.medium)
|
|
.background (
|
|
Color(.systemBackground)
|
|
.clipShape(.circle)
|
|
)
|
|
.offset(x: 5, y: 5)
|
|
}
|
|
}
|
|
}
|
|
.buttonStyle(.plain)
|
|
}
|
|
|
|
}
|
|
|
|
func setupCounts() {
|
|
let filteredTournaments = tournaments
|
|
let mappedItems = filteredTournaments.flatMap { tournamentHolder in
|
|
(0..<tournamentHolder.dayDuration).map({ dayDuration in
|
|
(tournamentHolder.startDate.dayInt + dayDuration, tournamentHolder.tournaments.count)
|
|
})
|
|
}
|
|
counts = Dictionary(mappedItems, uniquingKeysWith: +)
|
|
}
|
|
|
|
func event(forTournament tournament: FederalTournamentHolder) -> Event? {
|
|
guard let federalTournament = tournament as? FederalTournament else { return nil }
|
|
return dataStore.events.first(where: { $0.tenupId == federalTournament.id.string })
|
|
}
|
|
|
|
private func _createOrShow(federalTournament: FederalTournament, existingTournament: Tournament?, build: any TournamentBuildHolder) {
|
|
if let existingTournament {
|
|
navigation.agendaDestination = .activity
|
|
navigation.path.append(existingTournament)
|
|
} else {
|
|
let event = federalTournament.getEvent()
|
|
let newTournament = Tournament.newEmptyInstance()
|
|
newTournament.event = event.id
|
|
//todo
|
|
//newTournament.umpireMail()
|
|
//newTournament.jsonData = jsonData
|
|
newTournament.tournamentLevel = build.level
|
|
newTournament.tournamentCategory = build.category
|
|
newTournament.federalTournamentAge = build.age
|
|
newTournament.dayDuration = federalTournament.dayDuration
|
|
newTournament.startDate = federalTournament.startDate.atBeginningOfDay(hourInt: 9)
|
|
newTournament.setupFederalSettings()
|
|
do {
|
|
try dataStore.tournaments.addOrUpdate(instance: newTournament)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
navigation.path.append(newTournament)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//#Preview {
|
|
// CalendarView(date: .now, tournaments: [])
|
|
//}
|
|
|