You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
497 lines
19 KiB
497 lines
19 KiB
//
|
|
// UmpireView.swift
|
|
// PadelClub
|
|
//
|
|
// Created by Razmig Sarkissian on 01/03/2024.
|
|
//
|
|
|
|
import SwiftUI
|
|
import CoreLocation
|
|
import LeStorage
|
|
import StoreKit
|
|
|
|
struct UmpireView: View {
|
|
|
|
@Environment(NavigationViewModel.self) private var navigation: NavigationViewModel
|
|
@EnvironmentObject var dataStore: DataStore
|
|
|
|
@State private var presentSearchView: Bool = false
|
|
@State private var showSubscriptions: Bool = false
|
|
@State private var showProductIds: Bool = false
|
|
@State private var umpireCustomMail: String
|
|
@State private var umpireCustomPhone: String
|
|
@State private var umpireCustomContact: String
|
|
@State private var umpireCustomMailIsInvalid: Bool = false
|
|
@State private var umpireCustomPhoneIsInvalid: Bool = false
|
|
|
|
@FocusState private var focusedField: CustomUser.CodingKeys?
|
|
|
|
// @State var isConnected: Bool = false
|
|
|
|
init() {
|
|
_umpireCustomMail = State(wrappedValue: DataStore.shared.user.umpireCustomMail ?? "")
|
|
_umpireCustomPhone = State(wrappedValue: DataStore.shared.user.umpireCustomPhone ?? "")
|
|
_umpireCustomContact = State(wrappedValue: DataStore.shared.user.umpireCustomContact ?? "")
|
|
}
|
|
|
|
enum UmpireScreen {
|
|
case login
|
|
}
|
|
|
|
var body: some View {
|
|
@Bindable var navigation = navigation
|
|
NavigationStack(path: $navigation.umpirePath) {
|
|
List {
|
|
|
|
PurchaseListView()
|
|
|
|
if Guard.main.currentPlan != .monthlyUnlimited {
|
|
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: UmpireScreen.login) {
|
|
AccountRowView(userName: dataStore.user.username)
|
|
}
|
|
}
|
|
|
|
let currentPlayerData = dataStore.user.currentPlayerData()
|
|
Section {
|
|
if let currentPlayerData {
|
|
//todo palmares
|
|
ImportedPlayerView(player: currentPlayerData, showProgression: true)
|
|
// NavigationLink {
|
|
//
|
|
// } label: {
|
|
// ImportedPlayerView(player: currentPlayerData)
|
|
// }
|
|
} else {
|
|
RowButtonView("Ma fiche joueur", systemImage: "person.bust") {
|
|
presentSearchView = true
|
|
}
|
|
}
|
|
} footer: {
|
|
if dataStore.user.licenceId == nil {
|
|
Text("Si vous avez participé à un tournoi dans les 12 derniers mois, Padel Club peut vous retrouver.")
|
|
} else if let currentPlayerData {
|
|
Menu {
|
|
Button {
|
|
UIPasteboard.general.string = currentPlayerData.formattedLicense()
|
|
} label: {
|
|
Text("Copier ma licence")
|
|
Text(currentPlayerData.formattedLicense())
|
|
}
|
|
|
|
Button("Supprimer ma fiche") {
|
|
dataStore.user.licenceId = nil
|
|
self.dataStore.saveUser()
|
|
}
|
|
|
|
} label: {
|
|
Text("options")
|
|
.foregroundStyle(Color.master)
|
|
.underline()
|
|
}
|
|
}
|
|
}
|
|
|
|
Section {
|
|
NavigationLink {
|
|
ClubsView()
|
|
} label: {
|
|
LabeledContent {
|
|
Text(dataStore.user.clubs.count.formatted())
|
|
} label: {
|
|
Label("Clubs favoris", systemImage: "house.and.flag")
|
|
}
|
|
}
|
|
} footer: {
|
|
Text("Il s'agit des clubs qui sont utilisés pour récupérer les tournois tenup.")
|
|
}
|
|
|
|
// Section {
|
|
// NavigationLink {
|
|
// UmpireStatisticView()
|
|
// } label: {
|
|
// Text("Statistiques de participations")
|
|
// }
|
|
// }
|
|
//
|
|
_customUmpireView()
|
|
|
|
Section {
|
|
@Bindable var user = dataStore.user
|
|
if dataStore.user.hideUmpireMail, dataStore.user.hideUmpirePhone {
|
|
Text("Attention, les emails envoyés automatiquement au regard des inscriptions en ligne ne contiendront aucun moyen de vous contacter.").foregroundStyle(.logoRed)
|
|
}
|
|
|
|
Toggle(isOn: $user.hideUmpireMail) {
|
|
Text("Masquer l'email")
|
|
}
|
|
Toggle(isOn: $user.hideUmpirePhone) {
|
|
Text("Masquer le téléphone")
|
|
}
|
|
|
|
} footer: {
|
|
Text("Ces informations ne seront pas affichées sur la page d'information des tournois sur Padel Club et dans les emails envoyés automatiquement au regard des inscriptions en lignes.")
|
|
}
|
|
|
|
|
|
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.")
|
|
}
|
|
|
|
// Section {
|
|
// Text("Tenup ID")
|
|
// }
|
|
//
|
|
// Section {
|
|
// Text("Tournois")
|
|
// }
|
|
//
|
|
// Section {
|
|
// NavigationLink {
|
|
//
|
|
// } label: {
|
|
// Text("Favori")
|
|
// }
|
|
// NavigationLink {
|
|
//
|
|
// } label: {
|
|
// Text("Black list")
|
|
// }
|
|
// }
|
|
}
|
|
.navigationTitle("Juge-Arbitre")
|
|
.toolbar {
|
|
#if DEBUG
|
|
ToolbarItem(placement: .topBarTrailing) {
|
|
NetworkStatusView()
|
|
// if StoreCenter.main.collectionsCanSynchronize {
|
|
// Image(systemName: "checkmark.icloud")
|
|
// } else {
|
|
// Image(systemName: "icloud.slash")
|
|
// }
|
|
}
|
|
#endif
|
|
}
|
|
.navigationBarBackButtonHidden(focusedField != nil)
|
|
.toolbar(content: {
|
|
if focusedField != nil {
|
|
ToolbarItem(placement: .topBarLeading) {
|
|
Button("Annuler", role: .cancel) {
|
|
focusedField = nil
|
|
}
|
|
}
|
|
}
|
|
})
|
|
.toolbar {
|
|
if focusedField != nil {
|
|
ToolbarItem(placement: .keyboard) {
|
|
HStack {
|
|
if focusedField == ._umpireCustomMail, umpireCustomMail.isEmpty == false {
|
|
Button("Effacer") {
|
|
_deleteUmpireMail()
|
|
}
|
|
.buttonStyle(.borderless)
|
|
} else if focusedField == ._umpireCustomPhone, umpireCustomPhone.isEmpty == false {
|
|
Button("Effacer") {
|
|
_deleteUmpirePhone()
|
|
}
|
|
.buttonStyle(.borderless)
|
|
} else if focusedField == ._umpireCustomContact, umpireCustomContact.isEmpty == false {
|
|
Button("Effacer") {
|
|
_deleteUmpireContact()
|
|
}
|
|
.buttonStyle(.borderless)
|
|
}
|
|
Spacer()
|
|
Button("Valider") {
|
|
focusedField = nil
|
|
}
|
|
.buttonStyle(.bordered)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.onChange(of: [dataStore.user.umpireCustomMail, dataStore.user.umpireCustomPhone, dataStore.user.umpireCustomContact]) {
|
|
self.dataStore.saveUser()
|
|
}
|
|
.onChange(of: [dataStore.user.hideUmpireMail, dataStore.user.hideUmpirePhone]) {
|
|
self.dataStore.saveUser()
|
|
}
|
|
.onChange(of: focusedField) { old, new in
|
|
if old == ._umpireCustomMail {
|
|
_confirmUmpireMail()
|
|
} else if old == ._umpireCustomPhone {
|
|
_confirmUmpirePhone()
|
|
} else if old == ._umpireCustomContact {
|
|
_confirmUmpireContact()
|
|
}
|
|
}
|
|
|
|
.sheet(isPresented: self.$showSubscriptions, content: {
|
|
NavigationStack {
|
|
SubscriptionView(isPresented: self.$showSubscriptions)
|
|
.environment(\.colorScheme, .light)
|
|
}
|
|
})
|
|
.sheet(isPresented: self.$showProductIds, content: {
|
|
ProductIdsView()
|
|
})
|
|
.sheet(isPresented: $presentSearchView) {
|
|
let user = dataStore.user
|
|
NavigationStack {
|
|
SelectablePlayerListView(allowSelection: 1, searchField: user.firstName + " " + user.lastName, playerSelectionAction: { players in
|
|
if let player = players.first {
|
|
user.licenceId = player.license?.computedLicense
|
|
if user.clubsObjects().contains(where: { $0.code == player.clubCode }) == false {
|
|
let userClub = Club.findOrCreate(name: player.clubName!, code: player.clubCode)
|
|
if userClub.hasBeenCreated(by: StoreCenter.main.userId) {
|
|
do {
|
|
try dataStore.clubs.addOrUpdate(instance: userClub)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
}
|
|
user.setUserClub(userClub)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
.navigationDestination(for: UmpireScreen.self) { screen in
|
|
switch screen {
|
|
case .login:
|
|
LoginView {_ in }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func _confirmUmpireMail() {
|
|
umpireCustomMailIsInvalid = false
|
|
if umpireCustomMail.isEmpty {
|
|
dataStore.user.umpireCustomMail = nil
|
|
} else if umpireCustomMail.isValidEmail() {
|
|
dataStore.user.umpireCustomMail = umpireCustomMail
|
|
} else {
|
|
umpireCustomMailIsInvalid = true
|
|
}
|
|
}
|
|
|
|
private func _deleteUmpireMail() {
|
|
umpireCustomMailIsInvalid = false
|
|
umpireCustomMail = ""
|
|
dataStore.user.umpireCustomMail = nil
|
|
}
|
|
|
|
private func _confirmUmpirePhone() {
|
|
umpireCustomPhoneIsInvalid = false
|
|
if umpireCustomPhone.isEmpty {
|
|
dataStore.user.umpireCustomPhone = nil
|
|
} else if umpireCustomPhone.isPhoneNumber() {
|
|
dataStore.user.umpireCustomPhone = umpireCustomPhone.prefixMultilineTrimmed(15)
|
|
} else {
|
|
umpireCustomPhoneIsInvalid = true
|
|
}
|
|
}
|
|
|
|
private func _deleteUmpirePhone() {
|
|
umpireCustomPhoneIsInvalid = false
|
|
umpireCustomPhone = ""
|
|
dataStore.user.umpireCustomPhone = nil
|
|
}
|
|
|
|
private func _confirmUmpireContact() {
|
|
if umpireCustomContact.isEmpty {
|
|
dataStore.user.umpireCustomContact = nil
|
|
} else {
|
|
dataStore.user.umpireCustomContact = umpireCustomContact.prefixMultilineTrimmed(200)
|
|
}
|
|
}
|
|
|
|
private func _deleteUmpireContact() {
|
|
umpireCustomContact = ""
|
|
dataStore.user.umpireCustomContact = nil
|
|
}
|
|
|
|
|
|
private func _customUmpireView() -> some View {
|
|
Section {
|
|
VStack(alignment: .leading) {
|
|
TextField(dataStore.user.email, text: $umpireCustomMail)
|
|
.frame(maxWidth: .infinity)
|
|
.keyboardType(.emailAddress)
|
|
.autocapitalization(.none)
|
|
.focused($focusedField, equals: ._umpireCustomMail)
|
|
.onSubmit {
|
|
_confirmUmpireMail()
|
|
}
|
|
if umpireCustomMailIsInvalid {
|
|
Text("Vous n'avez pas indiqué un email valide.").foregroundStyle(.logoRed)
|
|
}
|
|
}
|
|
|
|
VStack(alignment: .leading) {
|
|
TextField(dataStore.user.phone ?? "Téléphone", text: $umpireCustomPhone)
|
|
.frame(maxWidth: .infinity)
|
|
.keyboardType(.phonePad)
|
|
.focused($focusedField, equals: ._umpireCustomPhone)
|
|
.onSubmit {
|
|
_confirmUmpirePhone()
|
|
}
|
|
if umpireCustomPhoneIsInvalid {
|
|
Text("Vous n'avez pas indiqué un téléphone valide.").foregroundStyle(.logoRed)
|
|
}
|
|
}
|
|
|
|
|
|
VStack(alignment: .leading) {
|
|
TextField(dataStore.user.fullName(), text: $umpireCustomContact)
|
|
.frame(maxWidth: .infinity)
|
|
.keyboardType(.default)
|
|
.focused($focusedField, equals: ._umpireCustomContact)
|
|
.onSubmit {
|
|
_confirmUmpireContact()
|
|
}
|
|
if dataStore.user.getSummonsMessageSignature() != nil, umpireCustomContact != dataStore.user.fullName() {
|
|
Text("Attention vous avez une signature personnalisée contenant un contact différent.").foregroundStyle(.logoRed)
|
|
|
|
FooterButtonView("retirer la personnalisation ?") {
|
|
dataStore.user.summonsMessageSignature = nil
|
|
self.dataStore.saveUser()
|
|
}
|
|
} }
|
|
|
|
} header: {
|
|
Text("Juge-arbitre")
|
|
} footer: {
|
|
Text("Ces informations seront utilisées pour vous contacter. Vous pouvez les modifier si vous souhaitez utiliser les informations de contact différentes de votre compte Padel Club.")
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
//#Preview {
|
|
// UmpireView()
|
|
//}
|
|
|