@ -15,9 +15,6 @@ struct CourtAvailabilitySettingsView: View {
let event : Event
@ 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 ?
var courtsUnavailability : [ Int : [ DateInterval ] ] {
@ -45,10 +42,6 @@ struct CourtAvailabilitySettingsView: View {
}
Button ( " éditer " ) {
editingSlot = dateInterval
courtIndex = dateInterval . courtIndex
startDate = dateInterval . startDate
endDate = dateInterval . endDate
showingPopover = true
}
Button ( " effacer " , role : . destructive ) {
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. " )
} actions : {
RowButtonView ( " Ajouter une indisponibilité " , systemImage : " plus.circle.fill " ) {
startDate = tournament . startDate
endDate = tournament . startDate . addingTimeInterval ( 5400 )
showingPopover = true
}
}
@ -120,8 +111,6 @@ struct CourtAvailabilitySettingsView: View {
. toolbar {
ToolbarItem ( placement : . topBarTrailing ) {
BarButtonView ( " Ajouter une indisponibilité " , icon : " plus.circle.fill " ) {
startDate = tournament . startDate
endDate = tournament . startDate . addingTimeInterval ( 5400 )
showingPopover = true
}
}
@ -130,66 +119,10 @@ struct CourtAvailabilitySettingsView: View {
. toolbarBackground ( . visible , for : . navigationBar )
. navigationTitle ( " Créneau indisponible " )
. sheet ( isPresented : $ showingPopover ) {
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 . 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
}
CourtAvailabilityEditorView ( event : event )
}
. sheet ( item : $ editingSlot ) { editingSlot in
CourtAvailabilityEditorView ( editingSlot : editingSlot , event : event )
}
}
}
@ -210,6 +143,135 @@ struct CourtPicker: View {
}
}
// # P r e v i e w {
// C o u r t A v a i l a b i l i t y S e t t i n g s V i e w ( e v e n t : E v e n t . m o c k ( ) )
// }
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 {
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 ) // M a k e b u t t o n s t a k e e q u a l s p a c e
}
. buttonStyle ( . borderedProminent )
. tint ( . master )
}
}