From aff79f892fc05635328462891b851c9e33b3e4fc Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Wed, 29 May 2024 17:57:23 +0200 Subject: [PATCH] fix stuff --- PadelClub/Data/GroupStage.swift | 1 - PadelClub/Data/Match.swift | 12 +- PadelClub/Data/MatchScheduler.swift | 4 + PadelClub/Data/TeamRegistration.swift | 10 ++ PadelClub/Data/TeamScore.swift | 10 +- PadelClub/Data/Tournament.swift | 7 +- PadelClub/Views/Cashier/CashierView.swift | 2 +- PadelClub/Views/Club/ClubDetailView.swift | 8 + .../GroupStage/GroupStageSettingsView.swift | 2 + .../Views/GroupStage/GroupStageView.swift | 5 + .../Match/Components/MatchDateView.swift | 5 +- PadelClub/Views/Match/MatchDetailView.swift | 1 + PadelClub/Views/Navigation/MainView.swift | 9 + .../Navigation/Ongoing/OngoingView.swift | 2 +- .../Navigation/Toolbox/ToolboxView.swift | 6 + .../Views/Navigation/Umpire/UmpireView.swift | 21 +-- .../Views/Planning/PlanningSettingsView.swift | 7 +- .../Tournament/Screen/BroadcastView.swift | 162 +++++++++--------- .../TournamentClubSettingsView.swift | 7 + .../Screen/InscriptionManagerView.swift | 11 +- .../Tournament/Screen/PrintSettingsView.swift | 5 +- .../Screen/TournamentCashierView.swift | 2 +- .../Views/Tournament/TournamentInitView.swift | 7 +- PadelClubTests/ServerDataTests.swift | 11 +- 24 files changed, 196 insertions(+), 121 deletions(-) diff --git a/PadelClub/Data/GroupStage.swift b/PadelClub/Data/GroupStage.swift index 58d15ba..c1efdbe 100644 --- a/PadelClub/Data/GroupStage.swift +++ b/PadelClub/Data/GroupStage.swift @@ -179,7 +179,6 @@ class GroupStage: ModelObject, Storable { } func availableToStart(playedMatches: [Match], in runningMatches: [Match]) -> [Match] { - return [] return playedMatches.filter({ $0.canBeStarted(inMatches: runningMatches) && $0.isRunning() == false }) } diff --git a/PadelClub/Data/Match.swift b/PadelClub/Data/Match.swift index 492cfdd..33f3b28 100644 --- a/PadelClub/Data/Match.swift +++ b/PadelClub/Data/Match.swift @@ -36,8 +36,9 @@ class Match: ModelObject, Storable { //var order: Int var disabled: Bool = false private(set) var courtIndex: Int? + var confirmed: Bool = false - internal init(round: String? = nil, groupStage: String? = nil, startDate: Date? = nil, endDate: Date? = nil, index: Int, matchFormat: MatchFormat? = nil, servingTeamId: String? = nil, winningTeamId: String? = nil, losingTeamId: String? = nil, name: String? = nil, disabled: Bool = false, courtIndex: Int? = nil) { + internal init(round: String? = nil, groupStage: String? = nil, startDate: Date? = nil, endDate: Date? = nil, index: Int, matchFormat: MatchFormat? = nil, servingTeamId: String? = nil, winningTeamId: String? = nil, losingTeamId: String? = nil, name: String? = nil, disabled: Bool = false, courtIndex: Int? = nil, confirmed: Bool = false) { self.round = round self.groupStage = groupStage self.startDate = startDate @@ -51,6 +52,7 @@ class Match: ModelObject, Storable { self.disabled = disabled self.name = name self.courtIndex = courtIndex + self.confirmed = confirmed // self.broadcasted = broadcasted // self.order = order } @@ -162,6 +164,7 @@ class Match: ModelObject, Storable { func cleanScheduleAndSave(_ targetStartDate: Date? = nil) { startDate = targetStartDate + confirmed = targetStartDate == nil ? false : true endDate = nil followingMatch()?.cleanScheduleAndSave(nil) _loserMatch()?.cleanScheduleAndSave(nil) @@ -548,6 +551,8 @@ class Match: ModelObject, Storable { startDate = fromStartDate endDate = toEndDate } + + confirmed = true } func courtName() -> String? { @@ -734,7 +739,7 @@ class Match: ModelObject, Storable { } func isRunning() -> Bool { // at least a match has started - hasStarted() && hasEnded() == false + confirmed && hasStarted() && hasEnded() == false } func hasStarted() -> Bool { // meaning at least one match is over @@ -785,6 +790,7 @@ class Match: ModelObject, Storable { case _name = "name" // case _order = "order" case _disabled = "disabled" + case _confirmed = "confirmed" } func encode(to encoder: Encoder) throws { @@ -855,6 +861,8 @@ class Match: ModelObject, Storable { } else { try container.encodeNil(forKey: ._courtIndex) } + + try container.encode(confirmed, forKey: ._confirmed) } func insertOnServer() throws { diff --git a/PadelClub/Data/MatchScheduler.swift b/PadelClub/Data/MatchScheduler.swift index cda8c45..a85429a 100644 --- a/PadelClub/Data/MatchScheduler.swift +++ b/PadelClub/Data/MatchScheduler.swift @@ -90,6 +90,7 @@ class MatchScheduler : ModelObject, Storable { matches.forEach({ $0.removeCourt() $0.startDate = nil + $0.confirmed = false }) var lastDate : Date = tournament.startDate @@ -565,6 +566,7 @@ class MatchScheduler : ModelObject, Storable { if (roundId == nil && matchId == nil) || $0.startDate?.isEarlierThan(startDate) == false { $0.startDate = nil $0.removeCourt() + $0.confirmed = false } }) @@ -590,6 +592,7 @@ class MatchScheduler : ModelObject, Storable { flattenedMatches[index...].forEach { $0.startDate = nil $0.removeCourt() + $0.confirmed = false } } } else if let roundId { @@ -598,6 +601,7 @@ class MatchScheduler : ModelObject, Storable { flattenedMatches[index...].forEach { $0.startDate = nil $0.removeCourt() + $0.confirmed = false } } } diff --git a/PadelClub/Data/TeamRegistration.swift b/PadelClub/Data/TeamRegistration.swift index 6319671..98466c3 100644 --- a/PadelClub/Data/TeamRegistration.swift +++ b/PadelClub/Data/TeamRegistration.swift @@ -69,6 +69,16 @@ class TeamRegistration: ModelObject, Storable { try Store.main.deleteDependencies(items: self.unsortedPlayers()) } + func hasArrived() { + let unsortedPlayers = unsortedPlayers() + unsortedPlayers.forEach({ $0.hasArrived = true }) + do { + try DataStore.shared.playerRegistrations.addOrUpdate(contentOfs: unsortedPlayers) + } catch { + Logger.error(error) + } + } + func isSeedable() -> Bool { bracketPosition == nil && groupStage == nil } diff --git a/PadelClub/Data/TeamScore.swift b/PadelClub/Data/TeamScore.swift index dfadc9f..84411cc 100644 --- a/PadelClub/Data/TeamScore.swift +++ b/PadelClub/Data/TeamScore.swift @@ -17,15 +17,15 @@ class TeamScore: ModelObject, Storable { var id: String = Store.randomId() var match: String var teamRegistration: String? - var playerRegistrations: [String] = [] + //var playerRegistrations: [String] = [] var score: String? var walkOut: Int? var luckyLoser: Int? - init(match: String, teamRegistration: String? = nil, playerRegistrations: [String], score: String? = nil, walkOut: Int? = nil, luckyLoser: Int? = nil) { + init(match: String, teamRegistration: String? = nil, score: String? = nil, walkOut: Int? = nil, luckyLoser: Int? = nil) { self.match = match self.teamRegistration = teamRegistration - self.playerRegistrations = playerRegistrations +// self.playerRegistrations = playerRegistrations self.score = score self.walkOut = walkOut self.luckyLoser = luckyLoser @@ -65,7 +65,7 @@ class TeamScore: ModelObject, Storable { case _id = "id" case _match = "match" case _teamRegistration = "teamRegistration" - case _playerRegistrations = "playerRegistrations" + //case _playerRegistrations = "playerRegistrations" case _score = "score" case _walkOut = "walkOut" case _luckyLoser = "luckyLoser" @@ -83,7 +83,7 @@ class TeamScore: ModelObject, Storable { try container.encodeNil(forKey: ._teamRegistration) } - try container.encode(playerRegistrations, forKey: ._playerRegistrations) + //try container.encode(playerRegistrations, forKey: ._playerRegistrations) if let score = score { try container.encode(score, forKey: ._score) diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index ad91e47..e0e7e2e 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -50,6 +50,7 @@ class Tournament : ModelObject, Storable { var publishBrackets: Bool = false var shouldVerifyGroupStage: Bool = false var shouldVerifyBracket: Bool = false + var hideTeamsWeight: Bool = false @ObservationIgnored var navigationPath: [Screen] = [] @@ -94,9 +95,10 @@ class Tournament : ModelObject, Storable { case _publishBrackets = "publishBrackets" case _shouldVerifyGroupStage = "shouldVerifyGroupStage" case _shouldVerifyBracket = "shouldVerifyBracket" + case _hideTeamsWeight = "hideTeamsWeight" } - internal init(event: String? = nil, name: String? = nil, startDate: Date = Date(), endDate: Date? = nil, creationDate: Date = Date(), isPrivate: Bool = false, groupStageFormat: MatchFormat? = nil, roundFormat: MatchFormat? = nil, loserRoundFormat: MatchFormat? = nil, groupStageSortMode: GroupStageOrderingMode, groupStageCount: Int = 4, rankSourceDate: Date? = nil, dayDuration: Int = 1, teamCount: Int = 24, teamSorting: TeamSortingType? = nil, federalCategory: TournamentCategory, federalLevelCategory: TournamentLevel, federalAgeCategory: FederalTournamentAge, closedRegistrationDate: Date? = nil, groupStageAdditionalQualified: Int = 0, courtCount: Int = 2, prioritizeClubMembers: Bool = false, qualifiedPerGroupStage: Int = 1, teamsPerGroupStage: Int = 4, entryFee: Double? = nil, additionalEstimationDuration: Int = 0, isDeleted: Bool = false, publishTeams: Bool = false, publishSummons: Bool = false, publishGroupStages: Bool = false, publishBrackets: Bool = false, shouldVerifyBracket: Bool = false, shouldVerifyGroupStage: Bool = false) { + internal init(event: String? = nil, name: String? = nil, startDate: Date = Date(), endDate: Date? = nil, creationDate: Date = Date(), isPrivate: Bool = false, groupStageFormat: MatchFormat? = nil, roundFormat: MatchFormat? = nil, loserRoundFormat: MatchFormat? = nil, groupStageSortMode: GroupStageOrderingMode, groupStageCount: Int = 4, rankSourceDate: Date? = nil, dayDuration: Int = 1, teamCount: Int = 24, teamSorting: TeamSortingType? = nil, federalCategory: TournamentCategory, federalLevelCategory: TournamentLevel, federalAgeCategory: FederalTournamentAge, closedRegistrationDate: Date? = nil, groupStageAdditionalQualified: Int = 0, courtCount: Int = 2, prioritizeClubMembers: Bool = false, qualifiedPerGroupStage: Int = 1, teamsPerGroupStage: Int = 4, entryFee: Double? = nil, additionalEstimationDuration: Int = 0, isDeleted: Bool = false, publishTeams: Bool = false, publishSummons: Bool = false, publishGroupStages: Bool = false, publishBrackets: Bool = false, shouldVerifyBracket: Bool = false, shouldVerifyGroupStage: Bool = false, hideTeamsWeight: Bool = false) { self.event = event self.name = name self.startDate = startDate @@ -130,6 +132,7 @@ class Tournament : ModelObject, Storable { self.publishGroupStages = publishGroupStages self.shouldVerifyBracket = shouldVerifyBracket self.shouldVerifyGroupStage = shouldVerifyGroupStage + self.hideTeamsWeight = hideTeamsWeight } required init(from decoder: Decoder) throws { @@ -170,6 +173,7 @@ class Tournament : ModelObject, Storable { publishBrackets = try container.decodeIfPresent(Bool.self, forKey: ._publishBrackets) ?? false shouldVerifyBracket = try container.decodeIfPresent(Bool.self, forKey: ._shouldVerifyBracket) ?? false shouldVerifyGroupStage = try container.decodeIfPresent(Bool.self, forKey: ._shouldVerifyGroupStage) ?? false + hideTeamsWeight = try container.decodeIfPresent(Bool.self, forKey: ._hideTeamsWeight) ?? false } fileprivate static let _numberFormatter: NumberFormatter = NumberFormatter() @@ -281,6 +285,7 @@ class Tournament : ModelObject, Storable { try container.encode(publishGroupStages, forKey: ._publishGroupStages) try container.encode(shouldVerifyBracket, forKey: ._shouldVerifyBracket) try container.encode(shouldVerifyGroupStage, forKey: ._shouldVerifyGroupStage) + try container.encode(hideTeamsWeight, forKey: ._hideTeamsWeight) } fileprivate func _encodePayment(container: inout KeyedEncodingContainer) throws { diff --git a/PadelClub/Views/Cashier/CashierView.swift b/PadelClub/Views/Cashier/CashierView.swift index bed78fe..e3c107e 100644 --- a/PadelClub/Views/Cashier/CashierView.swift +++ b/PadelClub/Views/Cashier/CashierView.swift @@ -21,7 +21,7 @@ struct CashierView: View { init(tournament: Tournament, teams: [TeamRegistration]) { self.tournaments = [tournament] self.teams = teams - if tournament.hasEnded(), tournament.paidCompletion() < 100.0 { + if tournament.hasEnded(), tournament.players().anySatisfy({ $0.hasPaid() == false }) { _filterOption = .init(wrappedValue: .didNotPay) } if teams.filter({ $0.callDate != nil }).isEmpty { diff --git a/PadelClub/Views/Club/ClubDetailView.swift b/PadelClub/Views/Club/ClubDetailView.swift index 5b64730..538b021 100644 --- a/PadelClub/Views/Club/ClubDetailView.swift +++ b/PadelClub/Views/Club/ClubDetailView.swift @@ -142,6 +142,14 @@ struct ClubDetailView: View { ClubCourtSetupView(club: club, displayContext: displayContext, selectedCourt: $selectedCourt) + if let padelClubLink = club.shareURL() { + Section { + Link(destination: padelClubLink) { + Text("Accéder au club sur le site Padel Club") + } + } + } + if let federalLink = club.federalLink() { Section { LabeledContent("Code Club") { diff --git a/PadelClub/Views/GroupStage/GroupStageSettingsView.swift b/PadelClub/Views/GroupStage/GroupStageSettingsView.swift index e31a1cc..0d902f8 100644 --- a/PadelClub/Views/GroupStage/GroupStageSettingsView.swift +++ b/PadelClub/Views/GroupStage/GroupStageSettingsView.swift @@ -105,6 +105,7 @@ struct GroupStageSettingsView: View { tournament.deleteGroupStages() tournament.buildGroupStages() generationDone = true + tournament.shouldVerifyGroupStage = false _save() } } @@ -115,6 +116,7 @@ struct GroupStageSettingsView: View { tournament.groupStageOrderingMode = mode tournament.refreshGroupStages() generationDone = true + tournament.shouldVerifyGroupStage = false _save() } } diff --git a/PadelClub/Views/GroupStage/GroupStageView.swift b/PadelClub/Views/GroupStage/GroupStageView.swift index 0500678..1631bae 100644 --- a/PadelClub/Views/GroupStage/GroupStageView.swift +++ b/PadelClub/Views/GroupStage/GroupStageView.swift @@ -150,6 +150,11 @@ struct GroupStageView: View { } } } + .contextMenu { + Button("équipe présente") { + team.hasArrived() + } + } } .listRowView(isActive: team.qualified, color: .master) } else { diff --git a/PadelClub/Views/Match/Components/MatchDateView.swift b/PadelClub/Views/Match/Components/MatchDateView.swift index 67144e9..86a7829 100644 --- a/PadelClub/Views/Match/Components/MatchDateView.swift +++ b/PadelClub/Views/Match/Components/MatchDateView.swift @@ -29,10 +29,12 @@ struct MatchDateView: View { if match.startDate == nil && isReady { Button("Démarrer") { match.startDate = Date() + match.confirmed = true _save() } Button("Échauffement") { match.startDate = Calendar.current.date(byAdding: .minute, value: 5, to: Date()) + match.confirmed = true _save() } } else { @@ -40,6 +42,7 @@ struct MatchDateView: View { Button("Démarrer maintenant") { match.startDate = Date() match.endDate = nil + match.confirmed = true _save() } } else { @@ -69,7 +72,7 @@ struct MatchDateView: View { if showPrefix { Text("en cours").font(.footnote).foregroundStyle(.secondary) } - if match.isReady() { + if match.isReady() && match.confirmed { Text(startDate, style: .timer) .monospacedDigit() .foregroundStyle(Color.master) diff --git a/PadelClub/Views/Match/MatchDetailView.swift b/PadelClub/Views/Match/MatchDetailView.swift index cf7000f..bffc314 100644 --- a/PadelClub/Views/Match/MatchDetailView.swift +++ b/PadelClub/Views/Match/MatchDetailView.swift @@ -300,6 +300,7 @@ struct MatchDetailView: View { Button(role: .destructive) { match.startDate = nil match.endDate = nil + match.confirmed = false save() } label: { Text("Supprimer l'horaire") diff --git a/PadelClub/Views/Navigation/MainView.swift b/PadelClub/Views/Navigation/MainView.swift index 6ca28c7..97540ce 100644 --- a/PadelClub/Views/Navigation/MainView.swift +++ b/PadelClub/Views/Navigation/MainView.swift @@ -44,6 +44,10 @@ struct MainView: View { } )} + var matches: [Match] { + dataStore.matches.filter({ $0.confirmed && $0.startDate != nil && $0.endDate == nil && $0.courtIndex != nil }) + } + var body: some View { TabView(selection: selectedTabHandler) { ActivityView() @@ -52,10 +56,15 @@ struct MainView: View { .tabItem(for: .tournamentOrganizer) OngoingView() .tabItem(for: .ongoing) + .badge(matches.count) ToolboxView() .tabItem(for: .toolbox) UmpireView() .tabItem(for: .umpire) +// .badge( +// Text("!") +// .font(.headline) +// ) // PadelClubView() // .tabItem(for: .padelClub) } diff --git a/PadelClub/Views/Navigation/Ongoing/OngoingView.swift b/PadelClub/Views/Navigation/Ongoing/OngoingView.swift index 0b4c24c..53785d0 100644 --- a/PadelClub/Views/Navigation/Ongoing/OngoingView.swift +++ b/PadelClub/Views/Navigation/Ongoing/OngoingView.swift @@ -18,7 +18,7 @@ struct OngoingView: View { var matches: [Match] { let sorting = sortByField ? fieldSorting : defaultSorting let now = Date() - return dataStore.matches.filter({ $0.startDate != nil && $0.startDate! < now && $0.endDate == nil && $0.courtIndex != nil }).sorted(using: sorting, order: .ascending) + return dataStore.matches.filter({ $0.confirmed && $0.startDate != nil && $0.endDate == nil && $0.courtIndex != nil }).sorted(using: sorting, order: .ascending) } var body: some View { diff --git a/PadelClub/Views/Navigation/Toolbox/ToolboxView.swift b/PadelClub/Views/Navigation/Toolbox/ToolboxView.swift index 72aff1c..a0b83cf 100644 --- a/PadelClub/Views/Navigation/Toolbox/ToolboxView.swift +++ b/PadelClub/Views/Navigation/Toolbox/ToolboxView.swift @@ -82,6 +82,12 @@ struct ToolboxView: View { } #endif + Section { + Link(destination: URLs.main.url) { + Text("Accéder au site Padel Club") + } + } + Section { NavigationLink { SelectablePlayerListView() diff --git a/PadelClub/Views/Navigation/Umpire/UmpireView.swift b/PadelClub/Views/Navigation/Umpire/UmpireView.swift index fcef6b2..20e9b70 100644 --- a/PadelClub/Views/Navigation/Umpire/UmpireView.swift +++ b/PadelClub/Views/Navigation/Umpire/UmpireView.swift @@ -65,6 +65,16 @@ struct UmpireView: View { if let currentPlayerData { //todo palmares ImportedPlayerView(player: currentPlayerData) + .contextMenu { + Button("Copier ma licence") { + UIPasteboard.general.string = currentPlayerData.formattedLicense() + } + + Button("Supprimer ma fiche") { + dataStore.user.licenceId = nil + self.dataStore.saveUser() + } + } // NavigationLink { // // } label: { @@ -75,18 +85,9 @@ struct UmpireView: View { presentSearchView = true } } - } header: { - if currentPlayerData != nil { - Text("Ma fiche joueur") - } } footer: { if dataStore.user.licenceId == nil { Text("Si vous avez participé à un tournoi dans les 12 derniers mois, Padel Club peut vous retrouver.") - } else { - Button("supprimer", role: .destructive) { - dataStore.user.licenceId = nil - self.dataStore.saveUser() - } } } @@ -181,11 +182,11 @@ struct UmpireView: View { do { try dataStore.clubs.addOrUpdate(instance: userClub) user.setUserClub(userClub) - self.dataStore.saveUser() } catch { Logger.error(error) } } + self.dataStore.saveUser() } }) } diff --git a/PadelClub/Views/Planning/PlanningSettingsView.swift b/PadelClub/Views/Planning/PlanningSettingsView.swift index 8d61aad..d01280b 100644 --- a/PadelClub/Views/Planning/PlanningSettingsView.swift +++ b/PadelClub/Views/Planning/PlanningSettingsView.swift @@ -104,7 +104,10 @@ struct PlanningSettingsView: View { Section { RowButtonView("Supprimer tous les horaires", role: .destructive) { do { - allMatches.forEach({ $0.startDate = nil }) + allMatches.forEach({ + $0.startDate = nil + $0.confirmed = false + }) try dataStore.matches.addOrUpdate(contentOfs: allMatches) allGroupStages.forEach({ $0.startDate = nil }) @@ -126,7 +129,7 @@ struct PlanningSettingsView: View { if roundsWithDate.isEmpty == false { Text("Des dates de démarrages ont été indiqué pour les manches et seront prises en compte.") } - RowButtonView("Horaire intelligent", role: .destructive, confirmationMessage: "L") { + RowButtonView("Horaire intelligent", role: .destructive) { schedulingDone = false await _setupSchedule() _save() diff --git a/PadelClub/Views/Tournament/Screen/BroadcastView.swift b/PadelClub/Views/Tournament/Screen/BroadcastView.swift index 458f839..c7e1235 100644 --- a/PadelClub/Views/Tournament/Screen/BroadcastView.swift +++ b/PadelClub/Views/Tournament/Screen/BroadcastView.swift @@ -40,118 +40,120 @@ struct BroadcastView: View { .tipStyle(tint: nil) } - Section { - LabeledContent { - if tournament.areTeamsPublished() { - Image(systemName:"checkmark").foregroundStyle(.green) - } else { - Text(tournament.publishedTeamsDate().formatted()) - } - } label: { - if tournament.areTeamsPublished() { - Text("Publiée") - } else { - Text("Publication prévue") - } - } - - Toggle(isOn: $tournament.hideTeamsWeight) { - Text("Masquer les poids des équipes") - } - } header: { - Text("Liste des équipes") - } footer: { - if Date() < tournament.publishedTeamsDate() { - HStack { - Spacer() - FooterButtonView(tournament.publishTeams ? "masquer sur le site" : "publier maintenant") { - tournament.publishTeams.toggle() - } - } - } - } - - Section { - LabeledContent { - if tournament.areSummonsPublished() { - Image(systemName:"checkmark").foregroundStyle(.green) - } else { - Text(tournament.publishedTeamsDate().formatted()) - } - } label: { - if tournament.areSummonsPublished() { - Text("Publiées") - } else { - Text("Publication prévue") - } - } - } header: { - Text("Convocations") - } footer: { - if Date() < tournament.publishedTeamsDate() { - HStack { - Spacer() - FooterButtonView(tournament.publishSummons ? "masquer sur le site" : "publier maintenant") { - tournament.publishSummons.toggle() - } - } - } - } - - if let publishedGroupStagesDate = tournament.publishedGroupStagesDate() { + if tournament.isPrivate == false { Section { - let areGroupStagesPublished = tournament.areGroupStagesPublished() LabeledContent { - if areGroupStagesPublished { + if tournament.areTeamsPublished() { Image(systemName:"checkmark").foregroundStyle(.green) } else { - Text(publishedGroupStagesDate.formatted()) + Text(tournament.publishedTeamsDate().formatted()) } } label: { - if areGroupStagesPublished { - Text("Publiées") + if tournament.areTeamsPublished() { + Text("Publiée") } else { Text("Publication prévue") } } + + Toggle(isOn: $tournament.hideTeamsWeight) { + Text("Masquer les poids des équipes") + } } header: { - Text("Poules") + Text("Liste des équipes") } footer: { - if Date() < publishedGroupStagesDate { + if Date() < tournament.publishedTeamsDate() { HStack { Spacer() - FooterButtonView(tournament.publishGroupStages ? "masquer sur le site" : "publier maintenant") { - tournament.publishGroupStages.toggle() + FooterButtonView(tournament.publishTeams ? "masquer sur le site" : "publier maintenant") { + tournament.publishTeams.toggle() } } } } - } - - if let publishedBracketsDate = tournament.publishedBracketsDate() { + Section { - let areBracketsPublished = tournament.areBracketsPublished() LabeledContent { - if areBracketsPublished { + if tournament.areSummonsPublished() { Image(systemName:"checkmark").foregroundStyle(.green) } else { - Text(publishedBracketsDate.formatted()) + Text(tournament.publishedTeamsDate().formatted()) } } label: { - if areBracketsPublished { - Text("Publié") + if tournament.areSummonsPublished() { + Text("Publiées") } else { Text("Publication prévue") } } } header: { - Text("Tableau") + Text("Convocations") } footer: { - if Date() < publishedBracketsDate { + if Date() < tournament.publishedTeamsDate() { HStack { Spacer() - FooterButtonView(tournament.publishBrackets ? "masquer sur le site" : "publier maintenant") { - tournament.publishBrackets.toggle() + FooterButtonView(tournament.publishSummons ? "masquer sur le site" : "publier maintenant") { + tournament.publishSummons.toggle() + } + } + } + } + + if let publishedGroupStagesDate = tournament.publishedGroupStagesDate() { + Section { + let areGroupStagesPublished = tournament.areGroupStagesPublished() + LabeledContent { + if areGroupStagesPublished { + Image(systemName:"checkmark").foregroundStyle(.green) + } else { + Text(publishedGroupStagesDate.formatted()) + } + } label: { + if areGroupStagesPublished { + Text("Publiées") + } else { + Text("Publication prévue") + } + } + } header: { + Text("Poules") + } footer: { + if Date() < publishedGroupStagesDate { + HStack { + Spacer() + FooterButtonView(tournament.publishGroupStages ? "masquer sur le site" : "publier maintenant") { + tournament.publishGroupStages.toggle() + } + } + } + } + } + + if let publishedBracketsDate = tournament.publishedBracketsDate() { + Section { + let areBracketsPublished = tournament.areBracketsPublished() + LabeledContent { + if areBracketsPublished { + Image(systemName:"checkmark").foregroundStyle(.green) + } else { + Text(publishedBracketsDate.formatted()) + } + } label: { + if areBracketsPublished { + Text("Publié") + } else { + Text("Publication prévue") + } + } + } header: { + Text("Tableau") + } footer: { + if Date() < publishedBracketsDate { + HStack { + Spacer() + FooterButtonView(tournament.publishBrackets ? "masquer sur le site" : "publier maintenant") { + tournament.publishBrackets.toggle() + } } } } diff --git a/PadelClub/Views/Tournament/Screen/Components/TournamentClubSettingsView.swift b/PadelClub/Views/Tournament/Screen/Components/TournamentClubSettingsView.swift index d49d35f..2cf4816 100644 --- a/PadelClub/Views/Tournament/Screen/Components/TournamentClubSettingsView.swift +++ b/PadelClub/Views/Tournament/Screen/Components/TournamentClubSettingsView.swift @@ -52,6 +52,13 @@ struct TournamentClubSettingsView: View { Section { TournamentFieldsManagerView(localizedStringKey: "Terrains pour le tournoi", count: $tournament.courtCount) + .onChange(of: tournament.courtCount) { + do { + try dataStore.tournaments.addOrUpdate(instance: tournament) + } catch { + Logger.error(error) + } + } if let event = tournament.eventObject() { NavigationLink { diff --git a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift index 4835e18..a0b6373 100644 --- a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift +++ b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift @@ -135,8 +135,9 @@ struct InscriptionManagerView: View { } } .onAppear { - if self.teamsHash == nil { - self.teamsHash = _simpleHash(ids: tournament.selectedSortedTeams().map { $0.id }) + let selectedSortedTeams = tournament.selectedSortedTeams() + if self.teamsHash == nil, selectedSortedTeams.isEmpty == false { + self.teamsHash = _simpleHash(ids: selectedSortedTeams.map { $0.id }) } } .onDisappear { @@ -424,6 +425,11 @@ struct InscriptionManagerView: View { let teamIndex = team.index(in: sortedTeams) Section { TeamDetailView(team: team) + .contextMenu { + Button("équipe présente") { + team.hasArrived() + } + } } header: { TeamHeaderView(team: team, teamIndex: teamIndex, tournament: tournament) } footer: { @@ -606,7 +612,6 @@ struct InscriptionManagerView: View { private func _informationView(count: Int) -> some View { Section { - let unsortedTeams = tournament.unsortedTeams() let walkoutTeams = tournament.walkoutTeams() let unsortedTeamsWithoutWO = tournament.unsortedTeamsWithoutWO() diff --git a/PadelClub/Views/Tournament/Screen/PrintSettingsView.swift b/PadelClub/Views/Tournament/Screen/PrintSettingsView.swift index 7aa4216..2f669e7 100644 --- a/PadelClub/Views/Tournament/Screen/PrintSettingsView.swift +++ b/PadelClub/Views/Tournament/Screen/PrintSettingsView.swift @@ -72,10 +72,7 @@ struct PrintSettingsView: View { } label: { Text("Aperçu du tableau") } - } - - ForEach(tournament.groupStages()) { groupStage in - Section { + ForEach(tournament.groupStages()) { groupStage in NavigationLink { WebView(htmlRawData: HtmlService.groupstage(groupStage: groupStage).html(headName: generator.displayHeads, withRank: generator.displayRank, withScore: false), loadStatusChanged: { loaded, error, webView in if let error { diff --git a/PadelClub/Views/Tournament/Screen/TournamentCashierView.swift b/PadelClub/Views/Tournament/Screen/TournamentCashierView.swift index 6fea6a1..1c2fdbe 100644 --- a/PadelClub/Views/Tournament/Screen/TournamentCashierView.swift +++ b/PadelClub/Views/Tournament/Screen/TournamentCashierView.swift @@ -100,7 +100,7 @@ struct TournamentCashierView: View { init(tournament: Tournament) { self.tournament = tournament if tournament.hasEnded() { - if tournament.paidCompletion() == 100.0 { + if tournament.players().anySatisfy({ $0.hasPaid() == false }) == false { _selectedDestination = .init(wrappedValue: .summary) } else { _selectedDestination = .init(wrappedValue: .all(tournament)) diff --git a/PadelClub/Views/Tournament/TournamentInitView.swift b/PadelClub/Views/Tournament/TournamentInitView.swift index 89e7678..c96ff3f 100644 --- a/PadelClub/Views/Tournament/TournamentInitView.swift +++ b/PadelClub/Views/Tournament/TournamentInitView.swift @@ -43,8 +43,11 @@ struct TournamentInitView: View { NavigationLink(value: Screen.broadcast) { LabeledContent { - Image(systemName: tournament.isPrivate ? "tv.slash" : "checkmark") - .foregroundStyle(tournament.isPrivate ? .logoRed : .green) + if tournament.isPrivate { + Text("tournoi privé").foregroundStyle(.logoRed) + } else { + Text("Automatique") + } } label: { Text("Publication") } diff --git a/PadelClubTests/ServerDataTests.swift b/PadelClubTests/ServerDataTests.swift index eacd7c3..6b92cc5 100644 --- a/PadelClubTests/ServerDataTests.swift +++ b/PadelClubTests/ServerDataTests.swift @@ -255,7 +255,7 @@ final class ServerDataTests: XCTestCase { let rounds: [Round] = try await Store.main.service().get() let parentRoundId = rounds.first?.id - let match: Match = Match(round: parentRoundId, groupStage: nil, startDate: Date(), endDate: Date(), index: 2, matchFormat: MatchFormat.twoSets, servingTeamId: teamRegistrationId, winningTeamId: teamRegistrationId, losingTeamId: teamRegistrationId, disabled: true, courtIndex: 1) + let match: Match = Match(round: parentRoundId, groupStage: nil, startDate: Date(), endDate: Date(), index: 2, matchFormat: MatchFormat.twoSets, servingTeamId: teamRegistrationId, winningTeamId: teamRegistrationId, losingTeamId: teamRegistrationId, disabled: true, courtIndex: 1, confirmed: true) let m: Match = try await Store.main.service().post(match) assert(m.round == match.round) @@ -269,7 +269,8 @@ final class ServerDataTests: XCTestCase { assert(m.losingTeamId == match.losingTeamId) assert(m.disabled == match.disabled) assert(m.courtIndex == match.courtIndex) - + assert(m.confirmed == match.confirmed) + } func testTeamScore() async throws { @@ -284,15 +285,11 @@ final class ServerDataTests: XCTestCase { assertionFailure("missing teamRegistrations in database") return } - let playerRegistrations: [PlayerRegistration] = try await Store.main.service().get() - let regs = playerRegistrations.prefix(upTo: 2).map { $0.id } - - let teamScore = TeamScore(match: matchId, teamRegistration: teamRegistrationId, playerRegistrations: regs, score: "6/6", walkOut: 1, luckyLoser: 1) + let teamScore = TeamScore(match: matchId, teamRegistration: teamRegistrationId, score: "6/6", walkOut: 1, luckyLoser: 1) let ts: TeamScore = try await Store.main.service().post(teamScore) assert(ts.match == teamScore.match) assert(ts.teamRegistration == teamScore.teamRegistration) - assert(ts.playerRegistrations == teamScore.playerRegistrations) assert(ts.score == teamScore.score) assert(ts.walkOut == teamScore.walkOut) assert(ts.luckyLoser == teamScore.luckyLoser)