Skip to content

Commit 40f9141

Browse files
authored
Merge pull request #8689 from woocommerce/issue/8688-connect-ipp-banner-vm-and-vc
[IPPInAppFeedback] Make banner content and surveys change dynamically
2 parents 18ab5c9 + 1dc6c46 commit 40f9141

File tree

6 files changed

+139
-51
lines changed

6 files changed

+139
-51
lines changed

WooCommerce/Classes/Analytics/WooAnalyticsEvent.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ extension WooAnalyticsEvent {
7575
case orderCreation = "order_creation"
7676
/// Shown in beta feature banner for coupon management.
7777
case couponManagement = "coupon_management"
78+
/// Shown in IPP banner for eligible merchants with no IPP transactions.
79+
case inPersonPaymentsCashOnDeliveryBanner
80+
/// Shown in IPP banner for eligible merchants with a few IPP transactions.
81+
case inPersonPaymentsFirstTransactionBanner
82+
/// Shown in IPP banner for eligible merchants with a significant number of IPP transactions.
83+
case inPersonPaymentsPowerUsersBanner
7884
}
7985

8086
/// The action performed on the survey screen.

WooCommerce/Classes/System/WooConstants.swift

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,28 @@ extension WooConstants {
155155
///
156156
#if DEBUG
157157
case inAppFeedback = "https://automattic.survey.fm/woo-app-general-feedback-test-survey"
158-
case IPPFeedback = "https://automattic.survey.fm/woo-app-ipp-in-app-feedback-testing"
159158
#else
160159
case inAppFeedback = "https://automattic.survey.fm/woo-app-general-feedback-user-survey"
161-
case IPPFeedback = "https://automattic.survey.fm/woo-app-ipp-in-app-feedback-testing"
160+
#endif
161+
162+
/// URL for the IPP feedback survey for testing purposes
163+
///
164+
#if DEBUG
165+
case inPersonPaymentsCashOnDeliveryFeedback,
166+
inPersonPaymentsFirstTransactionFeedback,
167+
inPersonPaymentsPowerUsersFeedback = "https://automattic.survey.fm/woo-app-ipp-in-app-feedback-testing"
168+
#else
169+
/// URL for the IPP feedback survey (COD case). Used when merchants have COD enabled, but no IPP transactions.
170+
///
171+
case inPersonPaymentsCashOnDeliveryFeedback = "https://automattic.survey.fm/woo-app-–-cod-survey"
172+
173+
/// URL for IPP feedback survey (First Transaction case). Used when merchants have only a few IPP transactions.
174+
///
175+
case inPersonPaymentsFirstTransactionFeedback = "https://automattic.survey.fm/woo-app-–-ipp-first-transaction-survey"
176+
177+
/// URL for IPP feedback survey (Power Users case). Used when merchants have a significant number of IPP transactions.
178+
///
179+
case inPersonPaymentsPowerUsersFeedback = "https://automattic.survey.fm/woo-app-–-ipp-survey-for-power-users"
162180
#endif
163181

164182
/// URL for the products feedback survey

WooCommerce/Classes/ViewRelated/Orders/OrderListViewController.swift

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ final class OrderListViewController: UIViewController, GhostableViewController {
120120
///
121121
private var swipeActionsGlanced = false
122122

123+
/// Banner variation that will be shown as In-Person Payments feedback banner. If any.
124+
///
125+
private var inPersonPaymentsSurveyVariation: SurveyViewController.Source?
126+
123127

124128
// MARK: - View Lifecycle
125129

@@ -158,7 +162,7 @@ final class OrderListViewController: UIViewController, GhostableViewController {
158162
configureSyncingCoordinator()
159163

160164
if ServiceLocator.featureFlagService.isFeatureFlagEnabled(.IPPInAppFeedbackBanner) {
161-
viewModel.displayIPPFeedbackBannerIfEligible()
165+
inPersonPaymentsSurveyVariation = viewModel.feedbackBannerSurveySource()
162166
}
163167
}
164168

@@ -255,7 +259,10 @@ private extension OrderListViewController {
255259
case .orderCreation:
256260
self.setOrderCreationTopBanner()
257261
case .IPPFeedback:
258-
self.setIPPFeedbackTopBanner()
262+
guard let survey = self.inPersonPaymentsSurveyVariation else {
263+
return
264+
}
265+
self.setIPPFeedbackTopBanner(survey: survey)
259266
}
260267
}
261268
.store(in: &cancellables)
@@ -353,6 +360,7 @@ extension OrderListViewController: SyncingCoordinatorDelegate {
353360

354361
transitionToSyncingState()
355362
viewModel.hasErrorLoadingData = false
363+
viewModel.updateBannerVisibility()
356364

357365
let action = viewModel.synchronizationAction(
358366
siteID: siteID,
@@ -788,19 +796,36 @@ private extension OrderListViewController {
788796

789797
/// Sets the `topBannerView` property to an IPP feedback banner.
790798
///
791-
func setIPPFeedbackTopBanner() {
792-
topBannerView = createIPPFeedbackTopBanner()
799+
func setIPPFeedbackTopBanner(survey: SurveyViewController.Source) {
800+
topBannerView = createIPPFeedbackTopBanner(survey: survey)
793801
showTopBannerView()
794802
}
795803

796-
private func createIPPFeedbackTopBanner() -> TopBannerView {
804+
private func createIPPFeedbackTopBanner(survey: SurveyViewController.Source) -> TopBannerView {
797805
let shareIPPFeedbackAction = TopBannerViewModel.ActionButton(title: Localization.shareFeedbackButton, action: { _ in
798-
self.displayIPPFeedbackBannerSurvey()
806+
self.displayIPPFeedbackBannerSurvey(survey: survey)
799807
})
800808

809+
var bannerTitle = ""
810+
var bannerText = ""
811+
812+
switch survey {
813+
case .IPP_COD :
814+
bannerTitle = Localization.inPersonPaymentsCashOnDeliveryBannerTitle
815+
bannerText = Localization.inPersonPaymentsCashOnDeliveryBannerContent
816+
case .IPP_firstTransaction:
817+
bannerTitle = Localization.inPersonPaymentsFirstTransactionBannerTitle
818+
bannerTitle = Localization.inPersonPaymentsFirstTransactionBannerContent
819+
case .IPP_powerUsers:
820+
bannerTitle = Localization.inPersonPaymentsPowerUsersBannerTitle
821+
bannerTitle = Localization.inPersonPaymentsPowerUsersBannerContent
822+
default:
823+
break
824+
}
825+
801826
let viewModel = TopBannerViewModel(
802-
title: Localization.feedbackBannerTitle,
803-
infoText: Localization.feedbackBannerContent,
827+
title: bannerTitle,
828+
infoText: bannerText,
804829
icon: UIImage.gridicon(.comment),
805830
isExpanded: true,
806831
topButton: .dismiss(handler: { }),
@@ -811,9 +836,8 @@ private extension OrderListViewController {
811836
return topBannerView
812837
}
813838

814-
private func displayIPPFeedbackBannerSurvey() {
815-
// TODO: Survey will change based on conditions
816-
let surveyNavigation = SurveyCoordinatingController(survey: .IPPFeedback)
839+
private func displayIPPFeedbackBannerSurvey(survey: SurveyViewController.Source) {
840+
let surveyNavigation = SurveyCoordinatingController(survey: survey)
817841
self.present(surveyNavigation, animated: true, completion: nil)
818842
}
819843
}
@@ -834,14 +858,30 @@ private extension OrderListViewController {
834858

835859
static let markCompleted = NSLocalizedString("Mark Completed", comment: "Title for the swipe order action to mark it as completed")
836860

837-
static let feedbackBannerTitle = NSLocalizedString("Let us know what you think",
861+
static let inPersonPaymentsCashOnDeliveryBannerTitle = NSLocalizedString("Let us know how we can help",
838862
comment: "Title of the In-Person Payments feedback banner in the Orders tab"
839863
)
840864

841-
static let feedbackBannerContent = NSLocalizedString("Rate your In-Person Payment experience.",
865+
static let inPersonPaymentsFirstTransactionBannerTitle = NSLocalizedString("Enjoyed your in-person payment?",
866+
comment: "Title of the In-Person Payments feedback banner in the Orders tab"
867+
)
868+
869+
static let inPersonPaymentsPowerUsersBannerTitle = NSLocalizedString("Let us know what you think",
870+
comment: "Title of the In-Person Payments feedback banner in the Orders tab"
871+
)
872+
873+
static let inPersonPaymentsCashOnDeliveryBannerContent = NSLocalizedString("Share your own experience or how you collect in-person payments.",
842874
comment: "Content of the In-Person Payments feedback banner in the Orders tab"
843875
)
844876

877+
static let inPersonPaymentsFirstTransactionBannerContent = NSLocalizedString("Rate your first in-person payment experience.",
878+
comment: "Content of the In-Person Payments feedback banner in the Orders tab"
879+
)
880+
881+
static let inPersonPaymentsPowerUsersBannerContent = NSLocalizedString("Tell us all about your experience with in-person payments.",
882+
comment: "Content of the In-Person Payments feedback banner in the Orders tab"
883+
)
884+
845885
static let shareFeedbackButton = NSLocalizedString("Share feedback",
846886
comment: "Title of the feedback action button on the In-Person Payments feedback banner"
847887
)

WooCommerce/Classes/ViewRelated/Orders/OrderListViewModel.swift

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -174,13 +174,6 @@ final class OrderListViewModel {
174174

175175
observeForegroundRemoteNotifications()
176176
bindTopBannerState()
177-
178-
if ServiceLocator.featureFlagService.isFeatureFlagEnabled(.IPPInAppFeedbackBanner) {
179-
syncIPPBannerVisibility()
180-
loadOrdersBannerVisibility()
181-
} else {
182-
loadOrdersBannerVisibility()
183-
}
184177
}
185178

186179
func dismissOrdersBanner() {
@@ -196,6 +189,15 @@ final class OrderListViewModel {
196189
stores.dispatch(action)
197190
}
198191

192+
func updateBannerVisibility() {
193+
if ServiceLocator.featureFlagService.isFeatureFlagEnabled(.IPPInAppFeedbackBanner) {
194+
syncIPPBannerVisibility()
195+
loadOrdersBannerVisibility()
196+
} else {
197+
loadOrdersBannerVisibility()
198+
}
199+
}
200+
199201
/// Starts the snapshotsProvider, logging any errors.
200202
private func startReceivingSnapshots() {
201203
do {
@@ -281,7 +283,7 @@ final class OrderListViewModel {
281283
}
282284
}
283285

284-
func displayIPPFeedbackBannerIfEligible() {
286+
func feedbackBannerSurveySource() -> SurveyViewController.Source? {
285287
if isCODEnabled && isIPPSupportedCountry {
286288
let hasResults = IPPOrdersResultsController.fetchedObjects.isEmpty ? false : true
287289

@@ -294,22 +296,15 @@ final class OrderListViewModel {
294296
$0.paymentMethodTitle == Constants.paymentMethodTitle})
295297
let IPPresultsCount = IPPTransactionsFound.count
296298

297-
// TODO: Debug. Remove before merging
298-
print("COD enabled? \(isCODEnabled) - Eligible Country? \(isIPPSupportedCountry)")
299-
print("hasResults? \(hasResults)")
300-
print("IPP transactions within 30 days: \(IPPresultsCount)")
301-
print(recentIPPOrdersResultsController.fetchedObjects.map {
302-
("OrderID: \($0.orderID) - PaymentMethodID: \($0.paymentMethodID) (\($0.paymentMethodTitle) - DatePaid: \(String(describing: $0.datePaid))")
303-
})
304-
305299
if !hasResults {
306-
print("0 transactions. Banner 1 shown")
307-
} else if IPPresultsCount < Constants.numberOfTransactions {
308-
print("< 10 transactions within 30 days. Banner 2 shown")
309-
} else if IPPresultsCount >= Constants.numberOfTransactions {
310-
print(">= 10 transactions within 30 days. Banner 3 shown")
311-
}
300+
return .IPP_COD
301+
} else if IPPresultsCount < Constants.numberOfTransactions {
302+
return .IPP_firstTransaction
303+
} else if IPPresultsCount >= Constants.numberOfTransactions {
304+
return .IPP_powerUsers
305+
}
312306
}
307+
return nil
313308
}
314309

315310
private func createQuery() -> FetchResultSnapshotsProvider<StorageOrder>.Query {

WooCommerce/Classes/ViewRelated/Survey/SurveyViewController.swift

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ extension SurveyViewController {
6868
case addOnsI1
6969
case orderCreation
7070
case couponManagement
71-
case IPPFeedback
71+
case IPP_COD
72+
case IPP_firstTransaction
73+
case IPP_powerUsers
7274

7375
fileprivate var url: URL {
7476
switch self {
@@ -103,8 +105,18 @@ extension SurveyViewController {
103105
.asURL()
104106
.tagPlatform("ios")
105107
.tagAppVersion(Bundle.main.bundleVersion())
106-
case .IPPFeedback:
107-
return WooConstants.URLs.IPPFeedback
108+
case .IPP_COD:
109+
return WooConstants.URLs.inPersonPaymentsCashOnDeliveryFeedback
110+
.asURL()
111+
.tagPlatform("ios")
112+
.tagAppVersion(Bundle.main.bundleVersion())
113+
case .IPP_firstTransaction:
114+
return WooConstants.URLs.inPersonPaymentsFirstTransactionFeedback
115+
.asURL()
116+
.tagPlatform("ios")
117+
.tagAppVersion(Bundle.main.bundleVersion())
118+
case .IPP_powerUsers:
119+
return WooConstants.URLs.inPersonPaymentsPowerUsersFeedback
108120
.asURL()
109121
.tagPlatform("ios")
110122
.tagAppVersion(Bundle.main.bundleVersion())
@@ -113,17 +125,17 @@ extension SurveyViewController {
113125

114126
fileprivate var title: String {
115127
switch self {
116-
case .inAppFeedback:
128+
case .inAppFeedback, .IPP_COD, .IPP_firstTransaction, .IPP_powerUsers:
117129
return Localization.title
118-
case .productsFeedback, .shippingLabelsRelease3Feedback, .addOnsI1, .orderCreation, .couponManagement, .IPPFeedback:
130+
case .productsFeedback, .shippingLabelsRelease3Feedback, .addOnsI1, .orderCreation, .couponManagement:
119131
return Localization.giveFeedback
120132
}
121133
}
122134

123135
/// The corresponding `FeedbackContext` for event tracking purposes.
124136
var feedbackContextForEvents: WooAnalyticsEvent.FeedbackContext {
125137
switch self {
126-
case .inAppFeedback, .IPPFeedback:
138+
case .inAppFeedback:
127139
return .general
128140
case .productsFeedback:
129141
return .productsGeneral
@@ -135,6 +147,12 @@ extension SurveyViewController {
135147
return .orderCreation
136148
case .couponManagement:
137149
return .couponManagement
150+
case .IPP_COD:
151+
return .inPersonPaymentsCashOnDeliveryBanner
152+
case .IPP_firstTransaction:
153+
return .inPersonPaymentsFirstTransactionBanner
154+
case .IPP_powerUsers:
155+
return .inPersonPaymentsPowerUsersBanner
138156
}
139157
}
140158
}

0 commit comments

Comments
 (0)