|
|
|
|
@ -13,20 +13,19 @@ |
|
|
|
|
import SwiftUI |
|
|
|
|
|
|
|
|
|
struct CalendarView: View { |
|
|
|
|
@Environment(NavigationViewModel.self) var navigation: NavigationViewModel |
|
|
|
|
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]() |
|
|
|
|
|
|
|
|
|
// Extension properties to display selected day's workouts |
|
|
|
|
@State private var selectedDay: Date? |
|
|
|
|
@State private var tournamentsByDay: [FederalTournamentHolder] = [] |
|
|
|
|
@State private var newTournament: Tournament? |
|
|
|
|
|
|
|
|
|
@ViewBuilder |
|
|
|
|
var body: some View { |
|
|
|
|
let color = Color.blue |
|
|
|
|
VStack { |
|
|
|
|
HStack { |
|
|
|
|
ForEach(daysOfWeek.indices, id: \.self) { index in |
|
|
|
|
@ -38,79 +37,83 @@ struct CalendarView: View { |
|
|
|
|
} |
|
|
|
|
LazyVGrid(columns: columns) { |
|
|
|
|
ForEach(days, id: \.self) { day in |
|
|
|
|
if day.monthInt != date.monthInt { |
|
|
|
|
Text("") |
|
|
|
|
} else { |
|
|
|
|
Text(day.formatted(.dateTime.day())) |
|
|
|
|
.fontWeight(.bold) |
|
|
|
|
.foregroundStyle(.secondary) |
|
|
|
|
.frame(maxWidth: .infinity, minHeight: 40) |
|
|
|
|
.background( |
|
|
|
|
Circle() |
|
|
|
|
.foregroundStyle( |
|
|
|
|
Date.now.startOfDay == day.startOfDay |
|
|
|
|
? .red.opacity(counts[day.dayInt] != nil ? 0.8 : 0.3) |
|
|
|
|
: color.opacity(counts[day.dayInt] != nil ? 0.8 : 0.3) |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
.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) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
.onTapGesture { |
|
|
|
|
// Used in the ExtendedProject branch |
|
|
|
|
if let count = counts[day.dayInt], count > 0 { |
|
|
|
|
selectedDay = day |
|
|
|
|
} else { |
|
|
|
|
selectedDay = nil |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
_dayView(day) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
.sheet(item: $newTournament) { tournament in |
|
|
|
|
EventCreationView(startingDate: tournament.startDate, tournaments: [tournament]) |
|
|
|
|
.environment(navigation) |
|
|
|
|
.tint(.master) |
|
|
|
|
} |
|
|
|
|
.onAppear { |
|
|
|
|
days = date.calendarDisplayDays |
|
|
|
|
setupCounts() |
|
|
|
|
selectedDay = nil // Used to present list of workouts when tapped |
|
|
|
|
} |
|
|
|
|
.onChange(of: date) { |
|
|
|
|
days = date.calendarDisplayDays |
|
|
|
|
setupCounts() |
|
|
|
|
selectedDay = nil // Used to present list of workouts when tapped |
|
|
|
|
} |
|
|
|
|
.onChange(of: selectedDay) { |
|
|
|
|
// Will filter the workouts for the specific day and activity is selected |
|
|
|
|
if let selectedDay { |
|
|
|
|
tournamentsByDay = tournaments.filter {$0.startDate.dayInt == selectedDay.dayInt} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@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() |
|
|
|
|
newTournament = tournament |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let tournamentsByDay = tournaments.filter { $0.startDate.dayInt == day.dayInt } |
|
|
|
|
ForEach(tournamentsByDay, id: \.holderId) { tournamentHolder in |
|
|
|
|
if let tournament = tournamentHolder as? Tournament { |
|
|
|
|
Button(tournament.tournamentTitle()) { |
|
|
|
|
navigation.path.append(tournament) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} label: { |
|
|
|
|
Text(day.formatted(.dateTime.day())) |
|
|
|
|
.fontWeight(.bold) |
|
|
|
|
.foregroundStyle(.white) |
|
|
|
|
.frame(maxWidth: .infinity, minHeight: 40) |
|
|
|
|
.background( |
|
|
|
|
Circle() |
|
|
|
|
.foregroundStyle( |
|
|
|
|
Date.now.startOfDay == day.startOfDay |
|
|
|
|
? .green.opacity(counts[day.dayInt] != nil ? 0.8 : 0.3) |
|
|
|
|
: color.opacity(counts[day.dayInt] != nil ? 0.8 : 0.3) |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
.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) |
|
|
|
|
} |
|
|
|
|
// |
|
|
|
|
// if let selectedDay { |
|
|
|
|
// // Presents the list of workouts for the selected day and activity |
|
|
|
|
// ForEach(tournamentsByDay) { tournament in |
|
|
|
|
// NavigationLink(value: tournament) { |
|
|
|
|
// HStack { |
|
|
|
|
// Text(tournament.tournamentTitle()) |
|
|
|
|
// Spacer() |
|
|
|
|
// Text(tournament.sortedTeams().count.formatted()) |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func setupCounts() { |
|
|
|
|
let filteredTournaments = tournaments |
|
|
|
|
let mappedItems = filteredTournaments.map{($0.startDate.dayInt, $0.tournaments.count)} |
|
|
|
|
let mappedItems = filteredTournaments.flatMap { tournamentHolder in |
|
|
|
|
(0..<tournamentHolder.dayDuration).map({ dayDuration in |
|
|
|
|
(tournamentHolder.startDate.dayInt + dayDuration, tournamentHolder.tournaments.count) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
counts = Dictionary(mappedItems, uniquingKeysWith: +) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|