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?)? {
if let scoreData = _score(forGroupStagePosition: groupStagePosition, nilIfEmpty: true) {
let hideSetDifference = matchFormat.setsToWin == 1

@ -348,10 +348,7 @@ class Match: ModelObject, Storable {
winningTeamId = teamScoreWinning.teamRegistration
losingTeamId = teamScoreWalkout.teamRegistration
// 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)
groupStageObject?.updateGroupStageState()
}
func setScore(fromMatchDescriptor matchDescriptor: MatchDescriptor) {
@ -359,11 +356,9 @@ class Match: ModelObject, Storable {
if endDate == nil {
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
losingTeamId = team(matchDescriptor.winner.otherTeam)?.id
groupStageObject?.updateGroupStageState()
}
func updateScore(fromMatchDescriptor matchDescriptor: MatchDescriptor) {

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

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

@ -6,6 +6,7 @@
//
import SwiftUI
import LeStorage
struct GroupStageSettingsView: View {
@EnvironmentObject var dataStore: DataStore
@ -25,17 +26,16 @@ struct GroupStageSettingsView: View {
var body: some View {
List {
Toggle(isOn: $nameAlphabetical) {
Text("Nommer les poules alphabétiquement")
}
Menu {
//menuAddGroupStage
Section {
menuBuildAllGroupStages
}
Section {
menuGenerateGroupStage(.random)
}
Section {
menuGenerateGroupStage(.snake)
//menuGenerateGroupStage(.swiss)
} label: {
LabelOptions()
}
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)) {
// Section {
// 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é.")
// }
Toggle(isOn: $nameAlphabetical) {
Text("Nommer les poules alphabétiquement")
}
// 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) {
let groupStages = tournament.groupStages()
@ -178,71 +72,30 @@ struct GroupStageSettingsView: View {
}
var menuBuildAllGroupStages: some View {
Button(role: .destructive) {
tournament.deleteGroupStages()
tournament.buildGroupStages()
} label: {
Label("Refaire les poules", systemImage: "restart")
}
var menuBuildAllGroupStages: some View {
RowButtonView("Refaire les poules", role: .destructive) {
tournament.deleteGroupStages()
tournament.buildGroupStages()
_save()
}
@ViewBuilder
func menuGenerateGroupStage(_ mode: GroupStageOrderingMode) -> some View {
Button(role: .destructive) {
tournament.groupStageOrderingMode = mode
tournament.refreshGroupStages()
//save()
} label: {
Label("Poule \(mode.localizedLabel().lowercased())", systemImage: mode.systemImage)
}
}
@ViewBuilder
func menuGenerateGroupStage(_ mode: GroupStageOrderingMode) -> some View {
RowButtonView("Poule \(mode.localizedLabel().lowercased())", role: .destructive, systemImage: mode.systemImage) {
tournament.groupStageOrderingMode = mode
tournament.refreshGroupStages()
_save()
}
}
// func addGroupStage(_ size: Int64) {
// let groupStage = GroupStage(context: viewContext)
// groupStage.index = tournament.firstIndexToUseForNewGroupStage
// groupStage.size = Int64(size)
// groupStage.matchFormatRawValue = tournament.groupStageMatchFormatRawValue
// 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)")
// }
// }
private func _save() {
do {
try dataStore.tournaments.addOrUpdate(instance: tournament)
} catch {
Logger.error(error)
}
}
}
#Preview {

@ -15,21 +15,9 @@ struct GroupStageTeamView: View {
var body: some View {
List {
ForEach(team.players()) { player in
Section {
ImportedPlayerView(player: player)
} 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")
}
}
Section {
ForEach(team.players()) { player in
EditablePlayerView(player: player, editingOptions: [.licenceId, .payment])
}
}
@ -38,7 +26,7 @@ struct GroupStageTeamView: View {
if team.qualified == false {
RowButtonView("Qualifier l'équipe") {
team.qualified = true
team.bracketPosition = nil
// team.bracketPosition = nil
_save()
}
}
@ -54,41 +42,13 @@ struct GroupStageTeamView: View {
}
Section {
// if let deltaLabel = bracket.tournament?.deltaLabel(index, bracketIndex: bracket.index.intValue) {
// 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")
RowButtonView("Remplacement") {
}
}
Section {
RowButtonView("Retirer de la poule") {
RowButtonView("Retirer de la poule", role: .destructive) {
team.groupStagePosition = nil
team.groupStage = nil
_save()

@ -6,6 +6,7 @@
//
import SwiftUI
import LeStorage
struct GroupStageView: View {
@EnvironmentObject var dataStore: DataStore
@ -15,21 +16,7 @@ struct GroupStageView: View {
@State private var confirmRemoveAll: Bool = false
@State private var confirmResetMatch: Bool = false
@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) {
self.groupStage = groupStage
_groupStageName = State(wrappedValue: groupStage.groupStageTitle())
@ -38,7 +25,7 @@ struct GroupStageView: View {
var body: some View {
List {
Section {
_groupStageView()
GroupStageScoreView(groupStage: groupStage, sortByScore: _sortByScore)
} header: {
if let startDate = groupStage.startDate {
Text(startDate.formatted(Date.FormatStyle().weekday(.wide)).capitalized + " à partir de " + startDate.formattedAsHourMinute())
@ -47,19 +34,9 @@ struct GroupStageView: View {
HStack {
Spacer()
Button {
if sortingMode == .auto {
if groupStage.hasEnded() {
sortingMode = .weight
} else {
sortingMode = .score
}
} else if sortingMode == .weight {
sortingMode = .score
} else {
sortingMode = .weight
}
_updateSortingMode()
} 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()
}
.buttonStyle(.borderless)
@ -70,11 +47,11 @@ struct GroupStageView: View {
MatchListView(section: "disponible", matches: groupStage.availableToStart()).id(UUID())
MatchListView(section: "en cours", matches: groupStage.runningMatches()).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) {
groupStage.name = groupStageName
try? dataStore.groupStages.addOrUpdate(instance: groupStage)
_save()
}
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
@ -84,65 +61,111 @@ struct GroupStageView: View {
.navigationTitle($groupStageName)
}
private func _groupStageView() -> 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: {
HStack(alignment: .center) {
private enum GroupStageSortingMode {
case auto
case score
case weight
}
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) {
HStack(spacing: 6.0) {
Text("#\(groupStagePosition + 1)")
Text("Poids \(team.weight)")
Spacer()
if team.qualified {
Text("qualifié")
}
}
.font(.footnote)
HStack {
if let teamName = team.name {
Text(teamName)
Text(teamName).font(.title)
} else {
VStack(alignment: .leading) {
ForEach(team.players()) { player in
Text(player.playerLabel())
Text(player.playerLabel()).lineLimit(1)
}
}
}
if team.qualified {
Image(systemName: "checkmark.seal")
}
}
}
Spacer()
if let score = groupStage.scoreLabel(forGroupStagePosition: groupStagePosition) {
VStack(alignment: .center) {
HStack(spacing: 0.0) {
Text(score.wins)
Text("/")
Text(score.losses)
}.bold()
if let setsDifference = score.setsDifference {
Text(setsDifference + " sets")
}
if let gamesDifference = score.gamesDifference {
Text(gamesDifference + " jeux")
Spacer()
if let score = groupStage.scoreLabel(forGroupStagePosition: groupStagePosition) {
VStack(alignment: .trailing) {
HStack(spacing: 0.0) {
Text(score.wins)
Text("/")
Text(score.losses)
}.font(.headline).monospacedDigit()
if let setsDifference = score.setsDifference {
HStack(spacing: 4.0) {
Text(setsDifference)
Text("sets")
}.font(.footnote)
}
if let gamesDifference = score.gamesDifference {
HStack(spacing: 4.0) {
Text(gamesDifference)
Text("jeux")
}.font(.footnote)
}
}
}
}
}
}
}
} else {
HStack(alignment: .center) {
.listRowView(isActive: team.qualified, color: .master)
} else {
VStack(alignment: .leading, spacing: 0) {
HStack {
Text("#\(index + 1)")
}
.font(.caption)
Text("#\(index + 1)")
.font(.caption)
TeamPickerView(teamPicked: { team in
print(team.pasteData())
team.groupStage = groupStage.id
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") {
groupStage.name = nil
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) {
confirmRemoveAll = true
}
Button("Recommencer tous les matchs", role: .destructive) {
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: {
LabelOptions()
}
@ -281,7 +198,11 @@ struct GroupStageView: View {
team.groupStagePosition = 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) {
@ -292,18 +213,11 @@ struct GroupStageView: View {
}
// func save() {
// do {
// groupStage.objectWillChange.send()
// groupStage.tournament?.orderedGroupStages.forEach { $0.objectWillChange.send() }
// groupStage.tournament?.objectWillChange.send()
//
// 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)")
// }
// }
private func _save() {
do {
try dataStore.groupStages.addOrUpdate(instance: groupStage)
} catch {
Logger.error(error)
}
}
}

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

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

@ -6,6 +6,7 @@
//
import SwiftUI
import LeStorage
struct EditScoreView: View {
@EnvironmentObject var dataStore: DataStore
@ -102,7 +103,11 @@ struct EditScoreView: View {
func save() {
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: "à lancer", matches: tournament.readyMatches(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: {
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 {
tournament.lockRegistration()
_save()

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

Loading…
Cancel
Save