Skip to content

Commit f629e6c

Browse files
authored
Merge pull request #8320 from woocommerce/issue/8243-delta-percentage
[Analytics Hub] Extract DeltaPercentage entity
2 parents 52e2593 + 9e8f0ad commit f629e6c

File tree

6 files changed

+119
-155
lines changed

6 files changed

+119
-155
lines changed

WooCommerce/Classes/ViewRelated/Dashboard/Analytics Hub/AnalyticsHubViewModel.swift

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -198,51 +198,36 @@ private extension AnalyticsHubViewModel {
198198

199199
static func revenueCard(currentPeriodStats: OrderStatsV4?, previousPeriodStats: OrderStatsV4?) -> AnalyticsReportCardViewModel {
200200
let showSyncError = currentPeriodStats == nil || previousPeriodStats == nil
201-
let totalDelta = StatsDataTextFormatter.createTotalRevenueDelta(from: previousPeriodStats, to: currentPeriodStats)
202-
let netDelta = StatsDataTextFormatter.createNetRevenueDelta(from: previousPeriodStats, to: currentPeriodStats)
203201

204202
return AnalyticsReportCardViewModel(title: Localization.RevenueCard.title,
205203
leadingTitle: Localization.RevenueCard.leadingTitle,
206204
leadingValue: StatsDataTextFormatter.createTotalRevenueText(orderStats: currentPeriodStats,
207205
selectedIntervalIndex: nil),
208-
leadingDelta: totalDelta.string,
209-
leadingDeltaColor: totalDelta.direction.deltaBackgroundColor,
210-
leadingDeltaTextColor: totalDelta.direction.deltaTextColor,
206+
leadingDelta: StatsDataTextFormatter.createTotalRevenueDelta(from: previousPeriodStats, to: currentPeriodStats),
211207
leadingChartData: StatsIntervalDataParser.getChartData(for: .totalRevenue, from: currentPeriodStats),
212-
leadingChartColor: totalDelta.direction.chartColor,
213208
trailingTitle: Localization.RevenueCard.trailingTitle,
214209
trailingValue: StatsDataTextFormatter.createNetRevenueText(orderStats: currentPeriodStats),
215-
trailingDelta: netDelta.string,
216-
trailingDeltaColor: netDelta.direction.deltaBackgroundColor,
217-
trailingDeltaTextColor: netDelta.direction.deltaTextColor,
210+
trailingDelta: StatsDataTextFormatter.createNetRevenueDelta(from: previousPeriodStats, to: currentPeriodStats),
218211
trailingChartData: StatsIntervalDataParser.getChartData(for: .netRevenue, from: currentPeriodStats),
219-
trailingChartColor: netDelta.direction.chartColor,
220212
isRedacted: false,
221213
showSyncError: showSyncError,
222214
syncErrorMessage: Localization.RevenueCard.noRevenue)
223215
}
224216

225217
static func ordersCard(currentPeriodStats: OrderStatsV4?, previousPeriodStats: OrderStatsV4?) -> AnalyticsReportCardViewModel {
226218
let showSyncError = currentPeriodStats == nil || previousPeriodStats == nil
227-
let ordersCountDelta = StatsDataTextFormatter.createOrderCountDelta(from: previousPeriodStats, to: currentPeriodStats)
228-
let orderValueDelta = StatsDataTextFormatter.createAverageOrderValueDelta(from: previousPeriodStats, to: currentPeriodStats)
229219

230220
return AnalyticsReportCardViewModel(title: Localization.OrderCard.title,
231221
leadingTitle: Localization.OrderCard.leadingTitle,
232222
leadingValue: StatsDataTextFormatter.createOrderCountText(orderStats: currentPeriodStats,
233223
selectedIntervalIndex: nil),
234-
leadingDelta: ordersCountDelta.string,
235-
leadingDeltaColor: ordersCountDelta.direction.deltaBackgroundColor,
236-
leadingDeltaTextColor: ordersCountDelta.direction.deltaTextColor,
224+
leadingDelta: StatsDataTextFormatter.createOrderCountDelta(from: previousPeriodStats, to: currentPeriodStats),
237225
leadingChartData: StatsIntervalDataParser.getChartData(for: .orderCount, from: currentPeriodStats),
238-
leadingChartColor: ordersCountDelta.direction.chartColor,
239226
trailingTitle: Localization.OrderCard.trailingTitle,
240227
trailingValue: StatsDataTextFormatter.createAverageOrderValueText(orderStats: currentPeriodStats),
241-
trailingDelta: orderValueDelta.string,
242-
trailingDeltaColor: orderValueDelta.direction.deltaBackgroundColor,
243-
trailingDeltaTextColor: orderValueDelta.direction.deltaTextColor,
228+
trailingDelta: StatsDataTextFormatter.createAverageOrderValueDelta(from: previousPeriodStats,
229+
to: currentPeriodStats),
244230
trailingChartData: StatsIntervalDataParser.getChartData(for: .averageOrderValue, from: currentPeriodStats),
245-
trailingChartColor: orderValueDelta.direction.chartColor,
246231
isRedacted: false,
247232
showSyncError: showSyncError,
248233
syncErrorMessage: Localization.OrderCard.noOrders)
@@ -259,9 +244,7 @@ private extension AnalyticsHubViewModel {
259244
let itemsSoldDelta = StatsDataTextFormatter.createOrderItemsSoldDelta(from: previousPeriodStats, to: currentPeriodStats)
260245

261246
return AnalyticsProductCardViewModel(itemsSold: itemsSold,
262-
delta: itemsSoldDelta.string,
263-
deltaBackgroundColor: itemsSoldDelta.direction.deltaBackgroundColor,
264-
deltaTextColor: itemsSoldDelta.direction.deltaTextColor,
247+
delta: itemsSoldDelta,
265248
itemsSoldData: itemSoldRows(from: itemsSoldStats),
266249
isRedacted: false,
267250
showStatsError: showStatsError,

WooCommerce/Classes/ViewRelated/Dashboard/Analytics Hub/AnalyticsProductCardViewModel.swift

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,9 @@ struct AnalyticsProductCardViewModel {
99
///
1010
let itemsSold: String
1111

12-
/// Items Sold Delta
12+
/// Items Sold Delta Percentage
1313
///
14-
let delta: String
15-
16-
/// Delta background color.
17-
///
18-
let deltaBackgroundColor: UIColor
19-
20-
/// Delta text color.
21-
///
22-
let deltaTextColor: UIColor
14+
let delta: DeltaPercentage
2315

2416
/// Items Solds data to render.
2517
///
@@ -45,9 +37,7 @@ extension AnalyticsProductCardViewModel {
4537
var redacted: Self {
4638
// Values here are placeholders and will be redacted in the UI
4739
.init(itemsSold: "1000",
48-
delta: "+50%",
49-
deltaBackgroundColor: .lightGray,
50-
deltaTextColor: .text,
40+
delta: DeltaPercentage(string: "0%", direction: .zero),
5141
itemsSoldData: [.init(imageURL: nil, name: "Product Name", details: "Net Sales", value: "$5678")],
5242
isRedacted: true,
5343
showStatsError: false,
@@ -61,9 +51,9 @@ extension AnalyticsProductCardViewModel {
6151
extension AnalyticsProductCard {
6252
init(viewModel: AnalyticsProductCardViewModel) {
6353
self.itemsSold = viewModel.itemsSold
64-
self.delta = viewModel.delta
65-
self.deltaBackgroundColor = viewModel.deltaBackgroundColor
66-
self.deltaTextColor = viewModel.deltaTextColor
54+
self.delta = viewModel.delta.string
55+
self.deltaBackgroundColor = viewModel.delta.direction.deltaBackgroundColor
56+
self.deltaTextColor = viewModel.delta.direction.deltaTextColor
6757
self.itemsSoldData = viewModel.itemsSoldData
6858
self.isRedacted = viewModel.isRedacted
6959
self.showStatsError = viewModel.showStatsError

WooCommerce/Classes/ViewRelated/Dashboard/Analytics Hub/AnalyticsReportCardViewModel.swift

Lines changed: 14 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,14 @@ struct AnalyticsReportCardViewModel {
1717
///
1818
let leadingValue: String
1919

20-
/// First Column Delta Value
20+
/// First Column Delta Percentage
2121
///
22-
let leadingDelta: String
23-
24-
/// First Column delta background color.
25-
///
26-
let leadingDeltaColor: UIColor
27-
28-
/// First Column delta text color.
29-
///
30-
let leadingDeltaTextColor: UIColor
22+
let leadingDelta: DeltaPercentage
3123

3224
/// First Column Chart Data
3325
///
3426
let leadingChartData: [Double]
3527

36-
/// First Column Chart Color
37-
///
38-
let leadingChartColor: UIColor
39-
4028
/// Second Column Title
4129
///
4230
let trailingTitle: String
@@ -45,26 +33,14 @@ struct AnalyticsReportCardViewModel {
4533
///
4634
let trailingValue: String
4735

48-
/// Second Column Delta Value
36+
/// Second Column Delta Percentage
4937
///
50-
let trailingDelta: String
51-
52-
/// Second Column Delta Background Color
53-
///
54-
let trailingDeltaColor: UIColor
55-
56-
/// Second Column delta text color.
57-
///
58-
let trailingDeltaTextColor: UIColor
38+
let trailingDelta: DeltaPercentage
5939

6040
/// Second Column Chart Data
6141
///
6242
let trailingChartData: [Double]
6343

64-
/// Second Column Chart Color
65-
///
66-
let trailingChartColor: UIColor
67-
6844
/// Indicates if the values should be hidden (for loading state)
6945
///
7046
let isRedacted: Bool
@@ -87,18 +63,12 @@ extension AnalyticsReportCardViewModel {
8763
.init(title: title,
8864
leadingTitle: leadingTitle,
8965
leadingValue: "$1000",
90-
leadingDelta: "+50%",
91-
leadingDeltaColor: .lightGray,
92-
leadingDeltaTextColor: .text,
66+
leadingDelta: DeltaPercentage(string: "0%", direction: .zero),
9367
leadingChartData: [],
94-
leadingChartColor: .lightGray,
9568
trailingTitle: trailingTitle,
9669
trailingValue: "$1000",
97-
trailingDelta: "+50%",
98-
trailingDeltaColor: .lightGray,
99-
trailingDeltaTextColor: .text,
70+
trailingDelta: DeltaPercentage(string: "0%", direction: .zero),
10071
trailingChartData: [],
101-
trailingChartColor: .lightGray,
10272
isRedacted: true,
10373
showSyncError: false,
10474
syncErrorMessage: "")
@@ -112,18 +82,18 @@ extension AnalyticsReportCard {
11282
self.title = viewModel.title
11383
self.leadingTitle = viewModel.leadingTitle
11484
self.leadingValue = viewModel.leadingValue
115-
self.leadingDelta = viewModel.leadingDelta
116-
self.leadingDeltaColor = viewModel.leadingDeltaColor
117-
self.leadingDeltaTextColor = viewModel.leadingDeltaTextColor
85+
self.leadingDelta = viewModel.leadingDelta.string
86+
self.leadingDeltaColor = viewModel.leadingDelta.direction.deltaBackgroundColor
87+
self.leadingDeltaTextColor = viewModel.leadingDelta.direction.deltaTextColor
11888
self.leadingChartData = viewModel.leadingChartData
119-
self.leadingChartColor = viewModel.leadingChartColor
89+
self.leadingChartColor = viewModel.leadingDelta.direction.chartColor
12090
self.trailingTitle = viewModel.trailingTitle
12191
self.trailingValue = viewModel.trailingValue
122-
self.trailingDelta = viewModel.trailingDelta
123-
self.trailingDeltaColor = viewModel.trailingDeltaColor
124-
self.trailingDeltaTextColor = viewModel.trailingDeltaTextColor
92+
self.trailingDelta = viewModel.trailingDelta.string
93+
self.trailingDeltaColor = viewModel.trailingDelta.direction.deltaBackgroundColor
94+
self.trailingDeltaTextColor = viewModel.trailingDelta.direction.deltaTextColor
12595
self.trailingChartData = viewModel.trailingChartData
126-
self.trailingChartColor = viewModel.trailingChartColor
96+
self.trailingChartColor = viewModel.trailingDelta.direction.chartColor
12797
self.isRedacted = viewModel.isRedacted
12898
self.showSyncError = viewModel.showSyncError
12999
self.syncErrorMessage = viewModel.syncErrorMessage
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import Foundation
2+
import class UIKit.UIColor
3+
4+
/// Represents a formatted delta percentage string and its direction of change
5+
struct DeltaPercentage {
6+
/// The delta percentage formatted as a localized string (e.g. `+100%`)
7+
let string: String
8+
9+
/// The direction of change
10+
let direction: Direction
11+
12+
init(string: String, direction: Direction) {
13+
self.string = string
14+
self.direction = direction
15+
}
16+
17+
/// Convenience initializer
18+
/// - Parameters:
19+
/// - value: The percentage expressed as a `Decimal` (e.g. 0.5 for 50%).
20+
/// - formatter: The formatter used to format the value as a string.
21+
init(value: Decimal, formatter: NumberFormatter) {
22+
self.string = formatter.string(from: value as NSNumber) ?? ""
23+
self.direction = {
24+
if value > 0 {
25+
return .positive
26+
} else if value < 0 {
27+
return .negative
28+
} else {
29+
return .zero
30+
}
31+
}()
32+
}
33+
34+
/// Represents the direction of change for a delta value
35+
enum Direction {
36+
case positive
37+
case negative
38+
case zero
39+
40+
/// Background color for a `DeltaTag`
41+
var deltaBackgroundColor: UIColor {
42+
switch self {
43+
case .positive:
44+
return Constants.green
45+
case .negative:
46+
return Constants.red
47+
case .zero:
48+
return Constants.lightGray
49+
}
50+
}
51+
52+
/// Text color for a `DeltaTag`
53+
var deltaTextColor: UIColor {
54+
switch self {
55+
case .positive, .negative:
56+
return .textInverted
57+
case .zero:
58+
return .text
59+
}
60+
}
61+
62+
/// Line color for an `AnalyticsLineChart`
63+
var chartColor: UIColor {
64+
switch self {
65+
case .positive:
66+
return Constants.green
67+
case .negative:
68+
return Constants.red
69+
case .zero:
70+
return Constants.darkGray
71+
}
72+
}
73+
}
74+
}
75+
76+
// MARK: Constants
77+
extension DeltaPercentage {
78+
enum Constants {
79+
static let green: UIColor = .withColorStudio(.green, shade: .shade50)
80+
static let red: UIColor = .withColorStudio(.red, shade: .shade40)
81+
static let lightGray: UIColor = .withColorStudio(.gray, shade: .shade0)
82+
static let darkGray: UIColor = .withColorStudio(.gray, shade: .shade30)
83+
}
84+
}

0 commit comments

Comments
 (0)