Skip to content

Commit 58de948

Browse files
committed
Unify logic for createStockText
1 parent 8fefa69 commit 58de948

File tree

6 files changed

+93
-98
lines changed

6 files changed

+93
-98
lines changed

WooCommerce/Classes/ViewRelated/Products/ProductSelector/ProductRowViewModel.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ final class ProductRowViewModel: ObservableObject, Identifiable {
178178
case .attributes(let attributes):
179179
return createAttributesText(from: attributes)
180180
default:
181+
// TODO: use `String.createStockText(...)` to display bundle products if necessary
181182
return createStockText()
182183
}
183184
}

WooCommerce/Classes/ViewRelated/Products/Variations/ProductsTabProductViewModel+ProductVariation.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ private extension EditableProductVariationModel {
3232
}
3333

3434
func createStockStatusAttributedString() -> NSAttributedString {
35-
let stockText = createStockText()
35+
let stockText = String.createStockText(productType: productType,
36+
manageStock: manageStock,
37+
stockStatus: stockStatus,
38+
stockQuantity: stockQuantity,
39+
bundleStockStatus: bundleStockStatus,
40+
bundleStockQuantity: bundleStockQuantity)
3641
return NSAttributedString(string: stockText,
3742
attributes: [
3843
.foregroundColor: UIColor.textSubtle,

WooCommerce/Classes/ViewRelated/Products/View Models/ProductFormDataModel+ProductsTabProductViewModel.swift

Lines changed: 0 additions & 48 deletions
This file was deleted.

WooCommerce/Classes/ViewRelated/Products/View Models/ProductsTabProductViewModel.swift

Lines changed: 6 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,12 @@ struct ProductsTabProductViewModel {
6666
private extension ProductListItem {
6767
func createDetailsAttributedString(isSKUShown: Bool) -> NSAttributedString {
6868
let statusText = createStatusText()
69-
let stockText = createStockText()
69+
let stockText = String.createStockText(productType: productType,
70+
manageStock: manageStock,
71+
stockStatus: productStockStatus,
72+
stockQuantity: stockQuantity,
73+
bundleStockStatus: bundleStockStatus,
74+
bundleStockQuantity: bundleStockQuantity)
7075
let variationsText = createVariationsText()
7176

7277
let detailsText = [statusText, stockText, variationsText]
@@ -113,50 +118,6 @@ private extension ProductListItem {
113118
}
114119
return String.localizedStringWithFormat(EditableProductModel.Localization.skuFormat, sku)
115120
}
116-
117-
/// Create a description text based on a product data model's stock status/quantity.
118-
func createStockText() -> String {
119-
if productType == .bundle {
120-
return createProductBundleStockText()
121-
}
122-
123-
switch productStockStatus {
124-
case .inStock:
125-
if let stockQuantity = stockQuantity, manageStock {
126-
let localizedStockQuantity = NumberFormatter.localizedString(from: stockQuantity as NSDecimalNumber, number: .decimal)
127-
let format = NSLocalizedString("%1$@ in stock", comment: "Label about product's inventory stock status shown on Products tab")
128-
return String.localizedStringWithFormat(format, localizedStockQuantity)
129-
} else {
130-
return NSLocalizedString("In stock", comment: "Label about product's inventory stock status shown on Products tab")
131-
}
132-
default:
133-
return productStockStatus.description
134-
}
135-
}
136-
137-
/// Create a description text based on a product bundle data model's stock status/quantity and bundle stock status/quantity.
138-
private func createProductBundleStockText() -> String {
139-
// Use bundle stock status if it is insufficent stock
140-
if let bundleStockStatus, bundleStockStatus == .insufficientStock {
141-
return bundleStockStatus.description
142-
}
143-
144-
switch productStockStatus {
145-
case .inStock:
146-
let quantityFormat = NSLocalizedString("%1$@ in stock", comment: "Label about product's inventory stock status shown on Products tab")
147-
if let bundleStockQuantity { // Use bundle stock quantity, if set
148-
let localizedStockQuantity = NumberFormatter.localizedString(from: NSDecimalNumber(value: bundleStockQuantity), number: .decimal)
149-
return String.localizedStringWithFormat(quantityFormat, localizedStockQuantity)
150-
} else if let stockQuantity, manageStock { // Otherwise, use product stock quantity if set and product manages stock
151-
let localizedStockQuantity = NumberFormatter.localizedString(from: stockQuantity as NSDecimalNumber, number: .decimal)
152-
return String.localizedStringWithFormat(quantityFormat, localizedStockQuantity)
153-
} else {
154-
return NSLocalizedString("In stock", comment: "Label about product's inventory stock status shown on Products tab")
155-
}
156-
default:
157-
return productStockStatus.description
158-
}
159-
}
160121
}
161122

162123
// MARK: Localization
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import Foundation
2+
import UIKit
3+
import Yosemite
4+
5+
extension String {
6+
/// Create a description text based on a product data model's stock status/quantity.
7+
static func createStockText(productType: ProductType,
8+
manageStock: Bool,
9+
stockStatus: ProductStockStatus,
10+
stockQuantity: Decimal?,
11+
bundleStockStatus: ProductStockStatus?,
12+
bundleStockQuantity: Int64?,) -> String {
13+
if productType == .bundle {
14+
return createProductBundleStockText(manageStock: manageStock,
15+
productStockStatus: stockStatus,
16+
stockQuantity: stockQuantity,
17+
bundleStockStatus: bundleStockStatus,
18+
bundleStockQuantity: bundleStockQuantity)
19+
}
20+
21+
switch stockStatus {
22+
case .inStock:
23+
if let stockQuantity = stockQuantity, manageStock {
24+
let localizedStockQuantity = NumberFormatter.localizedString(from: stockQuantity as NSDecimalNumber, number: .decimal)
25+
return String.localizedStringWithFormat(Localization.stockQuantity, localizedStockQuantity)
26+
} else {
27+
return Localization.inStock
28+
}
29+
default:
30+
return stockStatus.description
31+
}
32+
}
33+
34+
/// Create a description text based on a product bundle data model's stock status/quantity and bundle stock status/quantity.
35+
private static func createProductBundleStockText(manageStock: Bool,
36+
productStockStatus: ProductStockStatus,
37+
stockQuantity: Decimal?,
38+
bundleStockStatus: ProductStockStatus?,
39+
bundleStockQuantity: Int64?) -> String {
40+
// Use bundle stock status if it is insufficent stock
41+
if let bundleStockStatus, bundleStockStatus == .insufficientStock {
42+
return bundleStockStatus.description
43+
}
44+
45+
switch productStockStatus {
46+
case .inStock:
47+
let quantityFormat = Localization.stockQuantity
48+
if let bundleStockQuantity { // Use bundle stock quantity, if set
49+
let localizedStockQuantity = NumberFormatter.localizedString(from: NSDecimalNumber(value: bundleStockQuantity), number: .decimal)
50+
return String.localizedStringWithFormat(quantityFormat, localizedStockQuantity)
51+
} else if let stockQuantity, manageStock { // Otherwise, use product stock quantity if set and product manages stock
52+
let localizedStockQuantity = NumberFormatter.localizedString(from: stockQuantity as NSDecimalNumber, number: .decimal)
53+
return String.localizedStringWithFormat(quantityFormat, localizedStockQuantity)
54+
} else {
55+
return Localization.inStock
56+
}
57+
default:
58+
return productStockStatus.description
59+
}
60+
}
61+
}
62+
63+
private enum Localization {
64+
static let inStock = NSLocalizedString(
65+
"string.createStockText.inStock",
66+
value: "In stock",
67+
comment: "Label about product's inventory stock status shown on Products tab"
68+
)
69+
70+
static let stockQuantity = NSLocalizedString(
71+
"string.createStockText.count",
72+
value: "%1$@ in stock",
73+
comment: "Label about product's inventory stock status shown on Products tab " +
74+
"Placeholder is the stock quantity. Reads as: '20 in stock'."
75+
)
76+
}

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,6 @@
323323
025C00BA25514A7100FAC222 /* BarcodeScannerFrameScaler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025C00B925514A7100FAC222 /* BarcodeScannerFrameScaler.swift */; };
324324
025C00CC2551524300FAC222 /* BarcodeScannerFrameScalerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025C00CB2551524300FAC222 /* BarcodeScannerFrameScalerTests.swift */; };
325325
025CA1A62887D17A00CCBB25 /* LoggedOutAppSettingsProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025CA1A52887D17A00CCBB25 /* LoggedOutAppSettingsProtocol.swift */; };
326-
025E32BC251D8FEF00685C4A /* ProductFormDataModel+ProductsTabProductViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025E32BB251D8FEF00685C4A /* ProductFormDataModel+ProductsTabProductViewModel.swift */; };
327326
025FA38B2522CB4D0054CA57 /* AppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025FA38A2522CB4D0054CA57 /* AppCoordinator.swift */; };
328327
025FDD3223717D2900824006 /* EditorFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025FDD3123717D2900824006 /* EditorFactory.swift */; };
329328
025FDD3423717D4900824006 /* AztecEditorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025FDD3323717D4900824006 /* AztecEditorViewController.swift */; };
@@ -2748,6 +2747,7 @@
27482747
DE96844D2A332CC2000FBF4E /* ShareProductCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE96844C2A332CC2000FBF4E /* ShareProductCoordinatorTests.swift */; };
27492748
DE971219290A9615000C0BD3 /* AddStoreFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE971218290A9615000C0BD3 /* AddStoreFooterView.swift */; };
27502749
DE972D422E3C7238008C2EAE /* Product+ListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE972D412E3C7231008C2EAE /* Product+ListItem.swift */; };
2750+
DE9734B42E3CA163008C2EAE /* String+ProductStock.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9734B32E3CA155008C2EAE /* String+ProductStock.swift */; };
27512751
DE9A02A32A44441200193ABF /* RequirementsCheckerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9A02A22A44441200193ABF /* RequirementsCheckerTests.swift */; };
27522752
DE9F2D292A1B1AB2004E5957 /* FirstProductCreatedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9F2D282A1B1AB2004E5957 /* FirstProductCreatedView.swift */; };
27532753
DEA0D0682BA82EA2007786F2 /* StatsGranularityV4+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEA0D0672BA82EA2007786F2 /* StatsGranularityV4+UI.swift */; };
@@ -3502,7 +3502,6 @@
35023502
025C00B925514A7100FAC222 /* BarcodeScannerFrameScaler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarcodeScannerFrameScaler.swift; sourceTree = "<group>"; };
35033503
025C00CB2551524300FAC222 /* BarcodeScannerFrameScalerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarcodeScannerFrameScalerTests.swift; sourceTree = "<group>"; };
35043504
025CA1A52887D17A00CCBB25 /* LoggedOutAppSettingsProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedOutAppSettingsProtocol.swift; sourceTree = "<group>"; };
3505-
025E32BB251D8FEF00685C4A /* ProductFormDataModel+ProductsTabProductViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProductFormDataModel+ProductsTabProductViewModel.swift"; sourceTree = "<group>"; };
35063505
025FA38A2522CB4D0054CA57 /* AppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinator.swift; sourceTree = "<group>"; };
35073506
025FDD3123717D2900824006 /* EditorFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorFactory.swift; sourceTree = "<group>"; };
35083507
025FDD3323717D4900824006 /* AztecEditorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AztecEditorViewController.swift; sourceTree = "<group>"; };
@@ -5938,6 +5937,7 @@
59385937
DE96844C2A332CC2000FBF4E /* ShareProductCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareProductCoordinatorTests.swift; sourceTree = "<group>"; };
59395938
DE971218290A9615000C0BD3 /* AddStoreFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddStoreFooterView.swift; sourceTree = "<group>"; };
59405939
DE972D412E3C7231008C2EAE /* Product+ListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Product+ListItem.swift"; sourceTree = "<group>"; };
5940+
DE9734B32E3CA155008C2EAE /* String+ProductStock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+ProductStock.swift"; sourceTree = "<group>"; };
59415941
DE9A02A22A44441200193ABF /* RequirementsCheckerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequirementsCheckerTests.swift; sourceTree = "<group>"; };
59425942
DE9F2D282A1B1AB2004E5957 /* FirstProductCreatedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstProductCreatedView.swift; sourceTree = "<group>"; };
59435943
DEA0D0672BA82EA2007786F2 /* StatsGranularityV4+UI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatsGranularityV4+UI.swift"; sourceTree = "<group>"; };
@@ -6606,7 +6606,7 @@
66066606
isa = PBXGroup;
66076607
children = (
66086608
020DD48C2322A617005822B1 /* ProductsTabProductViewModel.swift */,
6609-
025E32BB251D8FEF00685C4A /* ProductFormDataModel+ProductsTabProductViewModel.swift */,
6609+
DE9734B32E3CA155008C2EAE /* String+ProductStock.swift */,
66106610
);
66116611
path = "View Models";
66126612
sourceTree = "<group>";
@@ -16111,7 +16111,6 @@
1611116111
022266BC2AE7707000614F34 /* ConfigurableBundleItemViewModel.swift in Sources */,
1611216112
D449C52926DFBCCC00D75B02 /* WhatsNewHostingController.swift in Sources */,
1611316113
B626C71B287659D60083820C /* CustomFieldsListView.swift in Sources */,
16114-
025E32BC251D8FEF00685C4A /* ProductFormDataModel+ProductsTabProductViewModel.swift in Sources */,
1611516114
02ECD1E624FFB4E900735BE5 /* ProductFactory.swift in Sources */,
1611616115
260520F42B87BA23005D5D59 /* WooAnalyticsEvent+ConnectivityTool.swift in Sources */,
1611716116
579CDEFF274D7E7900E8903D /* StoreStatsUsageTracksEventEmitter.swift in Sources */,
@@ -16265,6 +16264,7 @@
1626516264
DE3650662B512889001569A7 /* BlazeTargetLocationPickerView.swift in Sources */,
1626616265
020DD48A23229495005822B1 /* ProductsTabProductTableViewCell.swift in Sources */,
1626716266
CCA0EF8829CCA89300A44E6F /* CompositeComponentOptionType+UI.swift in Sources */,
16267+
DE9734B42E3CA163008C2EAE /* String+ProductStock.swift in Sources */,
1626816268
26E7EE7429365F0700793045 /* TopPerformersView.swift in Sources */,
1626916269
CE32B11520BF8779006FBCF4 /* ButtonTableViewCell.swift in Sources */,
1627016270
DE74A45B2BD9048E0009C415 /* DashboardCardErrorView.swift in Sources */,

0 commit comments

Comments
 (0)