improve unavailibity view

paca_championship
Raz 1 year ago
parent 77b3f27685
commit 5496bf2e96
  1. 2
      PadelClub/Data/Tournament.swift
  2. 128
      PadelClub/Views/Planning/CourtAvailabilitySettingsView.swift
  3. 5
      PadelClub/Views/Round/RoundSettingsView.swift

@ -2264,7 +2264,7 @@ defer {
} }
func seedsCount() -> Int { func seedsCount() -> Int {
teamCount - groupStageSpots() selectedSortedTeams().count - groupStageSpots()
} }
func lastDrawnDate() -> Date? { func lastDrawnDate() -> Date? {

@ -15,9 +15,6 @@ struct CourtAvailabilitySettingsView: View {
let event: Event let event: Event
@State private var showingPopover: Bool = false @State private var showingPopover: Bool = false
@State private var courtIndex: Int = 0
@State private var startDate: Date = Date()
@State private var endDate: Date = Date()
@State private var editingSlot: DateInterval? @State private var editingSlot: DateInterval?
var courtsUnavailability: [Int: [DateInterval]] { var courtsUnavailability: [Int: [DateInterval]] {
@ -45,10 +42,6 @@ struct CourtAvailabilitySettingsView: View {
} }
Button("éditer") { Button("éditer") {
editingSlot = dateInterval editingSlot = dateInterval
courtIndex = dateInterval.courtIndex
startDate = dateInterval.startDate
endDate = dateInterval.endDate
showingPopover = true
} }
Button("effacer", role: .destructive) { Button("effacer", role: .destructive) {
do { do {
@ -110,8 +103,6 @@ struct CourtAvailabilitySettingsView: View {
Text("Vous pouvez précisez l'indisponibilité d'une ou plusieurs terrains, que ce soit pour une journée entière ou un créneau précis.") Text("Vous pouvez précisez l'indisponibilité d'une ou plusieurs terrains, que ce soit pour une journée entière ou un créneau précis.")
} actions: { } actions: {
RowButtonView("Ajouter une indisponibilité", systemImage: "plus.circle.fill") { RowButtonView("Ajouter une indisponibilité", systemImage: "plus.circle.fill") {
startDate = tournament.startDate
endDate = tournament.startDate.addingTimeInterval(5400)
showingPopover = true showingPopover = true
} }
} }
@ -120,8 +111,6 @@ struct CourtAvailabilitySettingsView: View {
.toolbar { .toolbar {
ToolbarItem(placement: .topBarTrailing) { ToolbarItem(placement: .topBarTrailing) {
BarButtonView("Ajouter une indisponibilité", icon: "plus.circle.fill") { BarButtonView("Ajouter une indisponibilité", icon: "plus.circle.fill") {
startDate = tournament.startDate
endDate = tournament.startDate.addingTimeInterval(5400)
showingPopover = true showingPopover = true
} }
} }
@ -130,6 +119,58 @@ struct CourtAvailabilitySettingsView: View {
.toolbarBackground(.visible, for: .navigationBar) .toolbarBackground(.visible, for: .navigationBar)
.navigationTitle("Créneau indisponible") .navigationTitle("Créneau indisponible")
.sheet(isPresented: $showingPopover) { .sheet(isPresented: $showingPopover) {
CourtAvailabilityEditorView(event: event)
}
.sheet(item: $editingSlot) { editingSlot in
CourtAvailabilityEditorView(editingSlot: editingSlot, event: event)
}
}
}
struct CourtPicker: View {
@Environment(Tournament.self) var tournament: Tournament
let title: String
@Binding var selection: Int
let maxCourt: Int
var body: some View {
Picker(title, selection: $selection) {
ForEach(0..<maxCourt, id: \.self) {
Text(tournament.courtName(atIndex: $0))
}
}
}
}
struct CourtAvailabilityEditorView: View {
@Environment(Tournament.self) var tournament: Tournament
@EnvironmentObject var dataStore: DataStore
@Environment(\.dismiss) private var dismiss
var editingSlot: DateInterval?
let event: Event
@State private var courtIndex: Int
@State private var startDate: Date
@State private var endDate: Date
init(editingSlot: DateInterval, event: Event) {
self.editingSlot = editingSlot
self.event = event
_courtIndex = .init(wrappedValue: editingSlot.courtIndex)
_startDate = .init(wrappedValue: editingSlot.startDate)
_endDate = .init(wrappedValue: editingSlot.endDate)
}
init(event: Event) {
self.event = event
_courtIndex = .init(wrappedValue: 0)
let startDate = event.eventStartDate()
_startDate = .init(wrappedValue: event.eventStartDate())
_endDate = .init(wrappedValue: startDate.addingTimeInterval(5400))
}
var body: some View {
NavigationStack { NavigationStack {
Form { Form {
Section { Section {
@ -153,9 +194,21 @@ struct CourtAvailabilitySettingsView: View {
} footer: { } footer: {
FooterButtonView("jour entier") { FooterButtonView("jour entier") {
startDate = startDate.startOfDay startDate = startDate.startOfDay
endDate = startDate.endOfDay() endDate = startDate.tomorrowAtNine.startOfDay
} }
} }
Section {
DateAdjusterView(date: $startDate)
} header: {
Text("Modifier rapidement l'horaire de début")
}
Section {
DateAdjusterView(date: $endDate)
} header: {
Text("Modifier rapidement l'horaire de fin")
}
} }
.toolbar { .toolbar {
ButtonValidateView { ButtonValidateView {
@ -176,40 +229,49 @@ struct CourtAvailabilitySettingsView: View {
Logger.error(error) Logger.error(error)
} }
} }
showingPopover = false
dismiss()
}
ToolbarItem(placement: .topBarLeading) {
Button("Annuler", role: .cancel) {
dismiss()
}
} }
} }
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.toolbarBackground(.visible, for: .navigationBar) .toolbarBackground(.visible, for: .navigationBar)
.navigationTitle("Nouveau créneau") .navigationTitle(_navigationTitle())
.tint(.master) .tint(.master)
} }
.onAppear {
UIDatePicker.appearance().minuteInterval = 5
}
.onDisappear {
UIDatePicker.appearance().minuteInterval = 1
}
} }
private func _navigationTitle() -> String {
editingSlot == nil ? "Nouveau créneau" : "Édition du créneau"
} }
} }
struct CourtPicker: View { struct DateAdjusterView: View {
@Environment(Tournament.self) var tournament: Tournament @Binding var date: Date
let title: String
@Binding var selection: Int
let maxCourt: Int
var body: some View { var body: some View {
Picker(title, selection: $selection) { HStack {
ForEach(0..<maxCourt, id: \.self) { _createButton(label: "-1h", timeOffset: -1, component: .hour)
Text(tournament.courtName(atIndex: $0)) _createButton(label: "-30m", timeOffset: -30, component: .minute)
_createButton(label: "+30m", timeOffset: 30, component: .minute)
_createButton(label: "+1h", timeOffset: 1, component: .hour)
} }
.font(.headline)
} }
private func _createButton(label: String, timeOffset: Int, component: Calendar.Component) -> some View {
Button(action: {
date = Calendar.current.date(byAdding: component, value: timeOffset, to: date) ?? date
}) {
Text(label)
.frame(maxWidth: .infinity) // Make buttons take equal space
}
.buttonStyle(.borderedProminent)
.tint(.master)
} }
} }
//#Preview {
// CourtAvailabilitySettingsView(event: Event.mock())
//}

@ -74,6 +74,7 @@ struct RoundSettingsView: View {
} }
} }
let previewAvailable = tournament.rounds().flatMap({ $0.seeds() }).count < tournament.seedsCount() && tournament.lastDrawnDate() != nil && tournament.seedSpotsLeft()
Section { Section {
NavigationLink { NavigationLink {
DrawLogsView() DrawLogsView()
@ -82,7 +83,7 @@ struct RoundSettingsView: View {
Text("Gestionnaire des tirages au sort") Text("Gestionnaire des tirages au sort")
} }
if tournament.rounds().flatMap({ $0.seeds() }).count < tournament.seedsCount(), tournament.lastDrawnDate() != nil, tournament.seedSpotsLeft() { if previewAvailable {
NavigationLink { NavigationLink {
PreviewBracketPositionView(seeds: tournament.seeds(), drawLogs: tournament.drawLogs()) PreviewBracketPositionView(seeds: tournament.seeds(), drawLogs: tournament.drawLogs())
@ -94,8 +95,10 @@ struct RoundSettingsView: View {
} }
} }
} footer: { } footer: {
if previewAvailable {
Text("Vous avez une ou plusieurs places libres dans votre tableau. Pour respecter le tirage au sort effectué, vous pouvez décaler les têtes de séries.") Text("Vous avez une ou plusieurs places libres dans votre tableau. Pour respecter le tirage au sort effectué, vous pouvez décaler les têtes de séries.")
} }
}
// Section { // Section {
// RowButtonView("Enabled", role: .destructive) { // RowButtonView("Enabled", role: .destructive) {

Loading…
Cancel
Save