From f1727560598da5306ca77f7c881c171d8598a187 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Mon, 11 Dec 2023 19:15:34 -0600 Subject: [PATCH 01/16] add picker for PayPal funding source --- .../PayPalWebButtonsView.swift | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift index e213cb94e..af7a81200 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift @@ -1,25 +1,40 @@ import SwiftUI import PaymentButtons +import PayPalWebPayments struct PayPalWebButtonsView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel + @State private var selectedFundingSource: PayPalWebCheckoutFundingSource = .paypal + var body: some View { VStack { VStack(alignment: .center, spacing: 40) { - PayPalButton.Representable(color: .blue, size: .mini) { - payPalWebViewModel.paymentButtonTapped(funding: .paypal) - } - .frame(maxWidth: .infinity, maxHeight: 40) - PayPalCreditButton.Representable(color: .black, edges: .softEdges, size: .expanded) { - payPalWebViewModel.paymentButtonTapped(funding: .paypalCredit) + Picker("Funding Source", selection: $selectedFundingSource) { + Text("PayPal").tag(PayPalWebCheckoutFundingSource.paypal) + Text("PayPal Credit").tag(PayPalWebCheckoutFundingSource.paylater) + Text("Pay Later").tag(PayPalWebCheckoutFundingSource.paypalCredit) } - .frame(maxWidth: .infinity, maxHeight: 40) - PayPalPayLaterButton.Representable(color: .silver, edges: .rounded, size: .full) { - payPalWebViewModel.paymentButtonTapped(funding: .paylater) + .pickerStyle(SegmentedPickerStyle()) + + switch selectedFundingSource { + case .paypalCredit: + PayPalCreditButton.Representable(color: .black, size: .full) { + payPalWebViewModel.paymentButtonTapped(funding: .paypalCredit) + } + .frame(maxWidth: .infinity, maxHeight: 40) + case .paylater: + PayPalPayLaterButton.Representable(color: .silver, edges: .softEdges, size: .full) { + payPalWebViewModel.paymentButtonTapped(funding: .paylater) + } + .frame(maxWidth: .infinity, maxHeight: 40) + case .paypal: + PayPalButton.Representable(color: .blue, size: .full) { + payPalWebViewModel.paymentButtonTapped(funding: .paypal) + } + .frame(maxWidth: .infinity, maxHeight: 40) } - .frame(maxWidth: .infinity, maxHeight: 40) } .padding(20) .padding() From 8ab4ab71fb511a821790d6c6c83aed81507fc8a6 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Mon, 11 Dec 2023 19:15:59 -0600 Subject: [PATCH 02/16] simplify PayPalWebStatusView into single view --- .../PayPalWebStatusView.swift | 81 +++++++------------ 1 file changed, 28 insertions(+), 53 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift index 2ec377e39..6e925dfad 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift @@ -7,62 +7,37 @@ struct PayPalWebStatusView: View { var body: some View { VStack(spacing: 16) { - switch status { - case .created: - HStack { - Text("Order Created") - .font(.system(size: 20)) - Spacer() - } - if let order = payPalWebViewModel.createOrderResult { - LeadingText("Order ID", weight: .bold) - LeadingText("\(order.id)") - LeadingText("Status", weight: .bold) - LeadingText("\(order.status)") - } - case .approved: - HStack { - Text("Order Approved") - .font(.system(size: 20)) - Spacer() - } - if let order = payPalWebViewModel.createOrderResult { - LeadingText("Intent", weight: .bold) - LeadingText("\(payPalWebViewModel.intent)") - LeadingText("Order ID", weight: .bold) - LeadingText("\(order.id)") - LeadingText("Payer ID", weight: .bold) - LeadingText("\(payPalWebViewModel.checkoutResult?.payerID ?? "")") - } - case .completed: - if let order = payPalWebViewModel.transactionResult { - HStack { - Text("Order \(payPalWebViewModel.intent.rawValue.capitalized)d") - .font(.system(size: 20)) - Spacer() - } - LeadingText("Order ID", weight: .bold) - LeadingText("\(order.id)") - LeadingText("Status", weight: .bold) - LeadingText("\(order.status)") + HStack { + Text("Order Details") + .font(.system(size: 20)) + Spacer() + } + LeadingText("Order ID", weight: .bold) + LeadingText("\(payPalWebViewModel.createOrderResult?.id ?? "")") + + if let status = payPalWebViewModel.order?.status { + LeadingText("Status", weight: .bold) + LeadingText("\(status)") + } - if let emailAddress = order.paymentSource?.paypal?.emailAddress { - LeadingText("Email", weight: .bold) - LeadingText("\(emailAddress)") - } + if let payerID = payPalWebViewModel.checkoutResult?.payerID { + LeadingText("Payer ID", weight: .bold) + LeadingText("\(payerID)") + } - if let vaultID = order.paymentSource?.paypal?.attributes?.vault.id { - LeadingText("Vault ID / Payment Token", weight: .bold) - LeadingText("\(vaultID)") - } + if let emailAddress = payPalWebViewModel.order?.paymentSource?.paypal?.emailAddress { + LeadingText("Email", weight: .bold) + LeadingText("\(emailAddress)") + } + + if let vaultID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.id { + LeadingText("Vault ID / Payment Token", weight: .bold) + LeadingText("\(vaultID)") + } - if let customerID = order.paymentSource?.paypal?.attributes?.vault.customer.id { - LeadingText("Customer ID", weight: .bold) - LeadingText("\(customerID)") - } - } - default: - Text("") + if let customerID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.customer.id { + LeadingText("Customer ID", weight: .bold) + LeadingText("\(customerID)") } } .frame(maxWidth: .infinity) From ff49260e69bba36de9bb9724b49b8b0ad8b59393 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Mon, 11 Dec 2023 19:18:37 -0600 Subject: [PATCH 03/16] remove PayPalWebStatusView; add successView property to PayPalWebResultView --- .../PayPalWebResultView.swift | 46 ++++++++++++++++- .../PayPalWebStatusView.swift | 51 ------------------- 2 files changed, 45 insertions(+), 52 deletions(-) delete mode 100644 Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift index 85cd823c0..ebe70d43d 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift @@ -18,9 +18,53 @@ struct PayPalWebResultView: View { case .idle, .loading: EmptyView() case .success: - PayPalWebStatusView(status: status, payPalWebViewModel: payPalWebViewModel) + successView case .error(let errorMessage): ErrorView(errorMessage: errorMessage) } } + + var successView: some View { + VStack(spacing: 16) { + HStack { + Text("Order Details") + .font(.system(size: 20)) + Spacer() + } + LeadingText("Order ID", weight: .bold) + LeadingText("\(payPalWebViewModel.createOrderResult?.id ?? "")") + + if let status = payPalWebViewModel.order?.status { + LeadingText("Status", weight: .bold) + LeadingText("\(status)") + } + + if let payerID = payPalWebViewModel.checkoutResult?.payerID { + LeadingText("Payer ID", weight: .bold) + LeadingText("\(payerID)") + } + + if let emailAddress = payPalWebViewModel.order?.paymentSource?.paypal?.emailAddress { + LeadingText("Email", weight: .bold) + LeadingText("\(emailAddress)") + } + + if let vaultID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.id { + LeadingText("Vault ID / Payment Token", weight: .bold) + LeadingText("\(vaultID)") + } + + if let customerID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.customer.id { + LeadingText("Customer ID", weight: .bold) + LeadingText("\(customerID)") + } + } + .frame(maxWidth: .infinity) + .padding() + .background( + RoundedRectangle(cornerRadius: 10) + .stroke(.gray, lineWidth: 2) + .padding(5) + ) + } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift deleted file mode 100644 index 6e925dfad..000000000 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebStatusView.swift +++ /dev/null @@ -1,51 +0,0 @@ -import SwiftUI - -struct PayPalWebStatusView: View { - - var status: OrderStatus - var payPalWebViewModel: PayPalWebViewModel - - var body: some View { - VStack(spacing: 16) { - HStack { - Text("Order Details") - .font(.system(size: 20)) - Spacer() - } - LeadingText("Order ID", weight: .bold) - LeadingText("\(payPalWebViewModel.createOrderResult?.id ?? "")") - - if let status = payPalWebViewModel.order?.status { - LeadingText("Status", weight: .bold) - LeadingText("\(status)") - } - - if let payerID = payPalWebViewModel.checkoutResult?.payerID { - LeadingText("Payer ID", weight: .bold) - LeadingText("\(payerID)") - } - - if let emailAddress = payPalWebViewModel.order?.paymentSource?.paypal?.emailAddress { - LeadingText("Email", weight: .bold) - LeadingText("\(emailAddress)") - } - - if let vaultID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.id { - LeadingText("Vault ID / Payment Token", weight: .bold) - LeadingText("\(vaultID)") - } - - if let customerID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.customer.id { - LeadingText("Customer ID", weight: .bold) - LeadingText("\(customerID)") - } - } - .frame(maxWidth: .infinity) - .padding() - .background( - RoundedRectangle(cornerRadius: 10) - .stroke(.gray, lineWidth: 2) - .padding(5) - ) - } -} From 794a04fd3800d9f1d4411549716987b75965ba7f Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Mon, 11 Dec 2023 19:21:02 -0600 Subject: [PATCH 04/16] cleanup status --- Demo/Demo.xcodeproj/project.pbxproj | 4 ---- .../PayPalWebPayments/PayPalWebButtonsView.swift | 4 ++-- .../PayPalWebPayments/PayPalWebPaymentsView.swift | 10 ++++++++-- .../PayPalWebPayments/PayPalWebResultView.swift | 9 --------- .../PayPalWebPayments/PayPalWebTransactionView.swift | 6 +++--- .../PayPalWebPayments/PayPalWebViewModel.swift | 1 + 6 files changed, 14 insertions(+), 20 deletions(-) diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index ccd5e871f..3a2c44bd3 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -67,7 +67,6 @@ BE1766B326F911A2007EF438 /* URLResponseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE1766B226F911A2007EF438 /* URLResponseError.swift */; }; BE1766D926FA7BC8007EF438 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BE1766D826FA7BC8007EF438 /* Settings.bundle */; }; BE8117642B07E778009867B9 /* PayPalWebResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117632B07E778009867B9 /* PayPalWebResultView.swift */; }; - BE8117662B080202009867B9 /* PayPalWebStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117652B080202009867B9 /* PayPalWebStatusView.swift */; }; BE8117682B080472009867B9 /* CurrentState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117672B080472009867B9 /* CurrentState.swift */; }; BE9F36D82745490400AFC7DA /* FloatingLabelTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F36D72745490400AFC7DA /* FloatingLabelTextField.swift */; }; BECD84A027036DC2007CCAE4 /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECD849F27036DC2007CCAE4 /* Environment.swift */; }; @@ -191,7 +190,6 @@ BE1766D826FA7BC8007EF438 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; BE420F3628189A7A00D8D66A /* PayPalUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PayPalUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BE8117632B07E778009867B9 /* PayPalWebResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebResultView.swift; sourceTree = ""; }; - BE8117652B080202009867B9 /* PayPalWebStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebStatusView.swift; sourceTree = ""; }; BE8117672B080472009867B9 /* CurrentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentState.swift; sourceTree = ""; }; BE9F36D72745490400AFC7DA /* FloatingLabelTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingLabelTextField.swift; sourceTree = ""; }; BECD849F27036DC2007CCAE4 /* Environment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Environment.swift; sourceTree = ""; }; @@ -272,7 +270,6 @@ 3BA570022AA053AE0081D14F /* PayPalWebCreateOrderView.swift */, 3BA570002AA052E80081D14F /* PayPalWebPaymentsView.swift */, BE8117632B07E778009867B9 /* PayPalWebResultView.swift */, - BE8117652B080202009867B9 /* PayPalWebStatusView.swift */, 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, 3BA56FFB2A9FEFE90081D14F /* PayPalWebViewModel.swift */, ); @@ -598,7 +595,6 @@ 3BDB348E2A7CB02C008100D7 /* SetupTokenRequest.swift in Sources */, 80F33CF326F8EA50006811B1 /* DemoSettings.swift in Sources */, 3BA56FE72A9DC9D70081D14F /* CardPaymentViewModel.swift in Sources */, - BE8117662B080202009867B9 /* PayPalWebStatusView.swift in Sources */, 3BA5700B2AA13C1C0081D14F /* CoreConfigManager.swift in Sources */, 80E4300C2AD82C8D003CA748 /* ShippingPreference.swift in Sources */, BEDE304A275EA33500D275FD /* UIViewController+Extension.swift in Sources */, diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift index af7a81200..472fd96ff 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift @@ -45,7 +45,7 @@ struct PayPalWebButtonsView: View { ) if payPalWebViewModel.checkoutResult != nil && payPalWebViewModel.state == .success { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .approved) + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) NavigationLink { PayPalWebTransactionView(payPalWebViewModel: payPalWebViewModel) .navigationTitle("Complete Transaction") @@ -56,7 +56,7 @@ struct PayPalWebButtonsView: View { .buttonStyle(RoundedBlueButtonStyle()) .padding() } else if case .error = payPalWebViewModel.state { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .error) + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) } Spacer() } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift index 88a03e406..ab3d870c3 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift @@ -1,5 +1,11 @@ import SwiftUI +enum OrderStatusButton: String { + case created = "Create an Order" + case approved = "Checkout with PayPal" + case completed = "Complete Transaction" +} + struct PayPalWebPaymentsView: View { @StateObject var payPalWebViewModel = PayPalWebViewModel() @@ -9,7 +15,7 @@ struct PayPalWebPaymentsView: View { VStack(spacing: 16) { PayPalWebCreateOrderView(payPalWebViewModel: payPalWebViewModel) if payPalWebViewModel.createOrderResult != nil && payPalWebViewModel.state == .success { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .created) + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) NavigationLink { PayPalWebButtonsView(payPalWebViewModel: payPalWebViewModel) .navigationTitle("Checkout with PayPal") @@ -19,7 +25,7 @@ struct PayPalWebPaymentsView: View { .buttonStyle(RoundedBlueButtonStyle()) .padding() } else if case .error = payPalWebViewModel.state { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .error) + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) } } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift index ebe70d43d..effd5e322 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift @@ -1,18 +1,9 @@ import SwiftUI -enum OrderStatus { - case created - case approved - case completed - case error -} - struct PayPalWebResultView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel - var status: OrderStatus - var body: some View { switch payPalWebViewModel.state { case .idle, .loading: diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift index 88b075434..ef4b62589 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift @@ -8,7 +8,7 @@ struct PayPalWebTransactionView: View { ScrollView { ScrollViewReader { scrollView in VStack { - PayPalWebStatusView(status: .approved, payPalWebViewModel: payPalWebViewModel) +// PayPalWebStatusView(status: .approved, payPalWebViewModel: payPalWebViewModel) ZStack { Button("\(payPalWebViewModel.intent.rawValue.capitalized) Order") { Task { @@ -28,10 +28,10 @@ struct PayPalWebTransactionView: View { } if payPalWebViewModel.transactionResult != nil && payPalWebViewModel.state == .success { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .completed) + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) .id("bottomView") } else if case .error = payPalWebViewModel.state { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel, status: .error) + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) } } .onChange(of: payPalWebViewModel.transactionResult) { _ in diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift index 4b2f4b0be..05b7dedd3 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift @@ -6,6 +6,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { @Published var state: CurrentState = .idle @Published var intent: Intent = .authorize + @Published var order: Order? @Published var createOrderResult: Order? @Published var transactionResult: Order? @Published var checkoutResult: PayPalWebCheckoutResult? From c7e7b1caf48cc3c17dae5c3f5f6da38fb1e2d08e Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Mon, 11 Dec 2023 20:23:41 -0600 Subject: [PATCH 05/16] WIP - start move into singular view and add TODOs --- .../PayPalWebButtonsView.swift | 23 +--------- .../PayPalWebPaymentsView.swift | 33 ++++++++++----- .../PayPalWebResultView.swift | 6 ++- .../PayPalWebTransactionView.swift | 42 +++++-------------- .../PayPalWebViewModel.swift | 9 ++-- 5 files changed, 43 insertions(+), 70 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift index 472fd96ff..e09d69f25 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift @@ -10,7 +10,7 @@ struct PayPalWebButtonsView: View { var body: some View { VStack { - VStack(alignment: .center, spacing: 40) { + VStack(alignment: .center, spacing: 16) { Picker("Funding Source", selection: $selectedFundingSource) { Text("PayPal").tag(PayPalWebCheckoutFundingSource.paypal) Text("PayPal Credit").tag(PayPalWebCheckoutFundingSource.paylater) @@ -23,42 +23,23 @@ struct PayPalWebButtonsView: View { PayPalCreditButton.Representable(color: .black, size: .full) { payPalWebViewModel.paymentButtonTapped(funding: .paypalCredit) } - .frame(maxWidth: .infinity, maxHeight: 40) case .paylater: PayPalPayLaterButton.Representable(color: .silver, edges: .softEdges, size: .full) { payPalWebViewModel.paymentButtonTapped(funding: .paylater) } - .frame(maxWidth: .infinity, maxHeight: 40) case .paypal: PayPalButton.Representable(color: .blue, size: .full) { payPalWebViewModel.paymentButtonTapped(funding: .paypal) } - .frame(maxWidth: .infinity, maxHeight: 40) } } + .frame(height: 100) .padding(20) - .padding() .background( RoundedRectangle(cornerRadius: 10) .stroke(.gray, lineWidth: 2) .padding(5) ) - - if payPalWebViewModel.checkoutResult != nil && payPalWebViewModel.state == .success { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) - NavigationLink { - PayPalWebTransactionView(payPalWebViewModel: payPalWebViewModel) - .navigationTitle("Complete Transaction") - } label: { - Text("Complete Transaction") - } - .navigationViewStyle(StackNavigationViewStyle()) - .buttonStyle(RoundedBlueButtonStyle()) - .padding() - } else if case .error = payPalWebViewModel.state { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) - } - Spacer() } } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift index ab3d870c3..5ba828869 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift @@ -6,26 +6,37 @@ enum OrderStatusButton: String { case completed = "Complete Transaction" } +// TODO: make sure errors are handled +// TODO: pin result view to bottom +// TODO: hide order create view after order created +// TODO: scrollview not working as expected +// TODO: add reset button + struct PayPalWebPaymentsView: View { @StateObject var payPalWebViewModel = PayPalWebViewModel() var body: some View { ScrollView { - VStack(spacing: 16) { - PayPalWebCreateOrderView(payPalWebViewModel: payPalWebViewModel) - if payPalWebViewModel.createOrderResult != nil && payPalWebViewModel.state == .success { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) - NavigationLink { + ScrollViewReader { scrollView in + VStack(spacing: 16) { + PayPalWebCreateOrderView(payPalWebViewModel: payPalWebViewModel) + // TODO: replace state with order status? + if payPalWebViewModel.order != nil && payPalWebViewModel.state == .success { PayPalWebButtonsView(payPalWebViewModel: payPalWebViewModel) - .navigationTitle("Checkout with PayPal") - } label: { - Text("Checkout with PayPal") } - .buttonStyle(RoundedBlueButtonStyle()) - .padding() - } else if case .error = payPalWebViewModel.state { + + if payPalWebViewModel.checkoutResult != nil && payPalWebViewModel.state == .success { + PayPalWebTransactionView(payPalWebViewModel: payPalWebViewModel) + } + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) + .id("bottomView") + } + .onChange(of: payPalWebViewModel.order) { _ in + withAnimation { + scrollView.scrollTo("bottomView") + } } } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift index effd5e322..c3bd548d5 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift @@ -22,8 +22,10 @@ struct PayPalWebResultView: View { .font(.system(size: 20)) Spacer() } - LeadingText("Order ID", weight: .bold) - LeadingText("\(payPalWebViewModel.createOrderResult?.id ?? "")") + if let orderID = payPalWebViewModel.orderID { + LeadingText("Order ID", weight: .bold) + LeadingText("\(payPalWebViewModel.order?.id ?? "")") + } if let status = payPalWebViewModel.order?.status { LeadingText("Status", weight: .bold) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift index ef4b62589..86d82db7c 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift @@ -5,41 +5,19 @@ struct PayPalWebTransactionView: View { @ObservedObject var payPalWebViewModel: PayPalWebViewModel var body: some View { - ScrollView { - ScrollViewReader { scrollView in - VStack { -// PayPalWebStatusView(status: .approved, payPalWebViewModel: payPalWebViewModel) - ZStack { - Button("\(payPalWebViewModel.intent.rawValue.capitalized) Order") { - Task { - do { - try await payPalWebViewModel.completeTransaction() - } catch { - print("Error capturing order: \(error.localizedDescription)") - } - } + VStack { + ZStack { + Button("\(payPalWebViewModel.intent.rawValue.capitalized) Order") { + Task { + do { + try await payPalWebViewModel.completeTransaction() + } catch { + print("Error capturing order: \(error.localizedDescription)") } - .buttonStyle(RoundedBlueButtonStyle()) - .padding() - - if payPalWebViewModel.state == .loading { - CircularProgressView() - } - } - - if payPalWebViewModel.transactionResult != nil && payPalWebViewModel.state == .success { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) - .id("bottomView") - } else if case .error = payPalWebViewModel.state { - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) - } - } - .onChange(of: payPalWebViewModel.transactionResult) { _ in - withAnimation { - scrollView.scrollTo("bottomView") } } - Spacer() + .buttonStyle(RoundedBlueButtonStyle()) + .padding() } } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift index 05b7dedd3..25a09b3c4 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift @@ -7,8 +7,6 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { @Published var state: CurrentState = .idle @Published var intent: Intent = .authorize @Published var order: Order? - @Published var createOrderResult: Order? - @Published var transactionResult: Order? @Published var checkoutResult: PayPalWebCheckoutResult? var payPalWebCheckoutClient: PayPalWebCheckoutClient? @@ -49,8 +47,10 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { self.orderID = order.id + // TODO: move back into update method + DispatchQueue.main.async { - self.createOrderResult = order + self.order = order } updateState(.success) print("✅ fetched orderID: \(order.id) with status: \(order.status)") @@ -95,8 +95,9 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { if let orderID { let order = try await DemoMerchantAPI.sharedService.completeOrder(intent: intent, orderID: orderID) + // TODO: move back into update method DispatchQueue.main.async { - self.transactionResult = order + self.order = order } updateState(.success) } From 378785d70090932dbc6ea978636fc5650b9e43c6 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Tue, 12 Dec 2023 09:06:49 -0600 Subject: [PATCH 06/16] WIP - add header to buttons view; cleanup logic --- .../PayPalWebButtonsView.swift | 9 ++++++- .../PayPalWebPaymentsView.swift | 13 +++------- .../PayPalWebResultView.swift | 2 +- .../PayPalWebTransactionView.swift | 4 +++ .../PayPalWebViewModel.swift | 26 ++++++++++--------- 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift index e09d69f25..5a2d631d2 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebButtonsView.swift @@ -11,6 +11,13 @@ struct PayPalWebButtonsView: View { var body: some View { VStack { VStack(alignment: .center, spacing: 16) { + HStack { + Text("Checkout with PayPal") + .font(.system(size: 20)) + Spacer() + } + .frame(maxWidth: .infinity) + .font(.headline) Picker("Funding Source", selection: $selectedFundingSource) { Text("PayPal").tag(PayPalWebCheckoutFundingSource.paypal) Text("PayPal Credit").tag(PayPalWebCheckoutFundingSource.paylater) @@ -33,7 +40,7 @@ struct PayPalWebButtonsView: View { } } } - .frame(height: 100) + .frame(height: 150) .padding(20) .background( RoundedRectangle(cornerRadius: 10) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift index 5ba828869..5d209f7eb 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift @@ -1,12 +1,5 @@ import SwiftUI -enum OrderStatusButton: String { - case created = "Create an Order" - case approved = "Checkout with PayPal" - case completed = "Complete Transaction" -} - -// TODO: make sure errors are handled // TODO: pin result view to bottom // TODO: hide order create view after order created // TODO: scrollview not working as expected @@ -21,12 +14,12 @@ struct PayPalWebPaymentsView: View { ScrollViewReader { scrollView in VStack(spacing: 16) { PayPalWebCreateOrderView(payPalWebViewModel: payPalWebViewModel) - // TODO: replace state with order status? - if payPalWebViewModel.order != nil && payPalWebViewModel.state == .success { + + if payPalWebViewModel.orderID != nil { PayPalWebButtonsView(payPalWebViewModel: payPalWebViewModel) } - if payPalWebViewModel.checkoutResult != nil && payPalWebViewModel.state == .success { + if payPalWebViewModel.checkoutResult != nil { PayPalWebTransactionView(payPalWebViewModel: payPalWebViewModel) } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift index c3bd548d5..65f475f62 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift @@ -24,7 +24,7 @@ struct PayPalWebResultView: View { } if let orderID = payPalWebViewModel.orderID { LeadingText("Order ID", weight: .bold) - LeadingText("\(payPalWebViewModel.order?.id ?? "")") + LeadingText("\(orderID)") } if let status = payPalWebViewModel.order?.status { diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift index 86d82db7c..e8b0a132e 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebTransactionView.swift @@ -18,6 +18,10 @@ struct PayPalWebTransactionView: View { } .buttonStyle(RoundedBlueButtonStyle()) .padding() + + if payPalWebViewModel.state == .loading { + CircularProgressView() + } } } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift index 25a09b3c4..bb4caeeaf 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift @@ -45,13 +45,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { selectedMerchantIntegration: DemoSettings.merchantIntegration ) - self.orderID = order.id - - // TODO: move back into update method - - DispatchQueue.main.async { - self.order = order - } + updateOrder(order) updateState(.success) print("✅ fetched orderID: \(order.id) with status: \(order.status)") } catch { @@ -81,11 +75,15 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } } - func getPayPalClient() async throws -> PayPalWebCheckoutClient { + func getPayPalClient() async throws -> PayPalWebCheckoutClient? { do { let config = try await configManager.getCoreConfig() let payPalClient = PayPalWebCheckoutClient(config: config) return payPalClient + } catch { + updateState(.error(message: error.localizedDescription)) + print("❌ failed to create PayPalWebCheckoutClient with error: \(error.localizedDescription)") + return nil } } @@ -95,10 +93,7 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { if let orderID { let order = try await DemoMerchantAPI.sharedService.completeOrder(intent: intent, orderID: orderID) - // TODO: move back into update method - DispatchQueue.main.async { - self.order = order - } + updateOrder(order) updateState(.success) } } catch { @@ -107,6 +102,13 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } } + private func updateOrder(_ order: Order) { + DispatchQueue.main.async { + self.orderID = order.id + self.order = order + } + } + private func updateState(_ state: CurrentState) { DispatchQueue.main.async { self.state = state From e48b71c061e44d5bc2c9dfa48ba6d6eb8f67bff0 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Wed, 13 Dec 2023 15:32:58 -0600 Subject: [PATCH 07/16] add reset button; start addressing TODOs --- .../PayPalWebPayments/PayPalWebCreateOrderView.swift | 3 +++ .../PayPalWebPayments/PayPalWebPaymentsView.swift | 12 ++++++------ .../PayPalWebPayments/PayPalWebViewModel.swift | 10 +++++++++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebCreateOrderView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebCreateOrderView.swift index 0af1754d6..38308bbba 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebCreateOrderView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebCreateOrderView.swift @@ -13,6 +13,9 @@ struct PayPalWebCreateOrderView: View { Text("Create an Order") .font(.system(size: 20)) Spacer() + Button("Reset") { + payPalWebViewModel.resetState() + } } .frame(maxWidth: .infinity) .font(.headline) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift index 5d209f7eb..5278932f5 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift @@ -1,9 +1,9 @@ import SwiftUI // TODO: pin result view to bottom -// TODO: hide order create view after order created +// TODO: hide create order or disable button until reset +// TODO: fix duplicate spinners // TODO: scrollview not working as expected -// TODO: add reset button struct PayPalWebPaymentsView: View { @@ -19,14 +19,14 @@ struct PayPalWebPaymentsView: View { PayPalWebButtonsView(payPalWebViewModel: payPalWebViewModel) } + PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) + if payPalWebViewModel.checkoutResult != nil { PayPalWebTransactionView(payPalWebViewModel: payPalWebViewModel) + .id("bottomView") } - - PayPalWebResultView(payPalWebViewModel: payPalWebViewModel) - .id("bottomView") } - .onChange(of: payPalWebViewModel.order) { _ in + .onChange(of: payPalWebViewModel.state) { _ in withAnimation { scrollView.scrollTo("bottomView") } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift index bb4caeeaf..6e03aaa86 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift @@ -68,9 +68,10 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { let payPalRequest = PayPalWebCheckoutRequest(orderID: orderID, fundingSource: funding) payPalWebCheckoutClient.start(request: payPalRequest) } + updateState(.success) } catch { print("Error starting PayPalWebCheckoutClient") - state = .error(message: error.localizedDescription) + updateState(.error(message: error.localizedDescription)) } } } @@ -102,6 +103,13 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { } } + func resetState() { + updateState(.idle) + order = nil + checkoutResult = nil + orderID = nil + } + private func updateOrder(_ order: Order) { DispatchQueue.main.async { self.orderID = order.id From aee5ecea9a7fb3db083dfdd697a65d5340f76818 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Wed, 13 Dec 2023 15:44:06 -0600 Subject: [PATCH 08/16] fix duplicate spinners --- .../PayPalWebPayments/PayPalWebCreateOrderView.swift | 2 +- .../PayPalWebPayments/PayPalWebPaymentsView.swift | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebCreateOrderView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebCreateOrderView.swift index 38308bbba..ba995324d 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebCreateOrderView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebCreateOrderView.swift @@ -40,7 +40,7 @@ struct PayPalWebCreateOrderView: View { } } .buttonStyle(RoundedBlueButtonStyle()) - if payPalWebViewModel.state == .loading { + if payPalWebViewModel.state == .loading && payPalWebViewModel.checkoutResult == nil { CircularProgressView() } } diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift index 5278932f5..01d629bfd 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift @@ -1,8 +1,5 @@ import SwiftUI -// TODO: pin result view to bottom -// TODO: hide create order or disable button until reset -// TODO: fix duplicate spinners // TODO: scrollview not working as expected struct PayPalWebPaymentsView: View { From a5154f89ed64cf4372ebfbc208c5780327b80e5b Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Thu, 14 Dec 2023 13:01:29 -0600 Subject: [PATCH 09/16] address scrollview TODO --- .../PayPalWebPayments/PayPalWebPaymentsView.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift index 01d629bfd..2dcdc1dcd 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift @@ -1,7 +1,5 @@ import SwiftUI -// TODO: scrollview not working as expected - struct PayPalWebPaymentsView: View { @StateObject var payPalWebViewModel = PayPalWebViewModel() @@ -21,6 +19,11 @@ struct PayPalWebPaymentsView: View { if payPalWebViewModel.checkoutResult != nil { PayPalWebTransactionView(payPalWebViewModel: payPalWebViewModel) .id("bottomView") + .onAppear { + withAnimation { + scrollView.scrollTo("bottomView") + } + } } } .onChange(of: payPalWebViewModel.state) { _ in From fe86c7e0d59a577559cadc5bd3a13f4f5b76e15a Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Thu, 14 Dec 2023 14:06:22 -0600 Subject: [PATCH 10/16] extract out new SuccessViewText --- Demo/Demo.xcodeproj/project.pbxproj | 4 ++++ .../PayPalWebResultView.swift | 20 +++++++------------ .../PayPalWebPayments/SuccessViewText.swift | 20 +++++++++++++++++++ 3 files changed, 31 insertions(+), 13 deletions(-) create mode 100644 Demo/Demo/SwiftUIComponents/PayPalWebPayments/SuccessViewText.swift diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 3a2c44bd3..9ff2fa437 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -66,6 +66,7 @@ BC9D4D2627C6D1720089E5B1 /* XCUIElement+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9D4D2527C6D1720089E5B1 /* XCUIElement+Helpers.swift */; }; BE1766B326F911A2007EF438 /* URLResponseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE1766B226F911A2007EF438 /* URLResponseError.swift */; }; BE1766D926FA7BC8007EF438 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BE1766D826FA7BC8007EF438 /* Settings.bundle */; }; + BE5898952B2B91F800AA196E /* SuccessViewText.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE5898942B2B91F800AA196E /* SuccessViewText.swift */; }; BE8117642B07E778009867B9 /* PayPalWebResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117632B07E778009867B9 /* PayPalWebResultView.swift */; }; BE8117682B080472009867B9 /* CurrentState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117672B080472009867B9 /* CurrentState.swift */; }; BE9F36D82745490400AFC7DA /* FloatingLabelTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F36D72745490400AFC7DA /* FloatingLabelTextField.swift */; }; @@ -189,6 +190,7 @@ BE1766B226F911A2007EF438 /* URLResponseError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLResponseError.swift; sourceTree = ""; }; BE1766D826FA7BC8007EF438 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; BE420F3628189A7A00D8D66A /* PayPalUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PayPalUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BE5898942B2B91F800AA196E /* SuccessViewText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuccessViewText.swift; sourceTree = ""; }; BE8117632B07E778009867B9 /* PayPalWebResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebResultView.swift; sourceTree = ""; }; BE8117672B080472009867B9 /* CurrentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentState.swift; sourceTree = ""; }; BE9F36D72745490400AFC7DA /* FloatingLabelTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingLabelTextField.swift; sourceTree = ""; }; @@ -272,6 +274,7 @@ BE8117632B07E778009867B9 /* PayPalWebResultView.swift */, 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, 3BA56FFB2A9FEFE90081D14F /* PayPalWebViewModel.swift */, + BE5898942B2B91F800AA196E /* SuccessViewText.swift */, ); path = PayPalWebPayments; sourceTree = ""; @@ -575,6 +578,7 @@ 3BC622092A97198500251B85 /* LeadingText.swift in Sources */, 3B80D5102A291CB100D2EAC4 /* ClientIDResponse.swift in Sources */, 3BCCFE462A9D47AC00C5102F /* CardExtensions.swift in Sources */, + BE5898952B2B91F800AA196E /* SuccessViewText.swift in Sources */, CB34B32328BE3A9A001325B9 /* PayPalViewModel.swift in Sources */, 3BC622072A97115700251B85 /* RoundedBlueButtonStyle.swift in Sources */, 3B4DD9A22A8982B000F4A716 /* CardFormView.swift in Sources */, diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift index 65f475f62..147e5d581 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift @@ -16,40 +16,34 @@ struct PayPalWebResultView: View { } var successView: some View { - VStack(spacing: 16) { + VStack(alignment: .leading, spacing: 16) { HStack { Text("Order Details") .font(.system(size: 20)) Spacer() } if let orderID = payPalWebViewModel.orderID { - LeadingText("Order ID", weight: .bold) - LeadingText("\(orderID)") + SuccessViewText("Order ID:", bodyText: orderID) } if let status = payPalWebViewModel.order?.status { - LeadingText("Status", weight: .bold) - LeadingText("\(status)") + SuccessViewText("Status:", bodyText: status) } if let payerID = payPalWebViewModel.checkoutResult?.payerID { - LeadingText("Payer ID", weight: .bold) - LeadingText("\(payerID)") + SuccessViewText("Payer ID:", bodyText: payerID) } if let emailAddress = payPalWebViewModel.order?.paymentSource?.paypal?.emailAddress { - LeadingText("Email", weight: .bold) - LeadingText("\(emailAddress)") + SuccessViewText("Email:", bodyText: emailAddress) } if let vaultID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.id { - LeadingText("Vault ID / Payment Token", weight: .bold) - LeadingText("\(vaultID)") + SuccessViewText("Vault ID / Payment Token:", bodyText: vaultID) } if let customerID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.customer.id { - LeadingText("Customer ID", weight: .bold) - LeadingText("\(customerID)") + SuccessViewText("Customer ID:", bodyText: customerID) } } .frame(maxWidth: .infinity) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/SuccessViewText.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/SuccessViewText.swift new file mode 100644 index 000000000..f7a8a956d --- /dev/null +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/SuccessViewText.swift @@ -0,0 +1,20 @@ +import SwiftUI + +// TODO: Move this to a shared space once all modules are converted + +struct SuccessViewText: View { + + var titleText: String + var bodyText: String + + var body: some View { + HStack { + Text(titleText).fontWeight(.bold) + Text(bodyText) + } } + + init(_ titleText: String, bodyText: String) { + self.titleText = titleText + self.bodyText = bodyText + } +} From 69318d94f5763ada8de9c7a9318df83d1e653671 Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Thu, 14 Dec 2023 16:59:46 -0600 Subject: [PATCH 11/16] move SuccessViewText into Common Components --- Demo/Demo.xcodeproj/project.pbxproj | 2 +- .../SuccessViewText.swift | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) rename Demo/Demo/SwiftUIComponents/{PayPalWebPayments => CommonComponents}/SuccessViewText.swift (83%) diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 9ff2fa437..d5d279505 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -274,7 +274,6 @@ BE8117632B07E778009867B9 /* PayPalWebResultView.swift */, 3B6472A62AFAEB3A004745C4 /* PayPalWebTransactionView.swift */, 3BA56FFB2A9FEFE90081D14F /* PayPalWebViewModel.swift */, - BE5898942B2B91F800AA196E /* SuccessViewText.swift */, ); path = PayPalWebPayments; sourceTree = ""; @@ -289,6 +288,7 @@ 3BC6220A2A97204E00251B85 /* CircularProgressView.swift */, 3BC622082A97198500251B85 /* LeadingText.swift */, 3BA5700A2AA13C1C0081D14F /* CoreConfigManager.swift */, + BE5898942B2B91F800AA196E /* SuccessViewText.swift */, ); path = CommonComponents; sourceTree = ""; diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/SuccessViewText.swift b/Demo/Demo/SwiftUIComponents/CommonComponents/SuccessViewText.swift similarity index 83% rename from Demo/Demo/SwiftUIComponents/PayPalWebPayments/SuccessViewText.swift rename to Demo/Demo/SwiftUIComponents/CommonComponents/SuccessViewText.swift index f7a8a956d..0501a66a6 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/SuccessViewText.swift +++ b/Demo/Demo/SwiftUIComponents/CommonComponents/SuccessViewText.swift @@ -1,7 +1,5 @@ import SwiftUI -// TODO: Move this to a shared space once all modules are converted - struct SuccessViewText: View { var titleText: String From f492a3381753b50dccf4b655f5fe2ac8cc0b1c4a Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Thu, 14 Dec 2023 19:21:17 -0600 Subject: [PATCH 12/16] add padding to bottom view --- .../PayPalWebPayments/PayPalWebPaymentsView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift index 2dcdc1dcd..3b47ac991 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebPaymentsView.swift @@ -18,6 +18,7 @@ struct PayPalWebPaymentsView: View { if payPalWebViewModel.checkoutResult != nil { PayPalWebTransactionView(payPalWebViewModel: payPalWebViewModel) + .padding(.bottom, 20) .id("bottomView") .onAppear { withAnimation { From 23e580cc982915d62e6047d6ee226a247653c75a Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Thu, 14 Dec 2023 19:26:10 -0600 Subject: [PATCH 13/16] simplify payment token label --- .../PayPalWebPayments/PayPalWebResultView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift index 147e5d581..4987dacc1 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift @@ -39,7 +39,7 @@ struct PayPalWebResultView: View { } if let vaultID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.id { - SuccessViewText("Vault ID / Payment Token:", bodyText: vaultID) + SuccessViewText("Payment Token:", bodyText: vaultID) } if let customerID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.customer.id { From e3f37fa498ef94950551717cc24599682003d9ca Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Thu, 14 Dec 2023 19:29:09 -0600 Subject: [PATCH 14/16] rename SuccessViewText to LabelViewText --- Demo/Demo.xcodeproj/project.pbxproj | 8 ++++---- .../{SuccessViewText.swift => LabelViewText.swift} | 2 +- .../PayPalWebPayments/PayPalWebResultView.swift | 12 ++++++------ 3 files changed, 11 insertions(+), 11 deletions(-) rename Demo/Demo/SwiftUIComponents/CommonComponents/{SuccessViewText.swift => LabelViewText.swift} (91%) diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index d5d279505..d4a534605 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -66,7 +66,7 @@ BC9D4D2627C6D1720089E5B1 /* XCUIElement+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9D4D2527C6D1720089E5B1 /* XCUIElement+Helpers.swift */; }; BE1766B326F911A2007EF438 /* URLResponseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE1766B226F911A2007EF438 /* URLResponseError.swift */; }; BE1766D926FA7BC8007EF438 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BE1766D826FA7BC8007EF438 /* Settings.bundle */; }; - BE5898952B2B91F800AA196E /* SuccessViewText.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE5898942B2B91F800AA196E /* SuccessViewText.swift */; }; + BE5898952B2B91F800AA196E /* LabelViewText.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE5898942B2B91F800AA196E /* LabelViewText.swift */; }; BE8117642B07E778009867B9 /* PayPalWebResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117632B07E778009867B9 /* PayPalWebResultView.swift */; }; BE8117682B080472009867B9 /* CurrentState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8117672B080472009867B9 /* CurrentState.swift */; }; BE9F36D82745490400AFC7DA /* FloatingLabelTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F36D72745490400AFC7DA /* FloatingLabelTextField.swift */; }; @@ -190,7 +190,7 @@ BE1766B226F911A2007EF438 /* URLResponseError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLResponseError.swift; sourceTree = ""; }; BE1766D826FA7BC8007EF438 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; BE420F3628189A7A00D8D66A /* PayPalUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PayPalUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - BE5898942B2B91F800AA196E /* SuccessViewText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuccessViewText.swift; sourceTree = ""; }; + BE5898942B2B91F800AA196E /* LabelViewText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelViewText.swift; sourceTree = ""; }; BE8117632B07E778009867B9 /* PayPalWebResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalWebResultView.swift; sourceTree = ""; }; BE8117672B080472009867B9 /* CurrentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentState.swift; sourceTree = ""; }; BE9F36D72745490400AFC7DA /* FloatingLabelTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingLabelTextField.swift; sourceTree = ""; }; @@ -288,7 +288,7 @@ 3BC6220A2A97204E00251B85 /* CircularProgressView.swift */, 3BC622082A97198500251B85 /* LeadingText.swift */, 3BA5700A2AA13C1C0081D14F /* CoreConfigManager.swift */, - BE5898942B2B91F800AA196E /* SuccessViewText.swift */, + BE5898942B2B91F800AA196E /* LabelViewText.swift */, ); path = CommonComponents; sourceTree = ""; @@ -578,7 +578,7 @@ 3BC622092A97198500251B85 /* LeadingText.swift in Sources */, 3B80D5102A291CB100D2EAC4 /* ClientIDResponse.swift in Sources */, 3BCCFE462A9D47AC00C5102F /* CardExtensions.swift in Sources */, - BE5898952B2B91F800AA196E /* SuccessViewText.swift in Sources */, + BE5898952B2B91F800AA196E /* LabelViewText.swift in Sources */, CB34B32328BE3A9A001325B9 /* PayPalViewModel.swift in Sources */, 3BC622072A97115700251B85 /* RoundedBlueButtonStyle.swift in Sources */, 3B4DD9A22A8982B000F4A716 /* CardFormView.swift in Sources */, diff --git a/Demo/Demo/SwiftUIComponents/CommonComponents/SuccessViewText.swift b/Demo/Demo/SwiftUIComponents/CommonComponents/LabelViewText.swift similarity index 91% rename from Demo/Demo/SwiftUIComponents/CommonComponents/SuccessViewText.swift rename to Demo/Demo/SwiftUIComponents/CommonComponents/LabelViewText.swift index 0501a66a6..58a470c9c 100644 --- a/Demo/Demo/SwiftUIComponents/CommonComponents/SuccessViewText.swift +++ b/Demo/Demo/SwiftUIComponents/CommonComponents/LabelViewText.swift @@ -1,6 +1,6 @@ import SwiftUI -struct SuccessViewText: View { +struct LabelViewText: View { var titleText: String var bodyText: String diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift index 4987dacc1..bb3bfa5ac 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebResultView.swift @@ -23,27 +23,27 @@ struct PayPalWebResultView: View { Spacer() } if let orderID = payPalWebViewModel.orderID { - SuccessViewText("Order ID:", bodyText: orderID) + LabelViewText("Order ID:", bodyText: orderID) } if let status = payPalWebViewModel.order?.status { - SuccessViewText("Status:", bodyText: status) + LabelViewText("Status:", bodyText: status) } if let payerID = payPalWebViewModel.checkoutResult?.payerID { - SuccessViewText("Payer ID:", bodyText: payerID) + LabelViewText("Payer ID:", bodyText: payerID) } if let emailAddress = payPalWebViewModel.order?.paymentSource?.paypal?.emailAddress { - SuccessViewText("Email:", bodyText: emailAddress) + LabelViewText("Email:", bodyText: emailAddress) } if let vaultID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.id { - SuccessViewText("Payment Token:", bodyText: vaultID) + LabelViewText("Payment Token:", bodyText: vaultID) } if let customerID = payPalWebViewModel.order?.paymentSource?.paypal?.attributes?.vault.customer.id { - SuccessViewText("Customer ID:", bodyText: customerID) + LabelViewText("Customer ID:", bodyText: customerID) } } .frame(maxWidth: .infinity) From 2c4bfa571defdd69d349c3ddf3f2098f62ac013f Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Thu, 14 Dec 2023 19:30:58 -0600 Subject: [PATCH 15/16] update spacing --- .../SwiftUIComponents/CommonComponents/LabelViewText.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Demo/Demo/SwiftUIComponents/CommonComponents/LabelViewText.swift b/Demo/Demo/SwiftUIComponents/CommonComponents/LabelViewText.swift index 58a470c9c..a1f63367c 100644 --- a/Demo/Demo/SwiftUIComponents/CommonComponents/LabelViewText.swift +++ b/Demo/Demo/SwiftUIComponents/CommonComponents/LabelViewText.swift @@ -9,7 +9,8 @@ struct LabelViewText: View { HStack { Text(titleText).fontWeight(.bold) Text(bodyText) - } } + } + } init(_ titleText: String, bodyText: String) { self.titleText = titleText From 2b0c8db4aa1d593beb2afaffdeb2abbc57620d3c Mon Sep 17 00:00:00 2001 From: Jax DesMarais-Leder Date: Thu, 21 Dec 2023 10:23:24 -0600 Subject: [PATCH 16/16] PR feedback: update orderID to computed property --- .../PayPalWebPayments/PayPalWebViewModel.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift index 6e03aaa86..224c435ba 100644 --- a/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift +++ b/Demo/Demo/SwiftUIComponents/PayPalWebPayments/PayPalWebViewModel.swift @@ -10,7 +10,10 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { @Published var checkoutResult: PayPalWebCheckoutResult? var payPalWebCheckoutClient: PayPalWebCheckoutClient? - var orderID: String? + + var orderID: String? { + order?.id + } let configManager = CoreConfigManager(domain: "PayPalWeb Payments") @@ -107,12 +110,10 @@ class PayPalWebViewModel: ObservableObject, PayPalWebCheckoutDelegate { updateState(.idle) order = nil checkoutResult = nil - orderID = nil } private func updateOrder(_ order: Order) { DispatchQueue.main.async { - self.orderID = order.id self.order = order } }