@@ -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 , * )
56struct 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 , * )
108146private 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