add date manager view component

multistore
Razmig Sarkissian 2 years ago
parent b1db99f2a0
commit 6d28930359
  1. 16
      PadelClub.xcodeproj/project.pbxproj
  2. 4
      PadelClub/Views/Components/GenericDestinationPickerView.swift
  3. 54
      PadelClub/Views/Planning/Components/DateUpdateManagerView.swift
  4. 27
      PadelClub/Views/Planning/GroupStageScheduleEditorView.swift
  5. 129
      PadelClub/Views/Planning/LoserRoundScheduleEditorView.swift
  6. 79
      PadelClub/Views/Planning/LoserRoundStepScheduleEditorView.swift
  7. 28
      PadelClub/Views/Planning/MatchScheduleEditorView.swift
  8. 31
      PadelClub/Views/Planning/RoundScheduleEditorView.swift
  9. 6
      PadelClub/Views/Tournament/Screen/TournamentCashierView.swift

@ -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 = "<group>"; };
FF1162842BD00279000C4809 /* PlayerDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerDetailView.swift; sourceTree = "<group>"; };
FF1162862BD004AD000C4809 /* EditingTeamView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditingTeamView.swift; sourceTree = "<group>"; };
FF1162892BD05247000C4809 /* DateUpdateManagerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateUpdateManagerView.swift; sourceTree = "<group>"; };
FF11628B2BD05267000C4809 /* LoserRoundStepScheduleEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoserRoundStepScheduleEditorView.swift; sourceTree = "<group>"; };
FF1CBC182BB53D1F0036DAAB /* FederalTournament.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FederalTournament.swift; sourceTree = "<group>"; };
FF1CBC1C2BB53DC10036DAAB /* Calendar+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Calendar+Extensions.swift"; sourceTree = "<group>"; };
FF1CBC1E2BB53E0C0036DAAB /* FederalTournamentSearchScope.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FederalTournamentSearchScope.swift; sourceTree = "<group>"; };
@ -794,6 +798,14 @@
path = Cashier;
sourceTree = "<group>";
};
FF1162882BD0523B000C4809 /* Components */ = {
isa = PBXGroup;
children = (
FF1162892BD05247000C4809 /* DateUpdateManagerView.swift */,
);
path = Components;
sourceTree = "<group>";
};
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 = "<group>";
@ -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 */,

@ -53,7 +53,7 @@ struct GenericDestinationPickerView<T: Identifiable & Selectable>: 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<T: Identifiable & Selectable>: View {
Color(.systemBackground)
.clipShape(.circle)
)
.offset(x: 5, y: 5)
.offset(x: 3, y: 3)
}
}
}

@ -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
}
}
}

@ -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 {

@ -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)

@ -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))
}
}

@ -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)
}

@ -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

@ -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
}
}

Loading…
Cancel
Save