update groupstage views and fix lag

multistore
Razmig Sarkissian 2 years ago
parent d30e93c6f1
commit e39457f5ea
  1. 17
      PadelClub/Data/GroupStage.swift
  2. 9
      PadelClub/Data/Match.swift
  3. 2
      PadelClub/Views/Components/GenericDestinationPickerView.swift
  4. 2
      PadelClub/Views/Components/MatchListView.swift
  5. 209
      PadelClub/Views/GroupStage/GroupStageSettingsView.swift
  6. 56
      PadelClub/Views/GroupStage/GroupStageTeamView.swift
  7. 290
      PadelClub/Views/GroupStage/GroupStageView.swift
  8. 8
      PadelClub/Views/GroupStage/GroupStagesView.swift
  9. 7
      PadelClub/Views/Player/Components/EditablePlayerView.swift
  10. 7
      PadelClub/Views/Score/EditScoreView.swift
  11. 2
      PadelClub/Views/Tournament/TournamentRunningView.swift
  12. 2
      PadelClub/Views/Tournament/TournamentView.swift
  13. 8
      PadelClub/Views/ViewModifiers/ListRowViewModifier.swift

@ -94,6 +94,23 @@ class GroupStage: ModelObject, Storable {
} }
} }
func updateGroupStageState() {
if hasEnded(), let tournament = tournamentObject() {
do {
let teams = teams(true)
for (index, team) in teams {
team.qualified = index < tournament.qualifiedPerGroupStage
if team.bracketPosition != nil && team.qualified == false {
team.bracketPosition = nil
}
}
try DataStore.shared.teamRegistrations.addOrUpdate(contentOfs: teams)
} catch {
Logger.error(error)
}
}
}
func scoreLabel(forGroupStagePosition groupStagePosition: Int) -> (wins: String, losses: String, setsDifference: String?, gamesDifference: String?)? { func scoreLabel(forGroupStagePosition groupStagePosition: Int) -> (wins: String, losses: String, setsDifference: String?, gamesDifference: String?)? {
if let scoreData = _score(forGroupStagePosition: groupStagePosition, nilIfEmpty: true) { if let scoreData = _score(forGroupStagePosition: groupStagePosition, nilIfEmpty: true) {
let hideSetDifference = matchFormat.setsToWin == 1 let hideSetDifference = matchFormat.setsToWin == 1

@ -348,10 +348,7 @@ class Match: ModelObject, Storable {
winningTeamId = teamScoreWinning.teamRegistration winningTeamId = teamScoreWinning.teamRegistration
losingTeamId = teamScoreWalkout.teamRegistration losingTeamId = teamScoreWalkout.teamRegistration
groupStageObject?.updateGroupStageState()
// matchDescriptor.match?.tournament?.generateLoserBracket(for: matchDescriptor.match!.round, viewContext: viewContext, reset: false)
// matchDescriptor.match?.loserBracket?.generateLoserBracket(for: matchDescriptor.match!.round, viewContext: viewContext, reset: false)
// matchDescriptor.match?.currentTournament?.removeField(matchDescriptor.match?.fieldIndex)
} }
func setScore(fromMatchDescriptor matchDescriptor: MatchDescriptor) { func setScore(fromMatchDescriptor matchDescriptor: MatchDescriptor) {
@ -359,11 +356,9 @@ class Match: ModelObject, Storable {
if endDate == nil { if endDate == nil {
endDate = Date() endDate = Date()
} }
// matchDescriptor.match?.tournament?.generateLoserBracket(for: matchDescriptor.match!.round, viewContext: viewContext, reset: false)
// matchDescriptor.match?.loserBracket?.generateLoserBracket(for: matchDescriptor.match!.round, viewContext: viewContext, reset: false)
// matchDescriptor.match?.currentTournament?.removeField(matchDescriptor.match?.fieldIndex)
winningTeamId = team(matchDescriptor.winner)?.id winningTeamId = team(matchDescriptor.winner)?.id
losingTeamId = team(matchDescriptor.winner.otherTeam)?.id losingTeamId = team(matchDescriptor.winner.otherTeam)?.id
groupStageObject?.updateGroupStageState()
} }
func updateScore(fromMatchDescriptor matchDescriptor: MatchDescriptor) { func updateScore(fromMatchDescriptor matchDescriptor: MatchDescriptor) {

@ -21,8 +21,8 @@ struct GenericDestinationPickerView<T: Identifiable & Selectable>: View {
selectedDestination = nil selectedDestination = nil
} label: { } label: {
Image(systemName: "wrench.and.screwdriver") Image(systemName: "wrench.and.screwdriver")
.foregroundColor(selectedDestination == nil ? .white : .black)
} }
.foregroundStyle(selectedDestination == nil ? .primary : .secondary)
.padding() .padding()
.background { .background {
Circle() Circle()

@ -13,7 +13,7 @@ struct MatchListView: View {
let matches: [Match] let matches: [Match]
var matchViewStyle: MatchViewStyle = .sectionedStandardStyle var matchViewStyle: MatchViewStyle = .sectionedStandardStyle
@State private var isExpanded: Bool = true @State var isExpanded: Bool = true
@ViewBuilder @ViewBuilder
var body: some View { var body: some View {

@ -6,6 +6,7 @@
// //
import SwiftUI import SwiftUI
import LeStorage
struct GroupStageSettingsView: View { struct GroupStageSettingsView: View {
@EnvironmentObject var dataStore: DataStore @EnvironmentObject var dataStore: DataStore
@ -25,17 +26,16 @@ struct GroupStageSettingsView: View {
var body: some View { var body: some View {
List { List {
Toggle(isOn: $nameAlphabetical) { Section {
Text("Nommer les poules alphabétiquement")
}
Menu {
//menuAddGroupStage
menuBuildAllGroupStages menuBuildAllGroupStages
}
Section {
menuGenerateGroupStage(.random) menuGenerateGroupStage(.random)
}
Section {
menuGenerateGroupStage(.snake) menuGenerateGroupStage(.snake)
//menuGenerateGroupStage(.swiss)
} label: {
LabelOptions()
} }
if tournament.missingQualifiedFromGroupStages().isEmpty == false && tournament.qualifiedTeams().count >= tournament.qualifiedFromGroupStage() && tournament.groupStageAdditionalQualified > 0 { if tournament.missingQualifiedFromGroupStages().isEmpty == false && tournament.qualifiedTeams().count >= tournament.qualifiedFromGroupStage() && tournament.groupStageAdditionalQualified > 0 {
@ -52,115 +52,9 @@ struct GroupStageSettingsView: View {
} }
} }
// if (tournament.groupStagesAreWrong || (tournament.emptySlotInGroupStages > 0 && tournament.entriesCount >= tournament.teamsFromGroupStages)) { Toggle(isOn: $nameAlphabetical) {
// Section { Text("Nommer les poules alphabétiquement")
// RowButtonView("Reconstruire les poules") {
// confirmGroupStageRebuild = true
// }
// .modify {
// if UIDevice.current.userInterfaceIdiom == .pad {
// $0.alert("Êtes-vous sûr ?", isPresented: $confirmGroupStageRebuild) {
//
// Button(role: .destructive) {
// tournament.refreshGroupStages()
// save()
// } label: {
// Text("Reconstruire")
// }
//
//
// Button(role: .cancel) {
//
// } label: {
// Text("Annuler")
// }
// } message: {
// Text("Attention, cela peut modifier les poules existants.")
//
// }
// } else {
// $0.confirmationDialog("Êtes-vous sûr ?", isPresented: $confirmGroupStageRebuild) {
// Button(role: .destructive) {
// tournament.refreshGroupStages()
// save()
// } label: {
// Text("Reconstruire")
// }
// } message: {
// Text("Attention, cela peut modifier les poules existants.")
// }
// }
// }
// } header: {
// Text("Erreur détectée")
// }
// }
//
// if tournament.isRoundSwissTournament() == false && (tournament.orderedGroupStages.allSatisfy({ $0.orderedMatches.count > 0 }) == false && tournament.groupStagesAreOver == false && tournament.groupStagesCount > 0) {
// Section {
// RowButtonView("Générer les matchs de poules") {
// startAllGroupStageConfirmation = true
// }
// .modify {
// if UIDevice.current.userInterfaceIdiom == .pad {
// $0.alert("Êtes-vous sûr ?", isPresented: $startAllGroupStageConfirmation) {
// Button("Générer") {
// tournament.orderedGroupStages.forEach {
// if $0.orderedMatches.isEmpty {
// $0.startGroupStage()
// }
// }
// save()
// }
// Button(role: .cancel) {
//
// } label: {
// Text("Annuler")
// }
// }
//
// } else {
// $0.confirmationDialog("Êtes-vous sûr ?", isPresented: $startAllGroupStageConfirmation) {
// Button("Générer") {
// tournament.orderedGroupStages.forEach {
// if $0.orderedMatches.isEmpty {
// $0.startGroupStage()
// }
// }
// save()
// }
// }
// }
// }
// }
// }
//
if tournament.groupStagesAreOver() == false {
// Section {
// GroupStageMatchAvailableToStartView(tournament: tournament, groupStageIndex: selectedGroupStageIndex)
// } header: {
// if selectedGroupStageIndex == -1 {
// Text("Matchs de poules prêt à démarrer")
// } else {
// Text("Matchs de la poule \(selectedGroupStageIndex) prêt à démarrer")
// }
// } footer: {
// Text("présence d'au moins 2 équipes d'une même poule ayant réglé.")
// }
} }
// if tournament.teamsPerGroupStage == 3 && tournament.qualifiedPerGroupStage == 1 && tournament.numberOfGroupStages%2 == 0 && tournament.moreQualifiedFromGroupStages == 0 {
// Section {
// NavigationLink {
// GroupStageMissingMatchView(tournament: tournament)
// } label: {
// Text("Matchs de classement de poules")
// }
// }
// }
} }
.onChange(of: nameAlphabetical) { .onChange(of: nameAlphabetical) {
let groupStages = tournament.groupStages() let groupStages = tournament.groupStages()
@ -178,71 +72,30 @@ struct GroupStageSettingsView: View {
} }
var menuBuildAllGroupStages: some View { var menuBuildAllGroupStages: some View {
Button(role: .destructive) { RowButtonView("Refaire les poules", role: .destructive) {
tournament.deleteGroupStages() tournament.deleteGroupStages()
tournament.buildGroupStages() tournament.buildGroupStages()
} label: { _save()
Label("Refaire les poules", systemImage: "restart")
}
} }
}
@ViewBuilder
func menuGenerateGroupStage(_ mode: GroupStageOrderingMode) -> some View { @ViewBuilder
Button(role: .destructive) { func menuGenerateGroupStage(_ mode: GroupStageOrderingMode) -> some View {
tournament.groupStageOrderingMode = mode RowButtonView("Poule \(mode.localizedLabel().lowercased())", role: .destructive, systemImage: mode.systemImage) {
tournament.refreshGroupStages() tournament.groupStageOrderingMode = mode
//save() tournament.refreshGroupStages()
} label: { _save()
Label("Poule \(mode.localizedLabel().lowercased())", systemImage: mode.systemImage)
}
} }
}
// func addGroupStage(_ size: Int64) { private func _save() {
// let groupStage = GroupStage(context: viewContext) do {
// groupStage.index = tournament.firstIndexToUseForNewGroupStage try dataStore.tournaments.addOrUpdate(instance: tournament)
// groupStage.size = Int64(size) } catch {
// groupStage.matchFormatRawValue = tournament.groupStageMatchFormatRawValue Logger.error(error)
// print("addGroupStage groupStagesCount", tournament.groupStagesCount) }
// print("addGroupStage numberOfGroupStages", tournament.numberOfGroupStages) }
// if tournament.groupStagesCount >= tournament.numberOfGroupStages {
// tournament.numberOfGroupStages += 1
// }
// tournament.addToGroupStages(groupStage)
// save()
// }
//
// var menuAddGroupStage: some View {
// Menu {
// ForEach(-1...1) { index in
// let i = tournament.teamsPerGroupStage + Int64(index)
// Button {
// addGroupStage(i)
// } label: {
// Text("Poule de \(i)")
// }
// .disabled(i < 2)
// }
// } label: {
// Label("Ajouter une poule", systemImage: "server.rack")
// }
//
// }
// func save() {
// do {
// tournament.objectWillChange.send()
// try viewContext.save()
// viewContext.refreshAllObjects()
// } catch {
// // Replace this implementation with code to handle the error appropriately.
// // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
// let nsError = error as NSError
// fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
// }
// }
} }
#Preview { #Preview {

@ -15,21 +15,9 @@ struct GroupStageTeamView: View {
var body: some View { var body: some View {
List { List {
ForEach(team.players()) { player in Section {
Section { ForEach(team.players()) { player in
ImportedPlayerView(player: player) EditablePlayerView(player: player, editingOptions: [.licenceId, .payment])
} footer: {
HStack {
Button("contacter") {
}
Spacer()
Button {
player.hasArrived.toggle()
try? dataStore.playerRegistrations.addOrUpdate(instance: player)
} label: {
Label("présent", systemImage: player.hasArrived ? "checkmark.circle" : "circle")
}
}
} }
} }
@ -38,7 +26,7 @@ struct GroupStageTeamView: View {
if team.qualified == false { if team.qualified == false {
RowButtonView("Qualifier l'équipe") { RowButtonView("Qualifier l'équipe") {
team.qualified = true team.qualified = true
team.bracketPosition = nil // team.bracketPosition = nil
_save() _save()
} }
} }
@ -54,41 +42,13 @@ struct GroupStageTeamView: View {
} }
Section { Section {
// if let deltaLabel = bracket.tournament?.deltaLabel(index, bracketIndex: bracket.index.intValue) { RowButtonView("Remplacement") {
// Section {
// Button(role: .destructive) { }
// entrant.resetBracketPosition()
// save()
// } label: {
// Text(deltaLabel)
// }
// Divider()
// } header: {
// Text("Toute l'équipe, poids: " + entrant.updatedRank.formatted())
// }
// }
//
// ForEach(entrant.orderedPlayers) { player in
// if let deltaLabel = bracket.tournament?.playerDeltaLabel(rank: entrant.otherPlayer(player)?.currentRank, positionInBracket: index, bracketIndex: bracket.index.intValue) {
// Section {
// Button(role: .destructive) {
// entrant.team?.removeFromPlayers(player)
// save()
// } label: {
// Text(deltaLabel)
// }
// Divider()
// } header: {
// Text(player.longLabel + ", rang: " + player.formattedRank)
// }
// }
// }
} header: {
Text("Remplacement")
} }
Section { Section {
RowButtonView("Retirer de la poule") { RowButtonView("Retirer de la poule", role: .destructive) {
team.groupStagePosition = nil team.groupStagePosition = nil
team.groupStage = nil team.groupStage = nil
_save() _save()

@ -6,6 +6,7 @@
// //
import SwiftUI import SwiftUI
import LeStorage
struct GroupStageView: View { struct GroupStageView: View {
@EnvironmentObject var dataStore: DataStore @EnvironmentObject var dataStore: DataStore
@ -15,21 +16,7 @@ struct GroupStageView: View {
@State private var confirmRemoveAll: Bool = false @State private var confirmRemoveAll: Bool = false
@State private var confirmResetMatch: Bool = false @State private var confirmResetMatch: Bool = false
@State private var groupStageName: String = "" @State private var groupStageName: String = ""
private enum GroupStageSortingMode {
case auto
case score
case weight
}
var sortByScore: Bool {
sortingMode == .auto ? groupStage.hasEnded() : sortingMode == .score
}
func teamAt(atIndex index: Int) -> TeamRegistration? {
sortByScore ? groupStage.teams(sortByScore)[safe: index] : groupStage.teamAt(groupStagePosition: index)
}
init(groupStage: GroupStage) { init(groupStage: GroupStage) {
self.groupStage = groupStage self.groupStage = groupStage
_groupStageName = State(wrappedValue: groupStage.groupStageTitle()) _groupStageName = State(wrappedValue: groupStage.groupStageTitle())
@ -38,7 +25,7 @@ struct GroupStageView: View {
var body: some View { var body: some View {
List { List {
Section { Section {
_groupStageView() GroupStageScoreView(groupStage: groupStage, sortByScore: _sortByScore)
} header: { } header: {
if let startDate = groupStage.startDate { if let startDate = groupStage.startDate {
Text(startDate.formatted(Date.FormatStyle().weekday(.wide)).capitalized + " à partir de " + startDate.formattedAsHourMinute()) Text(startDate.formatted(Date.FormatStyle().weekday(.wide)).capitalized + " à partir de " + startDate.formattedAsHourMinute())
@ -47,19 +34,9 @@ struct GroupStageView: View {
HStack { HStack {
Spacer() Spacer()
Button { Button {
if sortingMode == .auto { _updateSortingMode()
if groupStage.hasEnded() {
sortingMode = .weight
} else {
sortingMode = .score
}
} else if sortingMode == .weight {
sortingMode = .score
} else {
sortingMode = .weight
}
} label: { } label: {
Label(sortByScore ? "tri par score" : "tri par poids", systemImage: "arrow.up.arrow.down").labelStyle(.titleOnly) Label(_sortByScore ? "tri par score" : "tri par poids", systemImage: "arrow.up.arrow.down").labelStyle(.titleOnly)
.underline() .underline()
} }
.buttonStyle(.borderless) .buttonStyle(.borderless)
@ -70,11 +47,11 @@ struct GroupStageView: View {
MatchListView(section: "disponible", matches: groupStage.availableToStart()).id(UUID()) MatchListView(section: "disponible", matches: groupStage.availableToStart()).id(UUID())
MatchListView(section: "en cours", matches: groupStage.runningMatches()).id(UUID()) MatchListView(section: "en cours", matches: groupStage.runningMatches()).id(UUID())
MatchListView(section: "à lancer", matches: groupStage.readyMatches()).id(UUID()) MatchListView(section: "à lancer", matches: groupStage.readyMatches()).id(UUID())
MatchListView(section: "terminés", matches: groupStage.finishedMatches()).id(UUID()) MatchListView(section: "terminés", matches: groupStage.finishedMatches(), isExpanded: false).id(UUID())
} }
.onChange(of: groupStageName) { .onChange(of: groupStageName) {
groupStage.name = groupStageName groupStage.name = groupStageName
try? dataStore.groupStages.addOrUpdate(instance: groupStage) _save()
} }
.toolbar { .toolbar {
ToolbarItem(placement: .topBarTrailing) { ToolbarItem(placement: .topBarTrailing) {
@ -84,65 +61,111 @@ struct GroupStageView: View {
.navigationTitle($groupStageName) .navigationTitle($groupStageName)
} }
private func _groupStageView() -> some View { private enum GroupStageSortingMode {
ForEach(0..<(groupStage.size), id: \.self) { index in case auto
if let team = teamAt(atIndex: index), let groupStagePosition = team.groupStagePosition { case score
NavigationLink { case weight
GroupStageTeamView(groupStage: groupStage, team: team) }
} label: {
HStack(alignment: .center) { private var _sortByScore: Bool {
sortingMode == .auto ? groupStage.hasEnded() : sortingMode == .score
}
private func _updateSortingMode() {
if sortingMode == .auto {
if groupStage.hasEnded() {
sortingMode = .weight
} else {
sortingMode = .score
}
} else if sortingMode == .weight {
sortingMode = .score
} else {
sortingMode = .weight
}
}
struct GroupStageScoreView: View {
@EnvironmentObject var dataStore: DataStore
let groupStage: GroupStage
let sortByScore: Bool
let teams: [TeamRegistration]
init(groupStage: GroupStage, sortByScore: Bool) {
self.groupStage = groupStage
self.sortByScore = sortByScore
self.teams = groupStage.teams(sortByScore)
}
private func _teamAt(atIndex index: Int) -> TeamRegistration? {
sortByScore ? teams[safe: index] : groupStage.teamAt(groupStagePosition: index)
}
var body: some View {
ForEach(0..<(groupStage.size), id: \.self) { index in
if let team = _teamAt(atIndex: index), let groupStagePosition = team.groupStagePosition {
NavigationLink {
GroupStageTeamView(groupStage: groupStage, team: team)
} label: {
VStack(alignment: .leading, spacing: 4.0) { VStack(alignment: .leading, spacing: 4.0) {
HStack(spacing: 6.0) { HStack(spacing: 6.0) {
Text("#\(groupStagePosition + 1)") Text("#\(groupStagePosition + 1)")
Text("Poids \(team.weight)") Text("Poids \(team.weight)")
Spacer()
if team.qualified {
Text("qualifié")
}
} }
.font(.footnote) .font(.footnote)
HStack { HStack {
if let teamName = team.name { if let teamName = team.name {
Text(teamName) Text(teamName).font(.title)
} else { } else {
VStack(alignment: .leading) { VStack(alignment: .leading) {
ForEach(team.players()) { player in ForEach(team.players()) { player in
Text(player.playerLabel()) Text(player.playerLabel()).lineLimit(1)
} }
} }
} }
Spacer()
if team.qualified { if let score = groupStage.scoreLabel(forGroupStagePosition: groupStagePosition) {
Image(systemName: "checkmark.seal") VStack(alignment: .trailing) {
} HStack(spacing: 0.0) {
} Text(score.wins)
} Text("/")
Spacer() Text(score.losses)
if let score = groupStage.scoreLabel(forGroupStagePosition: groupStagePosition) { }.font(.headline).monospacedDigit()
VStack(alignment: .center) { if let setsDifference = score.setsDifference {
HStack(spacing: 0.0) { HStack(spacing: 4.0) {
Text(score.wins) Text(setsDifference)
Text("/") Text("sets")
Text(score.losses) }.font(.footnote)
}.bold() }
if let setsDifference = score.setsDifference { if let gamesDifference = score.gamesDifference {
Text(setsDifference + " sets") HStack(spacing: 4.0) {
} Text(gamesDifference)
if let gamesDifference = score.gamesDifference { Text("jeux")
Text(gamesDifference + " jeux") }.font(.footnote)
}
}
} }
} }
} }
} }
} .listRowView(isActive: team.qualified, color: .master)
} else { } else {
HStack(alignment: .center) {
VStack(alignment: .leading, spacing: 0) { VStack(alignment: .leading, spacing: 0) {
HStack { Text("#\(index + 1)")
Text("#\(index + 1)") .font(.caption)
}
.font(.caption)
TeamPickerView(teamPicked: { team in TeamPickerView(teamPicked: { team in
print(team.pasteData()) print(team.pasteData())
team.groupStage = groupStage.id team.groupStage = groupStage.id
team.groupStagePosition = index team.groupStagePosition = index
try? dataStore.teamRegistrations.addOrUpdate(instance: team) do {
try dataStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}
}) })
} }
} }
@ -156,121 +179,15 @@ struct GroupStageView: View {
Button("Retirer le nom") { Button("Retirer le nom") {
groupStage.name = nil groupStage.name = nil
groupStageName = groupStage.groupStageTitle() groupStageName = groupStage.groupStageTitle()
try? dataStore.groupStages.addOrUpdate(instance: groupStage) _save()
} }
} }
// if groupStage.playedMatches().isEmpty {
// Button {
// //groupStage.startGroupStage()
// //save()
// } label: {
// Text("Créer les matchs")
// }
// .buttonStyle(.borderless)
// }
Button("Retirer tout le monde", role: .destructive) { Button("Retirer tout le monde", role: .destructive) {
confirmRemoveAll = true confirmRemoveAll = true
} }
Button("Recommencer tous les matchs", role: .destructive) { Button("Recommencer tous les matchs", role: .destructive) {
confirmResetMatch = true confirmResetMatch = true
} }
// Button {
// selectedMenuLink = .prepare
// } label: {
// Label("Préparer", systemImage: "calendar")
// }
//
// Menu {
// MenuWarnView(warningSender: groupStage)
// } label: {
// Label("Prévenir", systemImage: "person.crop.circle")
// }
//
// if groupStage.isBroadcasted() {
// Button {
// groupStage.refreshBroadcast()
// } label: {
// Label("Rafraîchir", systemImage: "arrow.up.circle.fill")
// }
// Button {
// groupStage.stopBroadcast()
// save()
// } label: {
// Label("Arrêter la diffusion", systemImage: "stop.circle.fill")
// }
// } else if groupStage.tournament?.canBroadcast() == true {
// Button {
// Task {
// try? await groupStage.broadcastGroupStage()
// save()
// }
// } label: {
// Label("Diffuser", systemImage: "airplayvideo")
// }
// }
//
// Divider()
// if groupStage.tournament?.canBroadcast() == true {
// Menu {
// Button {
// Task {
// try? await groupStage.broadcastGroupStageMatches()
// save()
// }
// } label: {
// Label("Diffuser", systemImage: "airplayvideo")
// }
//
// Button {
// groupStage.refreshBroadcastMatches()
// } label: {
// Label("Rafraîchir", systemImage: "arrow.up.circle.fill")
// }
// Button {
// groupStage.stopBroadcastMatches()
// save()
// } label: {
// Label("Arrêter la diffusion", systemImage: "stop.circle.fill")
// }
// } label: {
// Text("Diffusion des matchs")
// }
// }
//
// Divider()
// Menu {
// if groupStage.orderedMatches.isEmpty == false {
// Button(role: .destructive) {
// groupStage.startGroupStage()
// save()
// } label: {
// Label("Re-démarrer les matchs de la \(groupStage.titleLabel.lowercased())", systemImage: "trash")
// }
// }
//
// if groupStage.orderedMatches.isEmpty == false {
// Button(role: .destructive) {
// groupStage.removeMatches()
// save()
// } label: {
// Label("Supprimer les matchs de la \(groupStage.titleLabel.lowercased())", systemImage: "trash")
// }
// }
//
// Button(role: .destructive) {
// groupStage.tournament?.completeEntries.filter { $0.groupStagePosition == groupStage.index }.forEach { $0.resetGroupStagePosition() }
// groupStage.tournament?.removeFromGroupStages(groupStage)
// groupStage.tournament?.numberOfGroupStages -= 1
// save()
// } label: {
// Label("Supprimer la \(groupStage.titleLabel.lowercased())", systemImage: "trash")
// }
// } label: {
// Text("Éditer")
// }
} label: { } label: {
LabelOptions() LabelOptions()
} }
@ -281,7 +198,11 @@ struct GroupStageView: View {
team.groupStagePosition = nil team.groupStagePosition = nil
team.groupStage = nil team.groupStage = nil
} }
try? dataStore.teamRegistrations.addOrUpdate(contentOfs: teams) do {
try dataStore.teamRegistrations.addOrUpdate(contentOfs: teams)
} catch {
Logger.error(error)
}
} }
} }
.confirmationDialog("Êtes-vous sûr de vouloir faire cela ?", isPresented: $confirmResetMatch, titleVisibility: .visible) { .confirmationDialog("Êtes-vous sûr de vouloir faire cela ?", isPresented: $confirmResetMatch, titleVisibility: .visible) {
@ -292,18 +213,11 @@ struct GroupStageView: View {
} }
// func save() { private func _save() {
// do { do {
// groupStage.objectWillChange.send() try dataStore.groupStages.addOrUpdate(instance: groupStage)
// groupStage.tournament?.orderedGroupStages.forEach { $0.objectWillChange.send() } } catch {
// groupStage.tournament?.objectWillChange.send() Logger.error(error)
// }
// try viewContext.save() }
// } catch {
// // Replace this implementation with code to handle the error appropriately.
// // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
// let nsError = error as NSError
// fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
// }
// }
} }

@ -73,10 +73,10 @@ struct GroupStagesView: View {
let runningMatches = allGroupStages.flatMap({ $0.runningMatches() }) let runningMatches = allGroupStages.flatMap({ $0.runningMatches() })
let readyMatches = allGroupStages.flatMap({ $0.readyMatches() }) let readyMatches = allGroupStages.flatMap({ $0.readyMatches() })
let finishedMatches = allGroupStages.flatMap({ $0.finishedMatches() }) let finishedMatches = allGroupStages.flatMap({ $0.finishedMatches() })
MatchListView(section: "disponible", matches: availableToStart, matchViewStyle: .standardStyle) MatchListView(section: "disponible", matches: availableToStart, matchViewStyle: .standardStyle, isExpanded: false)
MatchListView(section: "en cours", matches: runningMatches, matchViewStyle: .standardStyle) MatchListView(section: "en cours", matches: runningMatches, matchViewStyle: .standardStyle, isExpanded: false)
MatchListView(section: "à lancer", matches: readyMatches, matchViewStyle: .standardStyle) MatchListView(section: "à lancer", matches: readyMatches, matchViewStyle: .standardStyle, isExpanded: false)
MatchListView(section: "terminés", matches: finishedMatches, matchViewStyle: .standardStyle) MatchListView(section: "terminés", matches: finishedMatches, matchViewStyle: .standardStyle, isExpanded: false)
} }
.navigationTitle("Toutes les poules") .navigationTitle("Toutes les poules")
case .groupStage(let groupStage): case .groupStage(let groupStage):

@ -74,6 +74,13 @@ struct EditablePlayerView: View {
} }
Section { Section {
Button {
player.hasArrived.toggle()
try? dataStore.playerRegistrations.addOrUpdate(instance: player)
} label: {
Label("présent", systemImage: player.hasArrived ? "checkmark.circle" : "circle")
}
Button { Button {
editedLicenceId = player.licenceId ?? "" editedLicenceId = player.licenceId ?? ""
shouldPresentLicenceIdEdition = true shouldPresentLicenceIdEdition = true

@ -6,6 +6,7 @@
// //
import SwiftUI import SwiftUI
import LeStorage
struct EditScoreView: View { struct EditScoreView: View {
@EnvironmentObject var dataStore: DataStore @EnvironmentObject var dataStore: DataStore
@ -102,7 +103,11 @@ struct EditScoreView: View {
func save() { func save() {
if let match = matchDescriptor.match { if let match = matchDescriptor.match {
try? dataStore.matches.addOrUpdate(instance: match) do {
try dataStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
} }
} }
} }

@ -75,7 +75,7 @@ struct TournamentRunningView: View {
MatchListView(section: "en cours", matches: tournament.runningMatches(allMatches)) MatchListView(section: "en cours", matches: tournament.runningMatches(allMatches))
// MatchListView(section: "à lancer", matches: tournament.readyMatches(allMatches)) // MatchListView(section: "à lancer", matches: tournament.readyMatches(allMatches))
// MatchListView(section: "disponible", matches: tournament.availableToStart(allMatches)) // MatchListView(section: "disponible", matches: tournament.availableToStart(allMatches))
MatchListView(section: "terminés", matches: tournament.finishedMatches(allMatches)) MatchListView(section: "terminés", matches: tournament.finishedMatches(allMatches), isExpanded: false)
} }
} }

@ -45,7 +45,7 @@ struct TournamentView: View {
} }
} }
} footer: { } footer: {
if tournament.inscriptionClosed() == false && tournament.state() == .build && tournament.unsortedTeams().isEmpty == false { if tournament.inscriptionClosed() == false && tournament.state() == .build && tournament.unsortedTeams().isEmpty == false && tournament.hasStarted() == false {
Button { Button {
tournament.lockRegistration() tournament.lockRegistration()
_save() _save()

@ -8,11 +8,11 @@
import SwiftUI import SwiftUI
struct ListRowViewModifier: ViewModifier { struct ListRowViewModifier: ViewModifier {
@State private var isActived = true let isActive: Bool
let color: Color let color: Color
func body(content: Content) -> some View { func body(content: Content) -> some View {
if isActived { if isActive {
content content
.listRowBackground( .listRowBackground(
color.variation() color.variation()
@ -27,7 +27,7 @@ struct ListRowViewModifier: ViewModifier {
} }
extension View { extension View {
func listRowView(color: Color) -> some View { func listRowView(isActive: Bool = true, color: Color) -> some View {
modifier(ListRowViewModifier(color: color)) modifier(ListRowViewModifier(isActive: isActive, color: color))
} }
} }

Loading…
Cancel
Save