@ -10,6 +10,7 @@ import SwiftUI
import PadelClubData
struct RegistrationSetupView : View {
@ Environment ( \ . openURL ) private var openURL
@ EnvironmentObject var dataStore : DataStore
@ Bindable var tournament : Tournament
@ State private var enableOnlineRegistration : Bool
@ -41,7 +42,7 @@ struct RegistrationSetupView: View {
@ State private var refundDateLimit : Date
@ State private var refundDateLimitEnabled : Bool
@ State private var stripeAccountId : String
@ State private var stripeAccountIdIsInvalid : Bool = false
@ State private var stripeAccountIdIsInvalid : Bool ?
@ State private var paymentConfig : PaymentConfig ?
@ State private var timeToConfirmConfig : TimeToConfirmConfig ?
@ -50,6 +51,10 @@ struct RegistrationSetupView: View {
@ State private var hasChanges : Bool = false
@ State private var stripeOnBoardingURL : URL ? = nil
@ State private var errorMessage : String ? = nil
@ State private var presentErrorAlert : Bool = false
@ Environment ( \ . dismiss ) private var dismiss
init ( tournament : Tournament ) {
@ -320,7 +325,6 @@ struct RegistrationSetupView: View {
ToolbarItem ( placement : . topBarTrailing ) {
ButtonValidateView ( role : . destructive ) {
_save ( )
dismiss ( )
}
}
}
@ -331,7 +335,7 @@ struct RegistrationSetupView: View {
HStack {
Button ( " Effacer " ) {
stripeAccountId = " "
stripeAccountIdIsInvalid = false
stripeAccountIdIsInvalid = nil
tournament . stripeAccountId = nil
}
. buttonStyle ( . borderless )
@ -344,7 +348,13 @@ struct RegistrationSetupView: View {
}
}
}
. alert ( " Paiement en ligne " , isPresented : $ presentErrorAlert , actions : {
Button ( " Fermer " ) {
self . presentErrorAlert = false
}
} , message : {
Text ( ValidationError . onlinePaymentNotEnabled . localizedDescription )
} )
. toolbarRole ( . editor )
. headerProminence ( . increased )
. navigationTitle ( " Inscription en ligne " )
@ -435,32 +445,6 @@ struct RegistrationSetupView: View {
Text ( " Revenu Padel Club " )
}
}
if isCorporateTournament = = false , dataStore . user . registrationPaymentMode . requiresStripe ( ) {
VStack ( alignment : . leading ) {
LabeledContent {
if isValidating {
ProgressView ( )
} else if focusedField = = nil , stripeAccountIdIsInvalid = = false , stripeAccountId . isEmpty = = false , isValidating = = false {
Image ( systemName : " checkmark.circle.fill " ) . foregroundStyle ( . green )
}
} label : {
TextField ( " Identifiant du compte Stripe " , text : $ stripeAccountId )
. frame ( maxWidth : . infinity )
. focused ( $ focusedField , equals : . _stripeAccountId )
. disabled ( isValidating )
. keyboardType ( . alphabet )
. textContentType ( nil )
. autocorrectionDisabled ( )
}
if stripeAccountIdIsInvalid {
Text ( " Identifiant Stripe invalide. Vous ne pouvez pas activer le paiement en ligne. " ) . foregroundStyle ( . logoRed )
Button ( " Ré-essayer " ) {
_confirmStripeAccountId ( )
}
}
}
}
} header : {
Text ( " Paiement en ligne " )
} footer : {
@ -488,13 +472,81 @@ struct RegistrationSetupView: View {
. onChange ( of : refundDateLimit ) {
_hasChanged ( )
}
. onChange ( of : focusedField ) { old , new in
if old = = . _stripeAccountId {
_confirmStripeAccountId ( )
}
}
if dataStore . user . registrationPaymentMode . requiresStripe ( ) {
if isCorporateTournament = = false , dataStore . user . registrationPaymentMode . requiresStripe ( ) {
Section {
LabeledContent {
if isValidating {
ProgressView ( )
} else if focusedField = = nil , stripeAccountIdIsInvalid = = false , stripeAccountId . isEmpty = = false , isValidating = = false {
Image ( systemName : " checkmark.circle.fill " ) . foregroundStyle ( . green )
}
} label : {
TextField ( " Identifiant du compte Stripe " , text : $ stripeAccountId )
. frame ( maxWidth : . infinity )
. focused ( $ focusedField , equals : . _stripeAccountId )
. disabled ( isValidating )
. keyboardType ( . alphabet )
. textContentType ( nil )
. autocorrectionDisabled ( )
}
. onChange ( of : focusedField ) { old , new in
if old = = . _stripeAccountId {
_confirmStripeAccountId ( )
}
}
if stripeAccountIdIsInvalid = = true {
Text ( " Identifiant Stripe invalide. Vous ne pouvez pas activer le paiement en ligne. " ) . foregroundStyle ( . logoRed )
}
if stripeAccountId . isEmpty = = false {
Button ( " Vérifier le compte Stripe " ) {
_confirmStripeAccountId ( )
}
. disabled ( isValidating )
}
if let errorMessage {
Text ( errorMessage ) . foregroundStyle ( . logoRed )
}
RowButtonView ( " Connecter ou créer un compte Stripe " , role : . destructive ) {
errorMessage = nil
stripeAccountIdIsInvalid = nil
stripeAccountId = " "
stripeOnBoardingURL = nil
do {
let createStripeAccountResponse = try await StripeValidationService . createStripeConnectAccount ( )
print ( " createStripeAccountResponse " , createStripeAccountResponse )
guard let accounId = createStripeAccountResponse . accountId else {
throw ValidationError . accountNotFound
}
let createStripeAccountLinkResponse = try await StripeValidationService . createStripeAccountLink ( accounId )
print ( " createStripeAccountLinkResponse " , createStripeAccountLinkResponse )
stripeOnBoardingURL = createStripeAccountLinkResponse . url
stripeAccountIdIsInvalid = nil
stripeAccountId = accounId
if let stripeOnBoardingURL {
openURL ( stripeOnBoardingURL )
} else {
throw ValidationError . urlNotFound
}
} catch {
self . errorMessage = error . localizedDescription
Logger . error ( error )
}
}
} header : {
Text ( " Compte Stripe " )
} footer : {
Text ( " Vous devez connecter un compte Stripe à Padel Club. En cliquant sur le bouton ci-dessus, vous serez dirigé vers Stripe pour choisir votre compte Stripe à connecter ou pour en créer un. " )
}
Section {
let fixedFee = RegistrationPaymentMode . stripeFixedFee // F i x e d f e e i n e u r o s
let percentageFee = RegistrationPaymentMode . stripePercentageFee
@ -526,11 +578,10 @@ struct RegistrationSetupView: View {
// T e x t ( " A u c u n e c o m m i s s i o n P a d e l C l u b n e s e r a p r é l e v é e . " ) . f o r e g r o u n d S t y l e ( . l o g o R e d ) . b o l d ( )
}
}
}
private func _confirmStripeAccountId ( ) {
stripeAccountIdIsInvalid = false
stripeAccountIdIsInvalid = nil
if stripeAccountId . isEmpty {
tournament . stripeAccountId = nil
} else if stripeAccountId . count >= 5 , stripeAccountId . starts ( with : " acct_ " ) {
@ -544,13 +595,12 @@ struct RegistrationSetupView: View {
Task {
isValidating = true
do {
let response = try await StripeValidationService . validateStripeAccountID ( accId )
let response = try await StripeValidationService . validateStripeAccount ( accountId : accId )
print ( " validateStripeAccount " , response )
stripeAccountId = accId
stripeAccountIdIsInvalid = response . valid = = false
enableOnlinePayment = response . valid
stripeAccountIdIsInvalid = response . canProcessPayments = = false
} catch {
stripeAccountIdIsInvalid = true
enableOnlinePayment = false
}
isValidating = false
}
@ -567,6 +617,8 @@ struct RegistrationSetupView: View {
tournament . isTemplate = isTemplate
tournament . isCorporateTournament = isCorporateTournament
tournament . unregisterDeltaInHours = unregisterDeltaInHours
var shouldDismiss = true
if enableOnlineRegistration {
tournament . accountIsRequired = userAccountIsRequired
tournament . licenseIsRequired = licenseIsRequired
@ -589,6 +641,12 @@ struct RegistrationSetupView: View {
tournament . stripeAccountId = stripeAccountId
} else {
tournament . stripeAccountId = nil
if enableOnlinePayment , isCorporateTournament = = false , dataStore . user . registrationPaymentMode . requiresStripe ( ) {
enableOnlinePayment = false
tournament . enableOnlinePayment = false
shouldDismiss = false
}
}
} else {
tournament . accountIsRequired = true
@ -626,8 +684,11 @@ struct RegistrationSetupView: View {
}
self . dataStore . tournaments . addOrUpdate ( instance : tournament )
dismiss ( )
if shouldDismiss {
dismiss ( )
} else {
presentErrorAlert = true
}
}
}