From a2eed6d4eb5805f9790687f70019ec1abbf65272 Mon Sep 17 00:00:00 2001 From: Raz Date: Tue, 29 Apr 2025 20:02:30 +0200 Subject: [PATCH 1/4] add remaining amount in event / tournament --- PadelClub/Data/Tournament.swift | 8 +++++ .../Views/Cashier/CashierDetailView.swift | 34 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index 9c32551..a1afae1 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -1425,6 +1425,14 @@ defer { return 0.0 } } + + func remainingAmount() -> Double { + if let entryFee { + return Double(selectedPlayers().filter { $0.hasPaid() == false }.count) * entryFee + } else { + return 0.0 + } + } func paidCompletion() -> Double { let selectedPlayers = selectedPlayers() diff --git a/PadelClub/Views/Cashier/CashierDetailView.swift b/PadelClub/Views/Cashier/CashierDetailView.swift index 0f1c8a1..100a39e 100644 --- a/PadelClub/Views/Cashier/CashierDetailView.swift +++ b/PadelClub/Views/Cashier/CashierDetailView.swift @@ -10,6 +10,7 @@ import SwiftUI struct CashierDetailView: View { var tournaments : [Tournament] @State private var earnings: Double? = nil + @State private var remainingAmount: Double? = nil @State private var paidCompletion: Double? = nil init(tournaments: [Tournament]) { @@ -24,6 +25,16 @@ struct CashierDetailView: View { List { if tournaments.count > 1 { Section { + LabeledContent { + if let remainingAmount { + Text(remainingAmount.formatted(.currency(code: Locale.defaultCurrency()).precision(.fractionLength(0)))) + } else { + ProgressView() + } + } label: { + Text("Reste à encaisser") + } + LabeledContent { if let earnings { Text(earnings.formatted(.currency(code: Locale.defaultCurrency()).precision(.fractionLength(0)))) @@ -57,10 +68,18 @@ struct CashierDetailView: View { if paidCompletion == nil { _getPaidCompletion() } + + if remainingAmount == nil { + _getRemainingAmount() + } } } } + private func _getRemainingAmount() { + remainingAmount = tournaments.map { $0.remainingAmount() }.reduce(0,+) + } + private func _getEarnings() { earnings = tournaments.map { $0.earnings() }.reduce(0,+) } @@ -88,11 +107,22 @@ struct CashierDetailView: View { let tournament: Tournament let showTournamentTitle: Bool @State private var earnings: Double? = nil + @State private var remainingAmount: Double? = nil @State private var paidCompletion: Double? = nil @State private var presence: Double? = nil var body: some View { Section { + LabeledContent { + if let remainingAmount { + Text(remainingAmount.formatted(.currency(code: Locale.defaultCurrency()).precision(.fractionLength(0)))) + } else { + ProgressView() + } + } label: { + Text("Reste à encaisser") + } + LabeledContent { if let earnings { Text(earnings.formatted(.currency(code: Locale.defaultCurrency()).precision(.fractionLength(0)))) @@ -130,6 +160,10 @@ struct CashierDetailView: View { if presence == nil { presence = tournament.presenceStatus() } + + if remainingAmount == nil { + remainingAmount = tournament.remainingAmount() + } } } } From ccf6b05e0d27cb297984b30d5c0a5beb8d9090d2 Mon Sep 17 00:00:00 2001 From: Raz Date: Thu, 1 May 2025 07:51:05 +0200 Subject: [PATCH 2/4] add losing group stage position selection consolante --- PadelClub/Data/Tournament.swift | 8 +++ .../ConsolationTournamentImportView.swift | 56 +++++++++++++++---- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index a1afae1..1153333 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -2485,6 +2485,14 @@ defer { } } + + func groupStageLosingPositions() -> [Int] { + guard let maxSize = groupStages().map({ $0.size }).max() else { + return [] + } + let leftInterval = qualifiedPerGroupStage + 1 + return Array(leftInterval...maxSize) + } // MARK: - Payments & Crypto diff --git a/PadelClub/Views/Tournament/ConsolationTournamentImportView.swift b/PadelClub/Views/Tournament/ConsolationTournamentImportView.swift index 835e416..59dcfd2 100644 --- a/PadelClub/Views/Tournament/ConsolationTournamentImportView.swift +++ b/PadelClub/Views/Tournament/ConsolationTournamentImportView.swift @@ -16,6 +16,7 @@ struct ConsolationTournamentImportView: View { @State private var selectedTournament: Tournament? @State private var selectedImportSelector: ImportSelector = .groupStage @State private var selectedImportType: ImportType = .losers + @State private var selectedGroupStagePosition: Set = Set() enum ImportType: Int, Identifiable, CaseIterable { case losers @@ -134,6 +135,36 @@ struct ConsolationTournamentImportView: View { Text("Type") } } + + if selectedImportSelector == .groupStage, selectedImportType == .losers { + NavigationLink { + List(selection: $selectedGroupStagePosition) { + ForEach(selectedTournament.groupStageLosingPositions()) { position in + let text: String = "\(position)" + position.ordinalFormattedSuffix() + Text(text) + .tag(position) + } + } + .environment(\.editMode, Binding.constant(EditMode.active)) + .navigationTitle("Position des poules") + .navigationBarTitleDisplayMode(.inline) + .toolbarBackground(.visible, for: .navigationBar) + } label: { + LabeledContent { + if selectedGroupStagePosition.isEmpty { + Text("Tous les perdants") + } else { + let value: String = selectedGroupStagePosition.map({ position in + let text: String = "\(position)" + position.ordinalFormattedSuffix() + return text + }).joined(separator: ", ") + Text(value) + } + } label: { + Text("Sélection des positions") + } + } + } } } @@ -154,16 +185,15 @@ struct ConsolationTournamentImportView: View { let teams = _teamsToImport(selectedTournament: selectedTournament) - Section { - RowButtonView("Importer les équipes") { - await _importTeams(selectedTournament: selectedTournament, teams: teams) - dismiss() - } - .disabled(teams.isEmpty) - } footer: { - if teams.isEmpty { - Text("Aucune équipe détectée").foregroundStyle(.logoRed) + if teams.isEmpty == false { + Section { + RowButtonView("Importer les \(teams.count) équipes") { + await _importTeams(selectedTournament: selectedTournament, teams: teams) + dismiss() + } } + } else { + Text("Aucune équipe à importer").foregroundStyle(.logoRed) } } } @@ -185,7 +215,13 @@ struct ConsolationTournamentImportView: View { teams = selectedTournament.groupStageTeams().filter({ switch selectedImportType { case .losers: - return $0.qualified == false + if selectedGroupStagePosition.isEmpty { + return $0.qualified == false + } else if let position = $0.groupStagePosition { + return $0.qualified == false && selectedGroupStagePosition.contains(position) + } else { + return $0.qualified == false + } case .winners: return $0.qualified case .all: From f7a208cc6bdbb3cccbb4d059a9e91a77e3d87545 Mon Sep 17 00:00:00 2001 From: Raz Date: Thu, 1 May 2025 07:53:08 +0200 Subject: [PATCH 3/4] 1.2.20 --- PadelClub.xcodeproj/project.pbxproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index 51f606e..6db343c 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -3726,7 +3726,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.19; + MARKETING_VERSION = 1.2.20; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -3772,7 +3772,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.19; + MARKETING_VERSION = 1.2.20; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -3891,7 +3891,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.19; + MARKETING_VERSION = 1.2.20; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -3936,7 +3936,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.19; + MARKETING_VERSION = 1.2.20; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -3980,7 +3980,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.19; + MARKETING_VERSION = 1.2.20; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub.beta; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -4022,7 +4022,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.19; + MARKETING_VERSION = 1.2.20; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub.beta; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; From 5a79d6ed6ab13013ae0726c9832211413670fe44 Mon Sep 17 00:00:00 2001 From: Raz Date: Thu, 1 May 2025 08:13:47 +0200 Subject: [PATCH 4/4] update delete account navigation --- PadelClub/Views/User/AccountView.swift | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/PadelClub/Views/User/AccountView.swift b/PadelClub/Views/User/AccountView.swift index 539a2d4..82ab45b 100644 --- a/PadelClub/Views/User/AccountView.swift +++ b/PadelClub/Views/User/AccountView.swift @@ -35,10 +35,25 @@ struct AccountView: View { } } Section { - RowButtonView("Supprimer mon compte", role: .destructive, confirmationMessage: "Voulez-vous vraiment supprimer définitivement votre compte et ses données associées ?") { - DataStore.shared.deleteAccount() -// handler() + NavigationLink { + List { + Section { + Text("Attention la suppression de votre compte est irréversible. Vous perdrez l'accès à tous vos tournois créés jusqu'à présent.").foregroundStyle(.logoRed).bold() + } + + RowButtonView("Supprimer mon compte", role: .destructive, confirmationMessage: "Voulez-vous vraiment supprimer définitivement votre compte et ses données associées ?") { + DataStore.shared.deleteAccount() + } + } + .navigationTitle("Supprimer votre compte") + .navigationBarTitleDisplayMode(.inline) + .toolbarBackground(.visible, for: .navigationBar) + .toolbarBackground(.logoRed, for: .navigationBar) + } label: { + Text("Suppression du compte") } + } header: { + Text("Accéder à l'écran de suppression de compte.") } }.navigationTitle(user.username) }