improve unavailibity view

paca_championship
Raz 1 year ago
parent 77b3f27685
commit 5496bf2e96
  1. 2
      PadelClub/Data/Tournament.swift
  2. 210
      PadelClub/Views/Planning/CourtAvailabilitySettingsView.swift
  3. 9
      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,66 +119,10 @@ 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) {
NavigationStack { CourtAvailabilityEditorView(event: event)
Form { }
Section { .sheet(item: $editingSlot) { editingSlot in
CourtPicker(title: "Terrain", selection: $courtIndex, maxCourt: tournament.courtCount) CourtAvailabilityEditorView(editingSlot: editingSlot, event: event)
}
Section {
DatePicker("Début", selection: $startDate)
.onChange(of: startDate) {
if endDate < startDate {
endDate = startDate.addingTimeInterval(90*60)
}
}
DatePicker("Fin", selection: $endDate)
.onChange(of: endDate) {
if startDate > endDate {
startDate = endDate.addingTimeInterval(-90*60)
}
}
} footer: {
FooterButtonView("jour entier") {
startDate = startDate.startOfDay
endDate = startDate.endOfDay()
}
}
}
.toolbar {
ButtonValidateView {
if editingSlot == nil {
let dateInterval = DateInterval(event: event.id, courtIndex: courtIndex, startDate: startDate, endDate: endDate)
do {
try dataStore.dateIntervals.addOrUpdate(instance: dateInterval)
} catch {
Logger.error(error)
}
} else {
editingSlot?.courtIndex = courtIndex
editingSlot?.endDate = endDate
editingSlot?.startDate = startDate
do {
try dataStore.dateIntervals.addOrUpdate(instance: editingSlot!)
} catch {
Logger.error(error)
}
}
showingPopover = false
}
}
.navigationBarTitleDisplayMode(.inline)
.toolbarBackground(.visible, for: .navigationBar)
.navigationTitle("Nouveau créneau")
.tint(.master)
}
.onAppear {
UIDatePicker.appearance().minuteInterval = 5
}
.onDisappear {
UIDatePicker.appearance().minuteInterval = 1
}
} }
} }
} }
@ -210,6 +143,135 @@ struct CourtPicker: View {
} }
} }
//#Preview { struct CourtAvailabilityEditorView: View {
// CourtAvailabilitySettingsView(event: Event.mock()) @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 {
Form {
Section {
CourtPicker(title: "Terrain", selection: $courtIndex, maxCourt: tournament.courtCount)
}
Section {
DatePicker("Début", selection: $startDate)
.onChange(of: startDate) {
if endDate < startDate {
endDate = startDate.addingTimeInterval(90*60)
}
}
DatePicker("Fin", selection: $endDate)
.onChange(of: endDate) {
if startDate > endDate {
startDate = endDate.addingTimeInterval(-90*60)
}
}
} footer: {
FooterButtonView("jour entier") {
startDate = startDate.startOfDay
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 {
ButtonValidateView {
if editingSlot == nil {
let dateInterval = DateInterval(event: event.id, courtIndex: courtIndex, startDate: startDate, endDate: endDate)
do {
try dataStore.dateIntervals.addOrUpdate(instance: dateInterval)
} catch {
Logger.error(error)
}
} else {
editingSlot?.courtIndex = courtIndex
editingSlot?.endDate = endDate
editingSlot?.startDate = startDate
do {
try dataStore.dateIntervals.addOrUpdate(instance: editingSlot!)
} catch {
Logger.error(error)
}
}
dismiss()
}
ToolbarItem(placement: .topBarLeading) {
Button("Annuler", role: .cancel) {
dismiss()
}
}
}
.navigationBarTitleDisplayMode(.inline)
.toolbarBackground(.visible, for: .navigationBar)
.navigationTitle(_navigationTitle())
.tint(.master)
}
}
private func _navigationTitle() -> String {
editingSlot == nil ? "Nouveau créneau" : "Édition du créneau"
}
}
struct DateAdjusterView: View {
@Binding var date: Date
var body: some View {
HStack {
_createButton(label: "-1h", timeOffset: -1, component: .hour)
_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)
}
}

@ -73,7 +73,8 @@ struct RoundSettingsView: View {
Text("Suite à un changement dans votre liste d'inscrits, veuillez vérifier l'intégrité de votre tableau et valider que tout est ok.") Text("Suite à un changement dans votre liste d'inscrits, veuillez vérifier l'intégrité de votre tableau et valider que tout est ok.")
} }
} }
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,7 +95,9 @@ struct RoundSettingsView: View {
} }
} }
} footer: { } footer: {
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.") 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.")
}
} }
// Section { // Section {

Loading…
Cancel
Save