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.
 
 
PadelClub/PadelClub/Views/Planning/PlanningView.swift

109 lines
4.6 KiB

//
// PlanningView.swift
// PadelClub
//
// Created by Razmig Sarkissian on 07/04/2024.
//
import SwiftUI
struct PlanningView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) var tournament: Tournament
let matches: [Match]
@Binding var selectedScheduleDestination: ScheduleDestination?
@State private var timeSlots: [Date:[Match]]
@State private var days: [Date]
@State private var keys: [Date]
init(matches: [Match], selectedScheduleDestination: Binding<ScheduleDestination?>) {
self.matches = matches
_selectedScheduleDestination = selectedScheduleDestination
let timeSlots = Dictionary(grouping: matches) { $0.startDate ?? .distantFuture }
_timeSlots = State(wrappedValue: timeSlots)
_days = State(wrappedValue: Set(timeSlots.keys.map { $0.startOfDay }).sorted())
_keys = State(wrappedValue: timeSlots.keys.sorted())
}
var body: some View {
List {
if matches.allSatisfy({ $0.startDate == nil }) == false {
ForEach(days, id: \.self) { day in
Section {
ForEach(keys.filter({ $0.dayInt == day.dayInt }), id: \.self) { key in
if let _matches = timeSlots[key] {
DisclosureGroup {
ForEach(_matches) { match in
NavigationLink {
MatchDetailView(match: match, matchViewStyle: .sectionedStandardStyle)
.environment(self.tournament)
} label: {
LabeledContent {
if let courtName = match.courtName() {
Text(courtName)
}
} label: {
if let groupStage = match.groupStageObject {
Text(groupStage.groupStageTitle())
} else if let round = match.roundObject {
Text(round.roundTitle())
}
Text(match.matchTitle())
}
}
}
} label: {
_timeSlotView(key: key, matches: _matches)
}
}
}
} header: {
HStack {
Text(day.formatted(.dateTime.day().weekday().month()))
Spacer()
let count = _matchesCount(inDayInt: day.dayInt)
Text(self._formattedMatchCount(count))
}
}
.headerProminence(.increased)
}
}
}
.overlay {
if matches.allSatisfy({ $0.startDate == nil }) {
ContentUnavailableView {
Label("Aucun horaire défini", systemImage: "clock.badge.questionmark")
} description: {
Text("Vous n'avez pas encore défini d'horaire pour les différentes phases du tournoi")
} actions: {
RowButtonView("Horaire intelligent") {
selectedScheduleDestination = nil
}
}
}
}
}
private func _matchesCount(inDayInt dayInt: Int) -> Int {
timeSlots.filter { $0.key.dayInt == dayInt }.flatMap({ $0.value }).count
}
private func _timeSlotView(key: Date, matches: [Match]) -> some View {
LabeledContent {
Text(self._formattedMatchCount(matches.count))
} label: {
Text(key.formatted(date: .omitted, time: .shortened)).font(.title).fontWeight(.semibold)
Text(Set(matches.compactMap { $0.roundTitle() }).joined(separator: ", "))
}
}
fileprivate func _formattedMatchCount(_ count: Int) -> String {
return "\(count.formatted()) match\(count.pluralSuffix)"
}
}
//#Preview {
// PlanningView(matches: [], selectedScheduleDestination: .constant(nil))
//}