Skip to content

Commit 335e348

Browse files
authored
[POS as a tab i2] Update POS ineligible UI with detailed text and design updates (#15859)
2 parents fe81261 + 156eefe commit 335e348

File tree

3 files changed

+238
-106
lines changed

3 files changed

+238
-106
lines changed

WooCommerce/Classes/POS/TabBar/POSIneligibleView.swift

Lines changed: 207 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2,129 +2,259 @@ import SwiftUI
22

33
/// A view that displays when the Point of Sale (POS) feature is not available for the current store.
44
/// Shows the specific reason why POS is ineligible and provides a button to re-check eligibility.
5+
@available(iOS 17.0, *)
56
struct POSIneligibleView: View {
67
let reason: POSIneligibleReason
78
let onRefresh: () async throws -> Void
89
@Environment(\.dismiss) private var dismiss
910
@State private var isLoading: Bool = false
1011

1112
var body: some View {
12-
VStack(spacing: POSSpacing.large) {
13-
HStack {
14-
Spacer()
15-
Button {
16-
dismiss()
17-
} label: {
18-
Text(Image(systemName: "xmark"))
19-
.font(POSFontStyle.posButtonSymbolLarge.font())
20-
}
21-
.foregroundColor(Color.posOnSurfaceVariantLowest)
22-
}
23-
13+
VStack(spacing: POSSpacing.none) {
2414
Spacer()
2515

26-
VStack(spacing: POSSpacing.medium) {
16+
VStack(alignment: .center, spacing: POSSpacing.none) {
2717
Image(PointOfSaleAssets.exclamationMark.imageName)
2818
.resizable()
2919
.frame(width: POSErrorAndAlertIconSize.large.dimension,
3020
height: POSErrorAndAlertIconSize.large.dimension)
3121

32-
Text(reasonText)
33-
.font(POSFontStyle.posHeadingBold.font())
34-
.multilineTextAlignment(.center)
35-
.foregroundColor(Color.posOnSurface)
36-
37-
Button {
38-
Task { @MainActor in
39-
do {
40-
isLoading = true
41-
try await onRefresh()
42-
isLoading = false
43-
} catch {
44-
// TODO-jc: handle error if needed, e.g., show an error message
45-
print("Error refreshing eligibility: \(error)")
46-
isLoading = false
22+
Spacer()
23+
.frame(height: POSSpacing.medium)
24+
25+
VStack(spacing: POSSpacing.small) {
26+
Text(Localization.title)
27+
.font(POSFontStyle.posHeadingBold.font())
28+
.multilineTextAlignment(.center)
29+
.foregroundColor(Color.posOnSurface)
30+
31+
Text(suggestionText)
32+
.font(POSFontStyle.posBodyLargeRegular().font())
33+
.multilineTextAlignment(.center)
34+
.foregroundColor(Color.posOnSurface)
35+
}
36+
.containerRelativeFrame(.horizontal) { length, _ in
37+
max(length * 0.5, 300)
38+
}
39+
40+
Spacer()
41+
.frame(height: POSSpacing.large)
42+
43+
VStack(spacing: POSSpacing.medium) {
44+
Button {
45+
Task { @MainActor in
46+
do {
47+
isLoading = true
48+
try await onRefresh()
49+
isLoading = false
50+
} catch {
51+
// TODO: WOOMOB-720 - handle error if needed, e.g., show an error message
52+
DDLogError("Error refreshing eligibility: \(error)")
53+
isLoading = false
54+
}
4755
}
56+
} label: {
57+
Text(Localization.refreshEligibility)
4858
}
49-
} label: {
50-
Text(Localization.refreshEligibility)
59+
.buttonStyle(POSFilledButtonStyle(size: .normal, isLoading: isLoading))
60+
61+
Button {
62+
dismiss()
63+
} label: {
64+
Text(Localization.dismiss)
65+
}
66+
.buttonStyle(POSOutlinedButtonStyle(size: .normal))
67+
}
68+
.containerRelativeFrame(.horizontal) { length, _ in
69+
max(length * 0.5 - 132, 300)
5170
}
52-
.buttonStyle(POSFilledButtonStyle(size: .normal, isLoading: isLoading))
5371
}
5472

5573
Spacer()
5674
}
5775
.padding(POSPadding.large)
5876
}
5977

60-
private var reasonText: String {
78+
private var suggestionText: String {
6179
switch reason {
6280
case .notTablet:
63-
return NSLocalizedString("pos.ineligible.reason.notTablet",
64-
value: "POS is only available on iPad.",
65-
comment: "Ineligible reason: not a tablet")
81+
return NSLocalizedString("pos.ineligible.suggestion.notTablet",
82+
value: "Please use a tablet to access POS features.",
83+
comment: "Suggestion for not tablet: use iPad")
6684
case .unsupportedIOSVersion:
67-
return NSLocalizedString("pos.ineligible.reason.unsupportedIOSVersion",
68-
value: "POS requires a newer version of iOS 17 and above.",
69-
comment: "Ineligible reason: iOS version too low")
70-
case .unsupportedWooCommerceVersion:
71-
return NSLocalizedString("pos.ineligible.reason.unsupportedWooCommerceVersion",
72-
value: "Please update WooCommerce plugin to use POS.",
73-
comment: "Ineligible reason: WooCommerce version too low")
85+
return NSLocalizedString("pos.ineligible.suggestion.unsupportedIOSVersion",
86+
value: "Point of Sale requires iOS 17 or later. Please update your device to iOS 17+ to use this feature.",
87+
comment: "Suggestion for unsupported iOS version: update iOS")
88+
case let .unsupportedWooCommerceVersion(minimumVersion):
89+
let format = NSLocalizedString("pos.ineligible.suggestion.unsupportedWooCommerceVersion",
90+
value: "Your WooCommerce version is not supported. " +
91+
"The POS system requires WooCommerce version %1$@ or above. Please update WooCommerce to the latest version.",
92+
comment: "Suggestion for unsupported WooCommerce version: update plugin. " +
93+
"%1$@ is a placeholder for the minimum required version.")
94+
return String.localizedStringWithFormat(format, minimumVersion)
7495
case .wooCommercePluginNotFound:
75-
return NSLocalizedString("pos.ineligible.reason.wooCommercePluginNotFound",
76-
value: "WooCommerce plugin not found.",
77-
comment: "Ineligible reason: plugin missing")
96+
return NSLocalizedString("pos.ineligible.suggestion.wooCommercePluginNotFound",
97+
value: "Install and activate the WooCommerce plugin from your WordPress admin.",
98+
comment: "Suggestion for missing WooCommerce plugin: install plugin")
7899
case .featureSwitchDisabled:
79-
return NSLocalizedString("pos.ineligible.reason.featureSwitchDisabled",
80-
value: "POS feature is not enabled for your store.",
81-
comment: "Ineligible reason: feature switch off")
100+
return NSLocalizedString("pos.ineligible.suggestion.featureSwitchDisabled",
101+
value: "Point of Sale must be enabled to proceed. " +
102+
"Please enable the POS feature from your WordPress admin under WooCommerce settings > Advanced > Features.",
103+
comment: "Suggestion for disabled feature switch: enable feature in WooCommerce settings")
82104
case .featureSwitchSyncFailure:
83-
return NSLocalizedString("pos.ineligible.reason.featureSwitchSyncFailure",
84-
value: "Could not verify POS feature status.",
85-
comment: "Ineligible reason: feature switch sync failed")
86-
case .unsupportedCountry:
87-
return NSLocalizedString("pos.ineligible.reason.unsupportedCountry",
88-
value: "POS is not available in your country.",
89-
comment: "Ineligible reason: country not supported")
90-
case .unsupportedCurrency:
91-
return NSLocalizedString("pos.ineligible.reason.unsupportedCurrency",
92-
value: "POS is not available for your store's currency.",
93-
comment: "Ineligible reason: currency not supported")
105+
return NSLocalizedString("pos.ineligible.suggestion.featureSwitchSyncFailure",
106+
value: "Try relaunching the app or check your internet connection and try again.",
107+
comment: "Suggestion for feature switch sync failure: relaunch or check connection")
108+
case let .unsupportedCountry(supportedCountries):
109+
let countryNames = supportedCountries.map { $0.readableCountry }
110+
let formattedCountryList = ListFormatter.localizedString(byJoining: countryNames)
111+
let format = NSLocalizedString(
112+
"pos.ineligible.suggestion.unsupportedCountry",
113+
value: "POS is currently only available in %1$@. Check back later for availability in your region.",
114+
comment: "Suggestion for unsupported country with list of supported countries. " +
115+
"%1$@ is a placeholder for the localized list of supported country names."
116+
)
117+
return String.localizedStringWithFormat(format, formattedCountryList)
118+
case let .unsupportedCurrency(supportedCurrencies):
119+
let currencyList = supportedCurrencies.map { $0.rawValue }
120+
let formattedCurrencyList = ListFormatter.localizedString(byJoining: currencyList)
121+
let format = NSLocalizedString(
122+
"pos.ineligible.suggestion.unsupportedCurrency",
123+
value: "The POS system is not available for your store’s currency. It currently supports only %1$@. " +
124+
"Please check your store currency settings or contact support for assistance.",
125+
comment: "Suggestion for unsupported currency with list of supported currencies. " +
126+
"%1$@ is a placeholder for the localized list of supported currency codes."
127+
)
128+
return String.localizedStringWithFormat(format, formattedCurrencyList)
94129
case .siteSettingsNotAvailable:
95-
return NSLocalizedString("pos.ineligible.reason.siteSettingsNotAvailable",
96-
value: "Unable to load store settings for POS.",
97-
comment: "Ineligible reason: site settings unavailable")
130+
return NSLocalizedString("pos.ineligible.suggestion.siteSettingsNotAvailable",
131+
value: "Check your internet connection and try relaunching the app. If the issue persists, please contact support.",
132+
comment: "Suggestion for site settings unavailable: check connection or contact support")
98133
case .featureFlagDisabled:
99-
return NSLocalizedString("pos.ineligible.reason.featureFlagDisabled",
100-
value: "POS feature is currently disabled.",
101-
comment: "Ineligible reason: feature flag disabled")
134+
return NSLocalizedString("pos.ineligible.suggestion.featureFlagDisabled",
135+
value: "POS is currently disabled.",
136+
comment: "Suggestion for disabled feature flag: notify that POS is disabled remotely")
102137
case .selfDeallocated:
103-
return Localization.defaultReason
138+
return NSLocalizedString("pos.ineligible.suggestion.selfDeallocated",
139+
value: "Try relaunching the app to resolve this issue.",
140+
comment: "Suggestion for self deallocated: relaunch")
104141
}
105142
}
106143
}
107144

145+
@available(iOS 17.0, *)
108146
private extension POSIneligibleView {
109147
enum Localization {
148+
static let title = NSLocalizedString(
149+
"pos.ineligible.title",
150+
value: "Unable to load",
151+
comment: "Title shown in POS ineligible view"
152+
)
153+
110154
static let refreshEligibility = NSLocalizedString(
111155
"pos.ineligible.refresh.button.title",
112-
value: "Check Eligibility Again",
156+
value: "Retry",
113157
comment: "Button title to refresh POS eligibility check"
114158
)
115159

116-
/// Default message shown when POS eligibility reason is not available.
117-
static let defaultReason = NSLocalizedString(
118-
"pos.ineligible.default.reason",
119-
value: "Your store is not eligible for POS at this time.",
120-
comment: "Default message shown when POS eligibility reason is not available"
160+
static let dismiss = NSLocalizedString(
161+
"pos.ineligible.dismiss.button.title",
162+
value: "Exit POS",
163+
comment: "Button title to dismiss POS ineligible view"
164+
)
165+
}
166+
}
167+
168+
#if DEBUG
169+
170+
#Preview("Unsupported currency") {
171+
if #available(iOS 17.0, *) {
172+
POSIneligibleView(
173+
reason: .unsupportedCurrency(supportedCurrencies: [.USD]),
174+
onRefresh: {}
175+
)
176+
}
177+
}
178+
179+
#Preview("Unsupported country") {
180+
if #available(iOS 17.0, *) {
181+
POSIneligibleView(
182+
reason: .unsupportedCountry(supportedCountries: [.US, .GB]),
183+
onRefresh: {}
121184
)
122185
}
123186
}
124187

125-
#Preview {
126-
POSIneligibleView(
127-
reason: .unsupportedCurrency,
128-
onRefresh: {}
129-
)
188+
#Preview("Not a tablet") {
189+
if #available(iOS 17.0, *) {
190+
POSIneligibleView(
191+
reason: .notTablet,
192+
onRefresh: {}
193+
)
194+
}
130195
}
196+
197+
#Preview("Unsupported iOS version") {
198+
if #available(iOS 17.0, *) {
199+
POSIneligibleView(
200+
reason: .unsupportedIOSVersion,
201+
onRefresh: {}
202+
)
203+
}
204+
}
205+
206+
#Preview("WooCommerce plugin not found") {
207+
if #available(iOS 17.0, *) {
208+
POSIneligibleView(
209+
reason: .wooCommercePluginNotFound,
210+
onRefresh: {}
211+
)
212+
}
213+
}
214+
215+
#Preview("Feature flag disabled") {
216+
if #available(iOS 17.0, *) {
217+
POSIneligibleView(
218+
reason: .featureFlagDisabled,
219+
onRefresh: {}
220+
)
221+
}
222+
}
223+
224+
#Preview("Feature switch disabled") {
225+
if #available(iOS 17.0, *) {
226+
POSIneligibleView(
227+
reason: .featureSwitchDisabled,
228+
onRefresh: {}
229+
)
230+
}
231+
}
232+
233+
#Preview("Site settings unavailable") {
234+
if #available(iOS 17.0, *) {
235+
POSIneligibleView(
236+
reason: .siteSettingsNotAvailable,
237+
onRefresh: {}
238+
)
239+
}
240+
}
241+
242+
#Preview("Feature switch sync failure") {
243+
if #available(iOS 17.0, *) {
244+
POSIneligibleView(
245+
reason: .featureSwitchSyncFailure,
246+
onRefresh: {}
247+
)
248+
}
249+
}
250+
251+
#Preview("Unsupported WooCommerce version") {
252+
if #available(iOS 17.0, *) {
253+
POSIneligibleView(
254+
reason: .unsupportedWooCommerceVersion(minimumVersion: "9.6.0"),
255+
onRefresh: {}
256+
)
257+
}
258+
}
259+
260+
#endif

0 commit comments

Comments
 (0)