From 1fc17d1992286a801815fe7be74baf3df98e157c Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Tue, 4 Jun 2024 17:53:22 +0200 Subject: [PATCH] fix stuff --- PadelClub/Data/Round.swift | 4 + PadelClub/Data/Tournament.swift | 5 + PadelClub/Utils/HtmlService.swift | 12 ++ PadelClub/Utils/SourceFileManager.swift | 4 +- PadelClub/Utils/Tips.swift | 109 +++++++++++++++++- PadelClub/Views/Navigation/MainView.swift | 2 +- .../Organizer/OrganizedTournamentView.swift | 6 +- .../Organizer/TournamentOrganizerView.swift | 2 +- .../Navigation/Umpire/PadelClubView.swift | 11 ++ PadelClub/Views/Round/RoundView.swift | 41 ++++++- .../Tournament/Screen/BroadcastView.swift | 29 +++-- 11 files changed, 204 insertions(+), 21 deletions(-) diff --git a/PadelClub/Data/Round.swift b/PadelClub/Data/Round.swift index 6926240..72cd29a 100644 --- a/PadelClub/Data/Round.swift +++ b/PadelClub/Data/Round.swift @@ -39,6 +39,10 @@ class Round: ModelObject, Storable { Store.main.filter { $0.round == self.id } } + func getDisabledMatches() -> [Match] { + Store.main.filter { $0.round == self.id && $0.disabled == true } + } + // MARK: - var matchFormat: MatchFormat { diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index 14c1c9e..aef0896 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -446,6 +446,11 @@ class Tournament : ModelObject, Storable { } func shareURL(_ pageLink: PageLink = .matches) -> URL? { +// if pageLink == .broadcast { +// if let club = club(), let broadcastCode = club.broadcastCode { +// +// } +// } return URLs.main.url.appending(path: "tournament/\(id)").appending(path: pageLink.path) } diff --git a/PadelClub/Utils/HtmlService.swift b/PadelClub/Utils/HtmlService.swift index 73fc31a..c083d34 100644 --- a/PadelClub/Utils/HtmlService.swift +++ b/PadelClub/Utils/HtmlService.swift @@ -88,6 +88,9 @@ enum HtmlService { } else { template = template.replacingOccurrences(of: "{{weightOne}}", with: "") } + } else { + template = template.replacingOccurrences(of: "{{playerOne}}", with: "--") + template = template.replacingOccurrences(of: "{{weightOne}}", with: "") } if let playerTwo = entrant.players()[safe: 1] { @@ -97,6 +100,9 @@ enum HtmlService { } else { template = template.replacingOccurrences(of: "{{weightTwo}}", with: "") } + } else { + template = template.replacingOccurrences(of: "{{playerTwo}}", with: "--") + template = template.replacingOccurrences(of: "{{weightTwo}}", with: "") } return template case .groupstageRow(let entrant, let teamsPerBracket): @@ -139,6 +145,9 @@ enum HtmlService { } else { template = template.replacingOccurrences(of: "{{weightOne}}", with: "") } + } else { + template = template.replacingOccurrences(of: "{{playerOne}}", with: "--") + template = template.replacingOccurrences(of: "{{weightOne}}", with: "") } if let playerTwo = entrant.players()[safe: 1] { @@ -148,6 +157,9 @@ enum HtmlService { } else { template = template.replacingOccurrences(of: "{{weightTwo}}", with: "") } + } else { + template = template.replacingOccurrences(of: "{{playerTwo}}", with: "--") + template = template.replacingOccurrences(of: "{{weightTwo}}", with: "") } return template case .hiddenPlayer: diff --git a/PadelClub/Utils/SourceFileManager.swift b/PadelClub/Utils/SourceFileManager.swift index 9e0c266..57fc1f3 100644 --- a/PadelClub/Utils/SourceFileManager.swift +++ b/PadelClub/Utils/SourceFileManager.swift @@ -113,8 +113,8 @@ class SourceFileManager { } - func getAllFiles() async { - let dates = monthsBetweenDates(startDateString: "08-2022", endDateString: Date().monthYearFormatted) + func getAllFiles(initialDate: String = "08-2022") async { + let dates = monthsBetweenDates(startDateString: initialDate, endDateString: Date().monthYearFormatted) .compactMap { URL.importDateFormatter.date(from: $0) } diff --git a/PadelClub/Utils/Tips.swift b/PadelClub/Utils/Tips.swift index 2a5abb4..bf609a9 100644 --- a/PadelClub/Utils/Tips.swift +++ b/PadelClub/Utils/Tips.swift @@ -440,13 +440,118 @@ struct CreateAccountTip: Tip { } } +struct SlideToDeleteSeedTip: Tip { + @Parameter + static var seeds: Int = 0 + + var rules: [Rule] { + [ + // Define a rule based on the app state. + #Rule(Self.$seeds) { + // Set the conditions for when the tip displays. + return $0 > 0 + } + ] + } + + var title: Text { + Text("Glisser pour effacer") + } + + var message: Text? { + Text("Vous pouvez retirer une tête de série de sa position en glissant votre doigt vers la gauche") + } + + var image: Image? { + Image(systemName: "person.fill.xmark") + } +} + +struct PrintTip: Tip { + @Parameter + static var seeds: Int = 0 + + var rules: [Rule] { + [ + // Define a rule based on the app state. + #Rule(Self.$seeds) { + // Set the conditions for when the tip displays. + return $0 > 0 + } + ] + } + + var title: Text { + Text("Coup d'oeil de votre tableau") + } + + var message: Text? { + Text("Vous pouvez avoir un aperçu de votre tableau ou l'imprimer.") + } + + var image: Image? { + Image(systemName: "printer") + } + + var actions: [Action] { + Action(id: ActionKey.printAction.rawValue, title: "Aperçu du tableau et option d'impression") + } + + enum ActionKey: String { + case printAction = "printAction" + } +} + +struct BracketEditTip: Tip { + @Parameter + static var matchesHidden: Int = 0 + + var nextRoundName: String? + + var rules: [Rule] { + [ + // Define a rule based on the app state. + #Rule(Self.$matchesHidden) { + // Set the conditions for when the tip displays. + return $0 > 0 + } + ] + } + + var title: Text { + Text("Désactivation automatique des matchs") + } + + var message: Text? { + let grammar = Self.matchesHidden == 1 ? "a" : "ont" + let article = Self.matchesHidden == 1 ? "la" : "les" + let wording = nextRoundName != nil ? "en \(nextRoundName!)" : "dans la manche suivante" + return Text("Padel Club a bien pris en compte \(article) tête\(Self.matchesHidden.pluralSuffix) de série positionnée\(Self.matchesHidden.pluralSuffix) \(wording). Le\(Self.matchesHidden.pluralSuffix) \(Self.matchesHidden) match\(Self.matchesHidden.pluralSuffix) inutile\(Self.matchesHidden.pluralSuffix) \(grammar) été désactivé automatiquement.") + } + + var image: Image? { + Image(systemName: "rectangle.slash") + } +} + struct TipStyleModifier: ViewModifier { @Environment(\.colorScheme) var colorScheme var tint: Color? var background: Color? + var asSection: Bool func body(content: Content) -> some View { + if asSection { + Section { + preparedContent(content: content) + } + } else { + preparedContent(content: content) + } + } + @ViewBuilder + func preparedContent(content: Content) -> some View { if let background { content .tint(.white) @@ -477,7 +582,7 @@ struct TipStyleModifier: ViewModifier { } extension View { - func tipStyle(tint: Color?, background: Color? = nil) -> some View { - modifier(TipStyleModifier(tint: tint, background: background)) + func tipStyle(tint: Color?, background: Color? = nil, asSection: Bool = false) -> some View { + modifier(TipStyleModifier(tint: tint, background: background, asSection: asSection)) } } diff --git a/PadelClub/Views/Navigation/MainView.swift b/PadelClub/Views/Navigation/MainView.swift index 9695d3f..8d9b1f2 100644 --- a/PadelClub/Views/Navigation/MainView.swift +++ b/PadelClub/Views/Navigation/MainView.swift @@ -150,7 +150,7 @@ struct MainView: View { } private func _downloadPreviousDate() async { - await SourceFileManager.shared.getAllFiles() + await SourceFileManager.shared.getAllFiles(initialDate: "05-2024") } } diff --git a/PadelClub/Views/Navigation/Organizer/OrganizedTournamentView.swift b/PadelClub/Views/Navigation/Organizer/OrganizedTournamentView.swift index 707b622..75e6a82 100644 --- a/PadelClub/Views/Navigation/Organizer/OrganizedTournamentView.swift +++ b/PadelClub/Views/Navigation/Organizer/OrganizedTournamentView.swift @@ -8,14 +8,10 @@ import SwiftUI struct OrganizedTournamentView: View { - let tournament: Tournament + @Bindable var tournament: Tournament var body: some View { - @Bindable var tournament = tournament NavigationStack(path: $tournament.navigationPath) { TournamentView(tournament: tournament, presentationContext: .organizer) -// .onChange(of: navigationPath) { -// tournament.navigationPath = navigationPath -// } } } } diff --git a/PadelClub/Views/Navigation/Organizer/TournamentOrganizerView.swift b/PadelClub/Views/Navigation/Organizer/TournamentOrganizerView.swift index 46bd65b..44a4699 100644 --- a/PadelClub/Views/Navigation/Organizer/TournamentOrganizerView.swift +++ b/PadelClub/Views/Navigation/Organizer/TournamentOrganizerView.swift @@ -15,7 +15,7 @@ struct TournamentOrganizerView: View { var body: some View { VStack(spacing: 0) { if let tournament = navigation.organizerTournament { - OrganizedTournamentView(tournament: tournament) + OrganizedTournamentView(tournament: tournament).id(tournament.id) } else { NavigationStack { let userClubsEmpty = dataStore.user.clubs.isEmpty diff --git a/PadelClub/Views/Navigation/Umpire/PadelClubView.swift b/PadelClub/Views/Navigation/Umpire/PadelClubView.swift index cb3f9e9..c8339a5 100644 --- a/PadelClub/Views/Navigation/Umpire/PadelClubView.swift +++ b/PadelClub/Views/Navigation/Umpire/PadelClubView.swift @@ -92,6 +92,11 @@ struct PadelClubView: View { } } + Section { + RowButtonView("Télécharger les données des mois précédents", role: .destructive) { _downloadPreviousDate() + } + } + if importingFiles { ContentUnavailableView("Importation en cours", systemImage: "server.rack", description: Text("Une importation des données fédérales publiques est en cours, veuillez patienter.")) } else if (players.isEmpty || lastDataSource == nil) { @@ -226,6 +231,12 @@ struct PadelClubView: View { viewContext.refreshAllObjects() } } + + private func _downloadPreviousDate() { + Task { + await SourceFileManager.shared.getAllFiles(initialDate: "08-2022") + } + } } #Preview { diff --git a/PadelClub/Views/Round/RoundView.swift b/PadelClub/Views/Round/RoundView.swift index a88fcbb..6231590 100644 --- a/PadelClub/Views/Round/RoundView.swift +++ b/PadelClub/Views/Round/RoundView.swift @@ -7,16 +7,20 @@ import SwiftUI import LeStorage +import TipKit struct RoundView: View { @Environment(\.isEditingTournamentSeed) private var isEditingTournamentSeed @Environment(Tournament.self) var tournament: Tournament @EnvironmentObject var dataStore: DataStore + @Environment(NavigationViewModel.self) private var navigation: NavigationViewModel + @State private var selectedSeedGroup: SeedInterval? @State private var spaceLeft: [Match] = [] @State private var seedSpaceLeft: [Match] = [] @State private var availableSeedGroup: SeedInterval? - + @State private var showPrintScreen: Bool = false + private func _getAvailableSeedGroup() async { availableSeedGroup = tournament.seedGroupAvailable(atRoundIndex: round.index) } @@ -55,6 +59,12 @@ struct RoundView: View { } } else if isEditingTournamentSeed.wrappedValue == false { //(where: { $0.isDisabled() == false || isEditingTournamentSeed.wrappedValue }) + let printTip = PrintTip() + TipView(printTip) { actions in + showPrintScreen = true + } + .tipStyle(tint: .master, asSection: true) + if loserRounds.isEmpty == false { let correspondingLoserRoundTitle = round.correspondingLoserRoundTitle() Section { @@ -68,6 +78,22 @@ struct RoundView: View { } } } else { + let disabledMatchesCount = BracketEditTip.matchesHidden + if disabledMatchesCount > 0 { + let bracketTip = BracketEditTip(nextRoundName: round.nextRound()?.roundTitle()) + TipView(bracketTip).tipStyle(tint: .green, asSection: true) + + Section { + let leftToPlay = (RoundRule.numberOfMatches(forRoundIndex: round.index) - disabledMatchesCount) + LabeledContent { + Text(leftToPlay.formatted()).font(.largeTitle) + } label: { + Text("Match\(leftToPlay.pluralSuffix) à jouer \(round.roundTitle(.short))") + Text("\(disabledMatchesCount) match\(disabledMatchesCount.pluralSuffix) désactivé\(disabledMatchesCount.pluralSuffix) automatiquement") + } + } + } + let availableSeeds = tournament.availableSeeds() let availableQualifiedTeams = tournament.availableQualifiedTeams() @@ -191,6 +217,12 @@ struct RoundView: View { } } } + + if isEditingTournamentSeed.wrappedValue == true { + let slideToDelete = SlideToDeleteSeedTip() + TipView(slideToDelete).tipStyle(tint: .logoRed, asSection: true) + } + ForEach(displayableMatches) { match in Section { MatchRowView(match: match, matchViewStyle: .sectionedStandardStyle) @@ -217,10 +249,17 @@ struct RoundView: View { } } } + .navigationDestination(isPresented: $showPrintScreen) { + PrintSettingsView(tournament: tournament) + } .onAppear { Task { await _prepareRound() } + let seeds = round.seeds() + SlideToDeleteSeedTip.seeds = seeds.count + PrintTip.seeds = seeds.count + BracketEditTip.matchesHidden = round.getDisabledMatches().count } .fullScreenCover(isPresented: showVisualDrawView) { if let availableSeedGroup = selectedSeedGroup { diff --git a/PadelClub/Views/Tournament/Screen/BroadcastView.swift b/PadelClub/Views/Tournament/Screen/BroadcastView.swift index caf27f2..61ae60f 100644 --- a/PadelClub/Views/Tournament/Screen/BroadcastView.swift +++ b/PadelClub/Views/Tournament/Screen/BroadcastView.swift @@ -63,6 +63,26 @@ struct BroadcastView: View { } if tournament.isPrivate == false { + if let url = tournament.shareURL(.broadcast) { + Section { + Link(destination: url) { + Text(url.absoluteString).font(.largeTitle) + } + .contextMenu { + Button("Copier") { + let pasteboard = UIPasteboard.general + pasteboard.string = url.absoluteString + } + actionForURL(url) + } + } header: { + Text("Lien pour la diffusion TV") + } footer: { + Text("Lien à mettre sur une smart tv ou ordinateur dans le club house par exemple !") + } + } + + Section { LabeledContent { if tournament.isTournamentPublished() { @@ -258,15 +278,6 @@ struct BroadcastView: View { Text("Modifier la page du tournoi à partager") } .pickerStyle(.menu) - - if let url = tournament.shareURL(.broadcast) { - LabeledContent { - actionForURL(url) - } label: { - Text("TV") - } - } - } header: { Text("Liens à partager") .textCase(nil)