diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index dba80b4..7debfe4 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -92,6 +92,8 @@ FF1162832BCFBE4E000C4809 /* EditablePlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1162822BCFBE4E000C4809 /* EditablePlayerView.swift */; }; FF1162852BD00279000C4809 /* PlayerDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1162842BD00279000C4809 /* PlayerDetailView.swift */; }; FF1162872BD004AD000C4809 /* EditingTeamView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1162862BD004AD000C4809 /* EditingTeamView.swift */; }; + FF11628A2BD05247000C4809 /* DateUpdateManagerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1162892BD05247000C4809 /* DateUpdateManagerView.swift */; }; + FF11628C2BD05267000C4809 /* LoserRoundStepScheduleEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF11628B2BD05267000C4809 /* LoserRoundStepScheduleEditorView.swift */; }; FF1CBC1B2BB53D1F0036DAAB /* FederalTournament.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1CBC182BB53D1F0036DAAB /* FederalTournament.swift */; }; FF1CBC1D2BB53DC10036DAAB /* Calendar+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1CBC1C2BB53DC10036DAAB /* Calendar+Extensions.swift */; }; FF1CBC1F2BB53E0C0036DAAB /* FederalTournamentSearchScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1CBC1E2BB53E0C0036DAAB /* FederalTournamentSearchScope.swift */; }; @@ -368,6 +370,8 @@ FF1162822BCFBE4E000C4809 /* EditablePlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditablePlayerView.swift; sourceTree = ""; }; FF1162842BD00279000C4809 /* PlayerDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerDetailView.swift; sourceTree = ""; }; FF1162862BD004AD000C4809 /* EditingTeamView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditingTeamView.swift; sourceTree = ""; }; + FF1162892BD05247000C4809 /* DateUpdateManagerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateUpdateManagerView.swift; sourceTree = ""; }; + FF11628B2BD05267000C4809 /* LoserRoundStepScheduleEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoserRoundStepScheduleEditorView.swift; sourceTree = ""; }; FF1CBC182BB53D1F0036DAAB /* FederalTournament.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FederalTournament.swift; sourceTree = ""; }; FF1CBC1C2BB53DC10036DAAB /* Calendar+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Calendar+Extensions.swift"; sourceTree = ""; }; FF1CBC1E2BB53E0C0036DAAB /* FederalTournamentSearchScope.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FederalTournamentSearchScope.swift; sourceTree = ""; }; @@ -794,6 +798,14 @@ path = Cashier; sourceTree = ""; }; + FF1162882BD0523B000C4809 /* Components */ = { + isa = PBXGroup; + children = ( + FF1162892BD05247000C4809 /* DateUpdateManagerView.swift */, + ); + path = Components; + sourceTree = ""; + }; FF1DC54D2BAB34FA00FD8220 /* Club */ = { isa = PBXGroup; children = ( @@ -1107,8 +1119,10 @@ FFF964542BC266CF00EEF017 /* SchedulerView.swift */, FFF964562BC26B3400EEF017 /* RoundScheduleEditorView.swift */, FFFCDE0D2BCC833600317DEF /* LoserRoundScheduleEditorView.swift */, + FF11628B2BD05267000C4809 /* LoserRoundStepScheduleEditorView.swift */, FFF527D52BC6DDD000FF4EF2 /* MatchScheduleEditorView.swift */, FFF9645A2BC2D53B00EEF017 /* GroupStageScheduleEditorView.swift */, + FF1162882BD0523B000C4809 /* Components */, ); path = Planning; sourceTree = ""; @@ -1320,6 +1334,7 @@ FF7091662B90F0B000AB08DA /* TabDestination.swift in Sources */, FF9267F82BCE78C70080F940 /* CashierView.swift in Sources */, FF8F263F2BAD7D5C00650388 /* Event.swift in Sources */, + FF11628C2BD05267000C4809 /* LoserRoundStepScheduleEditorView.swift in Sources */, FF089EBF2BB0B14600F0AEC7 /* FileImportView.swift in Sources */, C4A47D9F2B7D0BCE00ADC637 /* StepperView.swift in Sources */, FFC83D4F2BB807D100750834 /* RoundsView.swift in Sources */, @@ -1429,6 +1444,7 @@ FF5D0D8B2BB4D1E3005CB568 /* CalendarView.swift in Sources */, FF1CBC1F2BB53E0C0036DAAB /* FederalTournamentSearchScope.swift in Sources */, FF8F26472BAE0ACB00650388 /* TournamentFieldsManagerView.swift in Sources */, + FF11628A2BD05247000C4809 /* DateUpdateManagerView.swift in Sources */, FFCFC01A2BBC5A8500B82851 /* MatchTypeSmallSelectionView.swift in Sources */, FF967D0B2BAF3D4C00A9A3BD /* TeamPickerView.swift in Sources */, FFA6D7872BB0B7A2003A31F3 /* CloudConvert.swift in Sources */, diff --git a/PadelClub/Views/Components/GenericDestinationPickerView.swift b/PadelClub/Views/Components/GenericDestinationPickerView.swift index 517aaaf..13c0adf 100644 --- a/PadelClub/Views/Components/GenericDestinationPickerView.swift +++ b/PadelClub/Views/Components/GenericDestinationPickerView.swift @@ -53,7 +53,7 @@ struct GenericDestinationPickerView: View { Color(.systemBackground) .clipShape(.circle) ) - .offset(x: 5, y: 5) + .offset(x: 3, y: 3) } else if let count = destination.badgeValue(), count > 0 { Image(systemName: count <= 50 ? "\(count).circle.fill" : "plus.circle.fill") .foregroundColor(.red) @@ -62,7 +62,7 @@ struct GenericDestinationPickerView: View { Color(.systemBackground) .clipShape(.circle) ) - .offset(x: 5, y: 5) + .offset(x: 3, y: 3) } } } diff --git a/PadelClub/Views/Planning/Components/DateUpdateManagerView.swift b/PadelClub/Views/Planning/Components/DateUpdateManagerView.swift new file mode 100644 index 0000000..1c30303 --- /dev/null +++ b/PadelClub/Views/Planning/Components/DateUpdateManagerView.swift @@ -0,0 +1,54 @@ +// +// DateUpdateManagerView.swift +// PadelClub +// +// Created by Razmig Sarkissian on 17/04/2024. +// + +import SwiftUI + +enum DateUpdate { + case nextRotation + case previousRotation + case tomorrowAtNine + case inMinutes(Int) + case afterRound(Round) + case afterGroupStage(GroupStage) +} + +struct DateUpdateManagerView: View { + @Binding var startDate: Date + @State private var dateUpdated: Bool = false + + var validateAction: () -> Void + + var body: some View { + HStack { + Menu { + Text("à demain 9h") + Text("à la prochaine rotation") + Text("à la précédente rotation") + } label: { + Text("décaler") + .underline() + } + Spacer() + + if dateUpdated { + Button { + validateAction() + dateUpdated = false + } label: { + Text("valider la modification") + .underline() + } + } + } + .font(.subheadline) + .buttonStyle(.borderless) + .onChange(of: startDate) { + dateUpdated = true + } + } +} + diff --git a/PadelClub/Views/Planning/GroupStageScheduleEditorView.swift b/PadelClub/Views/Planning/GroupStageScheduleEditorView.swift index 023360c..db8860a 100644 --- a/PadelClub/Views/Planning/GroupStageScheduleEditorView.swift +++ b/PadelClub/Views/Planning/GroupStageScheduleEditorView.swift @@ -33,31 +33,10 @@ struct GroupStageScheduleEditorView: View { } header: { Text(groupStage.groupStageTitle()) } footer: { - HStack { - Menu { - Text("à demain 9h") - Text("à la prochaine rotation") - Text("à la précédente rotation") - } label: { - Text("décaler") - .underline() - } - Spacer() - - if dateUpdated { - Button { - //todo, faut-il tout décaler ? - groupStage.startDate = startDate - _save() - dateUpdated = false - } label: { - Text("valider la modification") - .underline() - } - } + DateUpdateManagerView(startDate: $startDate) { + groupStage.startDate = startDate + _save() } - .font(.subheadline) - .buttonStyle(.borderless) } NavigationLink { diff --git a/PadelClub/Views/Planning/LoserRoundScheduleEditorView.swift b/PadelClub/Views/Planning/LoserRoundScheduleEditorView.swift index b580ea7..5b58990 100644 --- a/PadelClub/Views/Planning/LoserRoundScheduleEditorView.swift +++ b/PadelClub/Views/Planning/LoserRoundScheduleEditorView.swift @@ -6,104 +6,6 @@ // import SwiftUI -struct LoserRoundStepScheduleEditorView: View { - @EnvironmentObject var dataStore: DataStore - @Environment(Tournament.self) var tournament: Tournament - - var round: Round - var upperRound: Round - var matches: [Match] - @State private var startDate: Date - @State private var matchFormat: MatchFormat - @State private var dateUpdated: Bool = false - - init(round: Round, upperRound: Round) { - self.upperRound = upperRound - self.round = round - let _matches = upperRound.loserRounds(forRoundIndex: round.index).flatMap({ $0.playedMatches() }) - self.matches = _matches - self._startDate = State(wrappedValue: round.startDate ?? _matches.first?.startDate ?? Date()) - self._matchFormat = State(wrappedValue: round.matchFormat) - } - - var body: some View { - @Bindable var round = round - Section { - MatchFormatPickerView(headerLabel: "Format", matchFormat: $round.matchFormat) - DatePicker(selection: $startDate) { - Text(startDate.formatted(.dateTime.weekday(.wide))).font(.headline) - } - .onChange(of: round.matchFormat) { - dateUpdated = true - } - .onChange(of: startDate) { - dateUpdated = true - } - NavigationLink { - List { - ForEach(matches) { match in - if match.disabled == false { - MatchScheduleEditorView(match: match) - } - } - } - .headerProminence(.increased) - .navigationTitle(round.selectionLabel()) - .environment(tournament) - } label: { - Text("Voir tous les matchs") - } - - } header: { - Text(round.selectionLabel()) - } footer: { - HStack { - Menu { - Text("à demain 9h") - Text("à la prochaine rotation") - Text("à la précédente rotation") - } label: { - Text("décaler") - .underline() - } - Spacer() - - if dateUpdated { - Button { - _updateSchedule() - dateUpdated = false - } label: { - Text("valider la modification") - .underline() - } - } - } - .font(.subheadline) - .buttonStyle(.borderless) - - } - .headerProminence(.increased) - } - - private func _updateSchedule() { - upperRound.loserRounds(forRoundIndex: round.index).forEach({ round in - round.resetRound(updateMatchFormat: round.matchFormat) - }) - - try? dataStore.matches.addOrUpdate(contentOfs: matches) - _save() - - MatchScheduler.shared.updateSchedule(tournament: tournament, fromRoundId: round.id, fromMatchId: nil, startDate: startDate) - upperRound.loserRounds(forRoundIndex: round.index).forEach({ round in - round.startDate = startDate - }) - _save() - } - - private func _save() { - try? dataStore.rounds.addOrUpdate(contentOfs: upperRound.loserRounds(forRoundIndex: round.index)) - } -} struct LoserRoundScheduleEditorView: View { @EnvironmentObject var dataStore: DataStore @@ -113,7 +15,6 @@ struct LoserRoundScheduleEditorView: View { var loserRounds: [Round] @State private var startDate: Date @State private var matchFormat: MatchFormat - @State private var dateUpdated: Bool = false init(upperRound: Round) { self.upperRound = upperRound @@ -133,29 +34,9 @@ struct LoserRoundScheduleEditorView: View { } header: { Text("Classement " + upperRound.roundTitle()) } footer: { - HStack { - Menu { - Text("à demain 9h") - Text("à la prochaine rotation") - Text("à la précédente rotation") - } label: { - Text("décaler") - .underline() - } - Spacer() - - if dateUpdated { - Button { - _updateSchedule() - dateUpdated = false - } label: { - Text("valider la modification") - .underline() - } - } + DateUpdateManagerView(startDate: $startDate) { + _updateSchedule() } - .font(.subheadline) - .buttonStyle(.borderless) } @@ -165,12 +46,6 @@ struct LoserRoundScheduleEditorView: View { } } } - .onChange(of: startDate) { - dateUpdated = true - } - .onChange(of: matchFormat) { - dateUpdated = true - } .headerProminence(.increased) .navigationTitle("Réglages") .toolbarBackground(.visible, for: .navigationBar) diff --git a/PadelClub/Views/Planning/LoserRoundStepScheduleEditorView.swift b/PadelClub/Views/Planning/LoserRoundStepScheduleEditorView.swift new file mode 100644 index 0000000..f4f48dd --- /dev/null +++ b/PadelClub/Views/Planning/LoserRoundStepScheduleEditorView.swift @@ -0,0 +1,79 @@ +// +// LoserRoundStepScheduleEditorView.swift +// PadelClub +// +// Created by Razmig Sarkissian on 17/04/2024. +// + +import SwiftUI + +struct LoserRoundStepScheduleEditorView: View { + @EnvironmentObject var dataStore: DataStore + @Environment(Tournament.self) var tournament: Tournament + + var round: Round + var upperRound: Round + var matches: [Match] + @State private var startDate: Date + @State private var matchFormat: MatchFormat + + init(round: Round, upperRound: Round) { + self.upperRound = upperRound + self.round = round + let _matches = upperRound.loserRounds(forRoundIndex: round.index).flatMap({ $0.playedMatches() }) + self.matches = _matches + self._startDate = State(wrappedValue: round.startDate ?? _matches.first?.startDate ?? Date()) + self._matchFormat = State(wrappedValue: round.matchFormat) + } + + var body: some View { + @Bindable var round = round + Section { + MatchFormatPickerView(headerLabel: "Format", matchFormat: $round.matchFormat) + DatePicker(selection: $startDate) { + Text(startDate.formatted(.dateTime.weekday(.wide))).font(.headline) + } + NavigationLink { + List { + ForEach(matches) { match in + if match.disabled == false { + MatchScheduleEditorView(match: match) + } + } + } + .headerProminence(.increased) + .navigationTitle(round.selectionLabel()) + .environment(tournament) + } label: { + Text("Voir tous les matchs") + } + + } header: { + Text(round.selectionLabel()) + } footer: { + DateUpdateManagerView(startDate: $startDate) { + _updateSchedule() + } + } + .headerProminence(.increased) + } + + private func _updateSchedule() { + upperRound.loserRounds(forRoundIndex: round.index).forEach({ round in + round.resetRound(updateMatchFormat: round.matchFormat) + }) + + try? dataStore.matches.addOrUpdate(contentOfs: matches) + _save() + + MatchScheduler.shared.updateSchedule(tournament: tournament, fromRoundId: round.id, fromMatchId: nil, startDate: startDate) + upperRound.loserRounds(forRoundIndex: round.index).forEach({ round in + round.startDate = startDate + }) + _save() + } + + private func _save() { + try? dataStore.rounds.addOrUpdate(contentOfs: upperRound.loserRounds(forRoundIndex: round.index)) + } +} diff --git a/PadelClub/Views/Planning/MatchScheduleEditorView.swift b/PadelClub/Views/Planning/MatchScheduleEditorView.swift index b5b39cb..2f24b72 100644 --- a/PadelClub/Views/Planning/MatchScheduleEditorView.swift +++ b/PadelClub/Views/Planning/MatchScheduleEditorView.swift @@ -11,7 +11,6 @@ struct MatchScheduleEditorView: View { @Environment(Tournament.self) var tournament: Tournament var match: Match @State private var startDate: Date - @State private var dateUpdated: Bool = false init(match: Match) { self.match = match @@ -23,9 +22,6 @@ struct MatchScheduleEditorView: View { DatePicker(selection: $startDate) { Text(startDate.formatted(.dateTime.weekday(.wide))).font(.headline) } - .onChange(of: startDate) { - dateUpdated = true - } } header: { if let round = match.roundObject { Text(round.roundTitle() + " " + match.matchTitle()) @@ -33,29 +29,9 @@ struct MatchScheduleEditorView: View { Text(match.matchTitle()) } } footer: { - HStack { - Menu { - Text("à demain 9h") - Text("à la prochaine rotation") - Text("à la précédente rotation") - } label: { - Text("décaler") - .underline() - } - Spacer() - - if dateUpdated { - Button { - _updateSchedule() - dateUpdated = false - } label: { - Text("valider la modification") - .underline() - } - } + DateUpdateManagerView(startDate: $startDate) { + _updateSchedule() } - .font(.subheadline) - .buttonStyle(.borderless) } .headerProminence(.increased) } diff --git a/PadelClub/Views/Planning/RoundScheduleEditorView.swift b/PadelClub/Views/Planning/RoundScheduleEditorView.swift index 5ced1eb..41640dc 100644 --- a/PadelClub/Views/Planning/RoundScheduleEditorView.swift +++ b/PadelClub/Views/Planning/RoundScheduleEditorView.swift @@ -13,7 +13,6 @@ struct RoundScheduleEditorView: View { var round: Round @State private var startDate: Date - @State private var dateUpdated: Bool = false init(round: Round) { self.round = round @@ -28,36 +27,10 @@ struct RoundScheduleEditorView: View { DatePicker(selection: $startDate) { Text(startDate.formatted(.dateTime.weekday(.wide))).font(.headline) } - .onChange(of: round.matchFormat) { - dateUpdated = true - } - .onChange(of: startDate) { - dateUpdated = true - } } footer: { - HStack { - Menu { - Text("à demain 9h") - Text("à la prochaine rotation") - Text("à la précédente rotation") - } label: { - Text("décaler") - .underline() - } - Spacer() - - if dateUpdated { - Button { - _updateSchedule() - dateUpdated = false - } label: { - Text("valider la modification") - .underline() - } - } + DateUpdateManagerView(startDate: $startDate) { + _updateSchedule() } - .font(.subheadline) - .buttonStyle(.borderless) } ForEach(round.playedMatches()) { match in diff --git a/PadelClub/Views/Tournament/Screen/TournamentCashierView.swift b/PadelClub/Views/Tournament/Screen/TournamentCashierView.swift index 9f1730d..1de11e8 100644 --- a/PadelClub/Views/Tournament/Screen/TournamentCashierView.swift +++ b/PadelClub/Views/Tournament/Screen/TournamentCashierView.swift @@ -55,11 +55,11 @@ enum CashierDestination: Identifiable, Selectable { case .summary: return nil case .groupStage(let groupStage): - return groupStage.unsortedPlayers().allSatisfy({ $0.hasPaid() }) ? "checkmark" : nil + return groupStage.unsortedPlayers().allSatisfy({ $0.hasPaid() }) ? "checkmark.circle.fill" : nil case .bracket(let round): - return round.seeds().flatMap { $0.unsortedPlayers() }.allSatisfy({ $0.hasPaid() }) ? "checkmark" : nil + return round.seeds().flatMap { $0.unsortedPlayers() }.allSatisfy({ $0.hasPaid() }) ? "checkmark.circle.fill" : nil case .all(let tournament): - return tournament.selectedPlayers().allSatisfy({ $0.hasPaid() }) ? "checkmark" : nil + return tournament.selectedPlayers().allSatisfy({ $0.hasPaid() }) ? "checkmark.circle.fill" : nil } }