Skip to content

Commit 791f111

Browse files
authored
Merge pull request #8401 from woocommerce/issue/8340-decouple-bussiness-ui
Analytics Hub: Decouple ranges
2 parents c45d2e0 + e6d60f1 commit 791f111

File tree

6 files changed

+329
-108
lines changed

6 files changed

+329
-108
lines changed

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

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@ struct AnalyticsTimeRangeCard: View {
3131
createTimeRangeContent()
3232
.sheet(isPresented: $showTimeRangeSelectionView) {
3333
SelectionList(title: Localization.timeRangeSelectionTitle,
34-
items: AnalyticsHubTimeRangeSelection.SelectionType.allCases,
34+
items: Range.allCases,
3535
contentKeyPath: \.description,
3636
selected: internalSelectionBinding()) { selection in
3737
usageTracksEventEmitter.interacted()
3838
ServiceLocator.analytics.track(event: .AnalyticsHub.dateRangeOptionSelected(selection.tracksIdentifier))
3939
}
4040
.sheet(isPresented: $showCustomRangeSelectionView) {
41-
RangedDatePicker() { start, end in
41+
RangedDatePicker(startDate: selectionType.startDate, endDate: selectionType.endDate) { start, end in
4242
showTimeRangeSelectionView = false // Dismiss the initial sheet for a smooth transition
4343
self.selectionType = .custom(start: start, end: end)
4444
}
@@ -96,26 +96,19 @@ struct AnalyticsTimeRangeCard: View {
9696
/// Tracks the range selection internally to determine if the custom range selection should be presented or not.
9797
/// If custom range selection is not needed, the internal selection is forwarded to `selectionType`.
9898
///
99-
private func internalSelectionBinding() -> Binding<AnalyticsHubTimeRangeSelection.SelectionType> {
99+
private func internalSelectionBinding() -> Binding<Range> {
100100
.init(
101101
get: {
102-
// Temporary
103-
switch selectionType {
104-
// If a `custom` case is set return one with nil values so the Custom row is selected
105-
case .custom:
106-
return .custom(start: nil, end: nil)
107-
default:
108-
return selectionType
109-
}
102+
return selectionType.asTimeCardRange
110103
},
111104
set: { newValue in
112105
switch newValue {
113-
// If we get a `custom` case with nil dates it is because we need to present the custom range selection
114-
case .custom(start: nil, end: nil):
106+
// If we get a `custom` case it is because we need to present the custom range selection
107+
case .custom:
115108
showCustomRangeSelectionView = true
116109
default:
117110
// Any other selection should be forwarded to our parent binding.
118-
selectionType = newValue
111+
selectionType = newValue.asAnalyticsHubRange
119112
}
120113
}
121114
)
@@ -154,3 +147,39 @@ struct TimeRangeCard_Previews: PreviewProvider {
154147
AnalyticsTimeRangeCard(viewModel: viewModel, selectionType: .constant(.monthToDate))
155148
}
156149
}
150+
151+
152+
extension AnalyticsTimeRangeCard {
153+
enum Range: CaseIterable {
154+
case custom
155+
case today
156+
case yesterday
157+
case lastWeek
158+
case lastMonth
159+
case lastQuarter
160+
case lastYear
161+
case weekToDate
162+
case monthToDate
163+
case quarterToDate
164+
case yearToDate
165+
166+
/// Wee need to provide a custom `allCases` in order to evict `.custom` while the feature flag is active.
167+
/// We should delete this once the feature flag has been removed.
168+
///
169+
static var allCases: [Range] {
170+
[
171+
ServiceLocator.featureFlagService.isFeatureFlagEnabled(.analyticsHub) ? .custom : nil,
172+
.today,
173+
.yesterday,
174+
.lastWeek,
175+
.lastMonth,
176+
.lastQuarter,
177+
.lastYear,
178+
.weekToDate,
179+
.monthToDate,
180+
.quarterToDate,
181+
yearToDate
182+
].compactMap { $0 }
183+
}
184+
}
185+
}
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
import Foundation
2+
3+
/// Type that help us converting and querying common data from the ranges supported for the Analytics Hub.
4+
/// Currently we have two range enum types, One for the list UI and one for the supported ranges in the business layer.
5+
/// This adapter help us sharing some common meta data between those two ranges.
6+
///
7+
struct AnalyticsHubRangeAdapter {
8+
9+
/// Converts an `AnalyticsHubTimeRangeSelection.SelectionType` range into a `AnalyticsTimeRangeCard.Range`.
10+
///
11+
static func timeCardRange(from analyticsHubRange: AnalyticsHubTimeRangeSelection.SelectionType) -> AnalyticsTimeRangeCard.Range {
12+
switch analyticsHubRange {
13+
case .custom:
14+
return .custom
15+
case .today:
16+
return .today
17+
case .yesterday:
18+
return .yesterday
19+
case .lastWeek:
20+
return .lastWeek
21+
case .lastMonth:
22+
return .lastMonth
23+
case .lastQuarter:
24+
return .lastQuarter
25+
case .lastYear:
26+
return .lastYear
27+
case .weekToDate:
28+
return .weekToDate
29+
case .monthToDate:
30+
return .monthToDate
31+
case .quarterToDate:
32+
return .quarterToDate
33+
case .yearToDate:
34+
return .yearToDate
35+
}
36+
}
37+
38+
/// Converts an `AnalyticsTimeRangeCard.Range` into a `AnalyticsHubTimeRangeSelection.SelectionType` range.
39+
///
40+
static func analyticsHubRange(from timeCardRange: AnalyticsTimeRangeCard.Range) -> AnalyticsHubTimeRangeSelection.SelectionType {
41+
switch timeCardRange {
42+
case .custom:
43+
return .custom(start: Date(), end: Date())
44+
case .today:
45+
return .today
46+
case .yesterday:
47+
return .yesterday
48+
case .lastWeek:
49+
return .lastWeek
50+
case .lastMonth:
51+
return .lastMonth
52+
case .lastQuarter:
53+
return .lastQuarter
54+
case .lastYear:
55+
return .lastYear
56+
case .weekToDate:
57+
return .weekToDate
58+
case .monthToDate:
59+
return .monthToDate
60+
case .quarterToDate:
61+
return .quarterToDate
62+
case .yearToDate:
63+
return .yearToDate
64+
}
65+
}
66+
67+
/// Returns the desciption of the provided `AnalyticsHubTimeRangeSelection.SelectionType`range.
68+
///
69+
static func description(from analyticsHubRange: AnalyticsHubTimeRangeSelection.SelectionType) -> String {
70+
switch analyticsHubRange {
71+
case .custom:
72+
return Localization.custom
73+
case .today:
74+
return Localization.today
75+
case .yesterday:
76+
return Localization.yesterday
77+
case .lastWeek:
78+
return Localization.lastWeek
79+
case .lastMonth:
80+
return Localization.lastMonth
81+
case .lastQuarter:
82+
return Localization.lastQuarter
83+
case .lastYear:
84+
return Localization.lastYear
85+
case .weekToDate:
86+
return Localization.weekToDate
87+
case .monthToDate:
88+
return Localization.monthToDate
89+
case .quarterToDate:
90+
return Localization.quarterToDate
91+
case .yearToDate:
92+
return Localization.yearToDate
93+
}
94+
}
95+
96+
/// Returns the desciption of the provided `AnalyticsTimeRangeCard.Range`.
97+
///
98+
static func description(from timeCardRange: AnalyticsTimeRangeCard.Range) -> String {
99+
switch timeCardRange {
100+
case .custom:
101+
return Localization.custom
102+
case .today:
103+
return Localization.today
104+
case .yesterday:
105+
return Localization.yesterday
106+
case .lastWeek:
107+
return Localization.lastWeek
108+
case .lastMonth:
109+
return Localization.lastMonth
110+
case .lastQuarter:
111+
return Localization.lastQuarter
112+
case .lastYear:
113+
return Localization.lastYear
114+
case .weekToDate:
115+
return Localization.weekToDate
116+
case .monthToDate:
117+
return Localization.monthToDate
118+
case .quarterToDate:
119+
return Localization.quarterToDate
120+
case .yearToDate:
121+
return Localization.yearToDate
122+
}
123+
}
124+
125+
/// Returns the tracks identifier of the provided `AnalyticsHubTimeRangeSelection.SelectionType`.
126+
///
127+
static func tracksIdentifier(from analyticsHubRange: AnalyticsHubTimeRangeSelection.SelectionType) -> String {
128+
switch analyticsHubRange {
129+
case .custom:
130+
return TracksIdentifier.custom
131+
case .today:
132+
return TracksIdentifier.today
133+
case .yesterday:
134+
return TracksIdentifier.yesterday
135+
case .lastWeek:
136+
return TracksIdentifier.lastWeek
137+
case .lastMonth:
138+
return TracksIdentifier.lastMonth
139+
case .lastQuarter:
140+
return TracksIdentifier.lastQuarter
141+
case .lastYear:
142+
return TracksIdentifier.lastYear
143+
case .weekToDate:
144+
return TracksIdentifier.weekToDate
145+
case .monthToDate:
146+
return TracksIdentifier.monthToDate
147+
case .quarterToDate:
148+
return TracksIdentifier.quarterToDate
149+
case .yearToDate:
150+
return TracksIdentifier.yearToDate
151+
}
152+
}
153+
154+
/// Returns the tracks identifier of the provided `AnalyticsTimeRangeCard.Range`.
155+
///
156+
static func tracksIdentifier(from timeCardRange: AnalyticsTimeRangeCard.Range) -> String {
157+
switch timeCardRange {
158+
case .custom:
159+
return TracksIdentifier.custom
160+
case .today:
161+
return TracksIdentifier.today
162+
case .yesterday:
163+
return TracksIdentifier.yesterday
164+
case .lastWeek:
165+
return TracksIdentifier.lastWeek
166+
case .lastMonth:
167+
return TracksIdentifier.lastMonth
168+
case .lastQuarter:
169+
return TracksIdentifier.lastQuarter
170+
case .lastYear:
171+
return TracksIdentifier.lastYear
172+
case .weekToDate:
173+
return TracksIdentifier.weekToDate
174+
case .monthToDate:
175+
return TracksIdentifier.monthToDate
176+
case .quarterToDate:
177+
return TracksIdentifier.quarterToDate
178+
case .yearToDate:
179+
return TracksIdentifier.yearToDate
180+
}
181+
}
182+
183+
/// Extracts the dates from an analytics hub range custom type.
184+
///
185+
static func customDates(from analyticsHubRange: AnalyticsHubTimeRangeSelection.SelectionType) -> (start: Date, end: Date)? {
186+
switch analyticsHubRange {
187+
case let .custom(startDate, endDate):
188+
return (startDate, endDate)
189+
default:
190+
return nil
191+
}
192+
}
193+
}
194+
195+
// MARK: Constants
196+
197+
private extension AnalyticsHubRangeAdapter {
198+
enum TracksIdentifier {
199+
static let custom = "Custom"
200+
static let today = "Today"
201+
static let yesterday = "Yesterday"
202+
static let lastWeek = "Last Week"
203+
static let lastMonth = "Last Month"
204+
static let lastQuarter = "Last Quarter"
205+
static let lastYear = "Last Year"
206+
static let weekToDate = "Week to Date"
207+
static let monthToDate = "Month to Date"
208+
static let quarterToDate = "Quarter to Date"
209+
static let yearToDate = "Year to Date"
210+
}
211+
212+
enum Localization {
213+
static let custom = NSLocalizedString("Custom", comment: "Title of the Analytics Hub Custom selection range")
214+
static let today = NSLocalizedString("Today", comment: "Title of the Analytics Hub Today's selection range")
215+
static let yesterday = NSLocalizedString("Yesterday", comment: "Title of the Analytics Hub Yesterday selection range")
216+
static let lastWeek = NSLocalizedString("Last Week", comment: "Title of the Analytics Hub Last Week selection range")
217+
static let lastMonth = NSLocalizedString("Last Month", comment: "Title of the Analytics Hub Last Month selection range")
218+
static let lastQuarter = NSLocalizedString("Last Quarter", comment: "Title of the Analytics Hub Last Quarter selection range")
219+
static let lastYear = NSLocalizedString("Last Year", comment: "Title of the Analytics Hub Last Year selection range")
220+
static let weekToDate = NSLocalizedString("Week to Date", comment: "Title of the Analytics Hub Week to Date selection range")
221+
static let monthToDate = NSLocalizedString("Month to Date", comment: "Title of the Analytics Hub Month to Date selection range")
222+
static let quarterToDate = NSLocalizedString("Quarter to Date", comment: "Title of the Analytics Hub Quarter to Date selection range")
223+
static let yearToDate = NSLocalizedString("Year to Date", comment: "Title of the Analytics Hub Year to Date selection range")
224+
}
225+
}
226+
227+
// MARK: Convenience Extensitons
228+
extension AnalyticsTimeRangeCard.Range {
229+
230+
var description: String {
231+
AnalyticsHubRangeAdapter.description(from: self)
232+
}
233+
234+
var tracksIdentifier: String {
235+
AnalyticsHubRangeAdapter.tracksIdentifier(from: self)
236+
}
237+
238+
var asAnalyticsHubRange: AnalyticsHubTimeRangeSelection.SelectionType {
239+
AnalyticsHubRangeAdapter.analyticsHubRange(from: self)
240+
}
241+
}
242+
243+
extension AnalyticsHubTimeRangeSelection.SelectionType {
244+
var description: String {
245+
AnalyticsHubRangeAdapter.description(from: self)
246+
}
247+
248+
var tracksIdentifier: String {
249+
AnalyticsHubRangeAdapter.tracksIdentifier(from: self)
250+
}
251+
252+
var asTimeCardRange: AnalyticsTimeRangeCard.Range {
253+
AnalyticsHubRangeAdapter.timeCardRange(from: self)
254+
}
255+
256+
/// Extracts the start date from custom range type.
257+
///
258+
var startDate: Date? {
259+
AnalyticsHubRangeAdapter.customDates(from: self)?.start
260+
}
261+
262+
/// Extracts the end date from custom range type.
263+
///
264+
var endDate: Date? {
265+
AnalyticsHubRangeAdapter.customDates(from: self)?.end
266+
}
267+
}

0 commit comments

Comments
 (0)