parent
2183f2863f
commit
8fdeff82f1
@ -0,0 +1,226 @@ |
||||
// |
||||
// MyAccountView.swift |
||||
// PadelClub |
||||
// |
||||
// Created by Razmig Sarkissian on 01/03/2024. |
||||
// |
||||
|
||||
import SwiftUI |
||||
import CoreLocation |
||||
import LeStorage |
||||
import StoreKit |
||||
import PadelClubData |
||||
|
||||
struct MyAccountView: View { |
||||
|
||||
@Environment(NavigationViewModel.self) private var navigation: NavigationViewModel |
||||
@EnvironmentObject var dataStore: DataStore |
||||
|
||||
@State private var showSubscriptions: Bool = false |
||||
@State private var showProductIds: Bool = false |
||||
|
||||
@FocusState private var focusedField: CustomUser.CodingKeys? |
||||
|
||||
// @State var isConnected: Bool = false |
||||
|
||||
enum AccountScreen { |
||||
case login |
||||
} |
||||
|
||||
var body: some View { |
||||
@Bindable var navigation = navigation |
||||
NavigationStack(path: $navigation.accountPath) { |
||||
List { |
||||
Section { |
||||
SupportButtonView(supportButtonType: .bugReport, showIcon: true) |
||||
} |
||||
|
||||
PurchaseListView() |
||||
|
||||
Section { |
||||
Button { |
||||
self.showSubscriptions = true |
||||
} label: { |
||||
Label("Les offres", systemImage: "bookmark.fill") |
||||
}.simultaneousGesture( |
||||
LongPressGesture() |
||||
.onEnded { _ in |
||||
self.showProductIds = true |
||||
} |
||||
) |
||||
|
||||
.highPriorityGesture( |
||||
TapGesture() |
||||
.onEnded { _ in |
||||
self.showSubscriptions = true |
||||
} |
||||
) |
||||
|
||||
} |
||||
|
||||
if StoreCenter.main.isAuthenticated { |
||||
NavigationLink { |
||||
AccountView(user: dataStore.user) { } |
||||
} label: { |
||||
AccountRowView(userName: dataStore.user.username) |
||||
} |
||||
} else { |
||||
NavigationLink(value: AccountScreen.login) { |
||||
AccountRowView(userName: dataStore.user.username) |
||||
} |
||||
} |
||||
|
||||
if StoreCenter.main.isAuthenticated { |
||||
let onlineRegPaymentMode = dataStore.user.registrationPaymentMode |
||||
Section { |
||||
LabeledContent { |
||||
switch onlineRegPaymentMode { |
||||
case .corporate: |
||||
Text("Activé") |
||||
.bold() |
||||
.foregroundStyle(.green) |
||||
case .disabled: |
||||
Text("Désactivé") |
||||
.bold() |
||||
case .noFee: |
||||
Text("Activé") |
||||
.bold() |
||||
.foregroundStyle(.green) |
||||
case .stripe: |
||||
Text("Activé") |
||||
.bold() |
||||
.foregroundStyle(.green) |
||||
} |
||||
} label: { |
||||
Text("Option 'Paiement en ligne'") |
||||
if onlineRegPaymentMode == .corporate { |
||||
Text("Mode Padel Club") |
||||
.foregroundStyle(.secondary) |
||||
} else if onlineRegPaymentMode == .noFee { |
||||
Text("Commission Stripe") |
||||
.foregroundStyle(.secondary) |
||||
} else if onlineRegPaymentMode == .stripe { |
||||
Text("Commission Stripe et Padel Club") |
||||
.foregroundStyle(.secondary) |
||||
} |
||||
} |
||||
} footer: { |
||||
if onlineRegPaymentMode == .disabled { |
||||
FooterButtonView("Contactez nous pour activer cette option.") { |
||||
let emailTo: String = "support@padelclub.app" |
||||
let subject: String = "Activer l'option de paiment en ligne : \(dataStore.user.email)" |
||||
if let url = URL(string: "mailto:\(emailTo)?subject=\(subject)"), UIApplication.shared.canOpenURL(url) { |
||||
UIApplication.shared.open(url, options: [:], completionHandler: nil) |
||||
} |
||||
} |
||||
.font(.callout) |
||||
.multilineTextAlignment(.leading) |
||||
} else { |
||||
Text("Permet de proposer le paiement de vos tournois en ligne.") |
||||
} |
||||
} |
||||
|
||||
Section { |
||||
SupportButtonView(supportButtonType: .sharingRequest) |
||||
} header: { |
||||
Text("Partage et délégation de compte") |
||||
} footer: { |
||||
Text("Vous souhaitez partager la supervision d'un tournoi à un autre compte ? Vous avez plusieurs juge-arbitres dans votre club ?") |
||||
} |
||||
} |
||||
|
||||
Section { |
||||
Link(destination: URLs.appReview.url) { |
||||
Text("Partagez vos impressions !") |
||||
} |
||||
|
||||
Link(destination: URLs.instagram.url) { |
||||
Text("Compte Instagram PadelClub.app") |
||||
} |
||||
|
||||
Link(destination: URLs.appDescription.url) { |
||||
Text("Page de présentation de Padel Club") |
||||
} |
||||
|
||||
} |
||||
|
||||
Section { |
||||
Link(destination: URLs.privacy.url) { |
||||
Text("Politique de confidentialité") |
||||
} |
||||
Link(destination: URLs.eula.url) { |
||||
Text("Contrat d'utilisation") |
||||
} |
||||
} |
||||
} |
||||
.sheet(isPresented: self.$showSubscriptions, content: { |
||||
NavigationStack { |
||||
SubscriptionView(isPresented: self.$showSubscriptions) |
||||
.environment(\.colorScheme, .light) |
||||
} |
||||
}) |
||||
.sheet(isPresented: self.$showProductIds, content: { |
||||
ProductIdsView() |
||||
}) |
||||
.navigationDestination(for: AccountScreen.self) { screen in |
||||
switch screen { |
||||
case .login: |
||||
LoginView {_ in } |
||||
} |
||||
} |
||||
.navigationTitle("Mon compte") |
||||
} |
||||
} |
||||
} |
||||
|
||||
struct AccountRowView: View { |
||||
@EnvironmentObject var dataStore: DataStore |
||||
|
||||
var userName: String |
||||
var body: some View { |
||||
|
||||
let isAuthenticated = StoreCenter.main.isAuthenticated |
||||
LabeledContent { |
||||
if isAuthenticated { |
||||
Text(self.userName) |
||||
} else if StoreCenter.main.userName != nil { |
||||
Image(systemName: "xmark.circle.fill") |
||||
.foregroundStyle(.logoRed) |
||||
} |
||||
} label: { |
||||
Label("Mon compte", systemImage: "person.fill") |
||||
if isAuthenticated && dataStore.user.email.isEmpty == false { |
||||
Text(dataStore.user.email) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
struct ProductIdsView: View { |
||||
|
||||
@State var transactions: [StoreKit.Transaction] = [] |
||||
|
||||
var body: some View { |
||||
VStack { |
||||
List { |
||||
LabeledContent("count", value: String(self.transactions.count)) |
||||
ForEach(self.transactions) { transaction in |
||||
if #available(iOS 17.2, *) { |
||||
if let offer = transaction.offer { |
||||
LabeledContent(transaction.productID, value: "\(offer.type)") |
||||
} else { |
||||
LabeledContent(transaction.productID, value: "no offer") |
||||
} |
||||
} else { |
||||
Text("need ios 17.2") |
||||
} |
||||
} |
||||
}.onAppear { |
||||
Task { |
||||
self.transactions = Array(Guard.main.purchasedTransactions) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,68 @@ |
||||
// |
||||
// UmpireOptionsView.swift |
||||
// PadelClub |
||||
// |
||||
// Created by Razmig Sarkissian on 06/10/2025. |
||||
// |
||||
|
||||
import SwiftUI |
||||
import PadelClubData |
||||
|
||||
struct UmpireOptionsView: View { |
||||
@Environment(NavigationViewModel.self) private var navigation: NavigationViewModel |
||||
@State private var umpireOption: UmpireOption? = .umpire |
||||
|
||||
var body: some View { |
||||
@Bindable var navigation = navigation |
||||
NavigationStack { |
||||
VStack(spacing: 0) { |
||||
GenericDestinationPickerView(selectedDestination: $umpireOption, destinations: UmpireOption.allCases, nilDestinationIsValid: true) |
||||
switch umpireOption { |
||||
case .none: |
||||
UmpireSettingsView() |
||||
.navigationTitle("Préférences") |
||||
case .umpire: |
||||
UmpireView() |
||||
.navigationTitle("Juge-Arbitre") |
||||
case .clubs: |
||||
ClubsView() |
||||
} |
||||
} |
||||
.navigationBarTitleDisplayMode(.large) |
||||
.navigationTitle("Juge-Arbitre") |
||||
.toolbarBackground(.visible, for: .navigationBar) |
||||
} |
||||
} |
||||
} |
||||
|
||||
enum UmpireOption: Int, CaseIterable, Identifiable, Selectable, Equatable { |
||||
func badgeValue() -> Int? { |
||||
nil |
||||
} |
||||
|
||||
func badgeImage() -> PadelClubData.Badge? { |
||||
nil |
||||
} |
||||
|
||||
func badgeValueColor() -> Color? { |
||||
nil |
||||
} |
||||
|
||||
var id: Int { self.rawValue } |
||||
|
||||
case umpire |
||||
case clubs |
||||
|
||||
var localizedTitleKey: String { |
||||
switch self { |
||||
case .umpire: |
||||
return "Juge-Arbitre" |
||||
case .clubs: |
||||
return "Clubs Favoris" |
||||
} |
||||
} |
||||
|
||||
func selectionLabel(index: Int) -> String { |
||||
localizedTitleKey |
||||
} |
||||
} |
||||
@ -0,0 +1,85 @@ |
||||
// |
||||
// UmpireSettingsView.swift |
||||
// PadelClub |
||||
// |
||||
// Created by Razmig Sarkissian on 06/10/2025. |
||||
// |
||||
|
||||
import SwiftUI |
||||
import CoreLocation |
||||
import LeStorage |
||||
import StoreKit |
||||
import PadelClubData |
||||
|
||||
struct UmpireSettingsView: View { |
||||
|
||||
@EnvironmentObject var dataStore: DataStore |
||||
|
||||
var body: some View { |
||||
List { |
||||
if dataStore.user.canEnableOnlinePayment() { |
||||
Section { |
||||
if let tournamentTemplate = Tournament.getTemplateTournament() { |
||||
NavigationLink { |
||||
RegistrationSetupView(tournament: tournamentTemplate) |
||||
} label: { |
||||
Text("Référence") |
||||
Text(tournamentTemplate.tournamentTitle()).foregroundStyle(.secondary) |
||||
} |
||||
} else { |
||||
Text("Aucun tournoi référence. Choisissez-en un dans la liste d'activité") |
||||
} |
||||
} header: { |
||||
Text("Inscription et paiement en ligne") |
||||
} footer: { |
||||
Text("Tournoi référence utilisé pour les réglages des inscriptions en ligne") |
||||
} |
||||
} |
||||
|
||||
Section { |
||||
@Bindable var user = dataStore.user |
||||
Toggle(isOn: $user.disableRankingFederalRuling) { |
||||
Text("Désactiver la règle fédéral") |
||||
} |
||||
.onChange(of: user.disableRankingFederalRuling) { |
||||
dataStore.saveUser() |
||||
} |
||||
} header: { |
||||
Text("Règle fédérale classement finale") |
||||
} footer: { |
||||
Text("Dernier de poule ≠ dernier du tournoi") |
||||
} |
||||
|
||||
Section { |
||||
@Bindable var user = dataStore.user |
||||
Picker(selection: $user.loserBracketMode) { |
||||
ForEach(LoserBracketMode.allCases) { |
||||
Text($0.localizedLoserBracketMode()).tag($0) |
||||
} |
||||
} label: { |
||||
Text("Position des perdants") |
||||
} |
||||
.onChange(of: user.loserBracketMode) { |
||||
dataStore.saveUser() |
||||
} |
||||
} header: { |
||||
Text("Matchs de classement") |
||||
} |
||||
|
||||
Section { |
||||
NavigationLink { |
||||
GlobalSettingsView() |
||||
} label: { |
||||
Label("Formats de jeu par défaut", systemImage: "megaphone") |
||||
} |
||||
NavigationLink { |
||||
DurationSettingsView() |
||||
} label: { |
||||
Label("Définir les durées moyennes", systemImage: "deskclock") |
||||
} |
||||
} footer: { |
||||
Text("Vous pouvez définir vos propres estimations de durées de match en fonction du format de jeu.") |
||||
} |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue