Skip to content

Commit 02384e2

Browse files
authored
Merge pull request #8185 from woocommerce/issue/8148-view-model
Analytics Hub: Add Main View Model
2 parents d9be157 + 956253d commit 02384e2

File tree

5 files changed

+112
-27
lines changed

5 files changed

+112
-27
lines changed

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

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import SwiftUI
66
///
77
final class AnalyticsHubHostingViewController: UIHostingController<AnalyticsHubView> {
88
init(timeRange: StatsTimeRangeV4) {
9-
super.init(rootView: AnalyticsHubView())
9+
let viewModel = AnalyticsHubViewModel()
10+
super.init(rootView: AnalyticsHubView(viewModel: viewModel))
1011
}
1112

1213
@available(*, unavailable)
@@ -19,10 +20,12 @@ final class AnalyticsHubHostingViewController: UIHostingController<AnalyticsHubV
1920
///
2021
struct AnalyticsHubView: View {
2122

23+
@StateObject var viewModel: AnalyticsHubViewModel
24+
2225
var body: some View {
2326
ScrollView {
2427
VStack(alignment: .leading, spacing: Layout.vertialSpacing) {
25-
VStack(spacing: 0) {
28+
VStack(spacing: Layout.dividerSpacing) {
2629
Divider()
2730
Text("Placeholder for Time Range Selection")
2831
.padding(.leading)
@@ -33,35 +36,19 @@ struct AnalyticsHubView: View {
3336
}
3437

3538

36-
VStack(spacing: 0) {
39+
VStack(spacing: Layout.dividerSpacing) {
3740
Divider()
3841

39-
AnalyticsReportCard(title: "REVENUE",
40-
leadingTitle: "Total Sales",
41-
leadingValue: "$3.234",
42-
leadingDelta: "+23%",
43-
leadingDeltaColor: .withColorStudio(.green, shade: .shade50),
44-
trailingTitle: "Net Sales",
45-
trailingValue: "$2.324",
46-
trailingDelta: "-4%",
47-
trailingDeltaColor: .withColorStudio(.red, shade: .shade40))
42+
AnalyticsReportCard(viewModel: viewModel.revenueCard)
4843
.background(Color(uiColor: .listForeground))
4944

5045
Divider()
5146
}
5247

53-
VStack(spacing: 0) {
48+
VStack(spacing: Layout.dividerSpacing) {
5449
Divider()
5550

56-
AnalyticsReportCard(title: "ORDERS",
57-
leadingTitle: "Total Orders",
58-
leadingValue: "145",
59-
leadingDelta: "+36%",
60-
leadingDeltaColor: .withColorStudio(.green, shade: .shade50),
61-
trailingTitle: "Average Order Value",
62-
trailingValue: "$57,99",
63-
trailingDelta: "-16%",
64-
trailingDeltaColor: .withColorStudio(.red, shade: .shade40))
51+
AnalyticsReportCard(viewModel: viewModel.ordersCard)
6552
.background(Color(uiColor: .listForeground))
6653

6754
Divider()
@@ -85,6 +72,7 @@ private extension AnalyticsHubView {
8572

8673
struct Layout {
8774
static let vertialSpacing: CGFloat = 24.0
75+
static let dividerSpacing: CGFloat = .zero
8876
}
8977
}
9078

@@ -93,7 +81,7 @@ private extension AnalyticsHubView {
9381
struct AnalyticsHubPreview: PreviewProvider {
9482
static var previews: some View {
9583
NavigationView {
96-
AnalyticsHubView()
84+
AnalyticsHubView(viewModel: AnalyticsHubViewModel())
9785
}
9886
}
9987
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import Foundation
2+
3+
/// Main View Model for the Analytics Hub.
4+
///
5+
final class AnalyticsHubViewModel: ObservableObject {
6+
7+
/// Revenue Card ViewModel
8+
///
9+
@Published var revenueCard = AnalyticsReportCardViewModel(title: "REVENUE",
10+
leadingTitle: "Total Sales",
11+
leadingValue: "$3.234",
12+
leadingDelta: "+23%",
13+
leadingDeltaColor: .withColorStudio(.green, shade: .shade50),
14+
trailingTitle: "Net Sales",
15+
trailingValue: "$2.324",
16+
trailingDelta: "-4%",
17+
trailingDeltaColor: .withColorStudio(.red, shade: .shade40))
18+
19+
/// Orders Card ViewModel
20+
///
21+
@Published var ordersCard = AnalyticsReportCardViewModel(title: "ORDERS",
22+
leadingTitle: "Total Orders",
23+
leadingValue: "145",
24+
leadingDelta: "+36%",
25+
leadingDeltaColor: .withColorStudio(.green, shade: .shade50),
26+
trailingTitle: "Average Order Value",
27+
trailingValue: "$57,99",
28+
trailingDelta: "-16%",
29+
trailingDeltaColor: .withColorStudio(.red, shade: .shade40))
30+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import Foundation
2+
import class UIKit.UIColor
3+
4+
/// Analytics Hub Report Card ViewModel.
5+
/// Used to transmit analytics report data.
6+
///
7+
struct AnalyticsReportCardViewModel {
8+
/// Report Card Title.
9+
///
10+
let title: String
11+
12+
/// First Column Title
13+
///
14+
let leadingTitle: String
15+
16+
/// First Column Value
17+
///
18+
let leadingValue: String
19+
20+
/// First Column Delta Value
21+
///
22+
let leadingDelta: String
23+
24+
/// First Column delta background color.
25+
///
26+
let leadingDeltaColor: UIColor
27+
28+
/// Second Column Titlke
29+
///
30+
let trailingTitle: String
31+
32+
/// Second Column Value
33+
///
34+
let trailingValue: String
35+
36+
/// Second Column Delta Value
37+
///
38+
let trailingDelta: String
39+
40+
/// Second Column Delta Background Color
41+
///
42+
let trailingDeltaColor: UIColor
43+
}
44+
45+
/// Convenience extension to create an `AnalyticsReportCard` from a view model.
46+
///
47+
extension AnalyticsReportCard {
48+
init(viewModel: AnalyticsReportCardViewModel) {
49+
self.title = viewModel.title
50+
self.leadingTitle = viewModel.leadingTitle
51+
self.leadingValue = viewModel.leadingValue
52+
self.leadingDelta = viewModel.leadingDelta
53+
self.leadingDeltaColor = viewModel.leadingDeltaColor
54+
self.trailingTitle = viewModel.trailingTitle
55+
self.trailingValue = viewModel.trailingValue
56+
self.trailingDelta = viewModel.trailingDelta
57+
self.trailingDeltaColor = viewModel.trailingDeltaColor
58+
}
59+
}

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@
559559
263E38472641FF3400260D3B /* Codegen in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 263E38452641FF3400260D3B /* Codegen */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
560560
263EB409242C58EA00F3A15F /* ProductFormActionsFactoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 263EB408242C58EA00F3A15F /* ProductFormActionsFactoryTests.swift */; };
561561
2647F7B529280A7F00D59FDF /* AnalyticsHubView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2647F7B429280A7F00D59FDF /* AnalyticsHubView.swift */; };
562-
2647F7BA292BE2F900D59FDF /* StatsCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2647F7B9292BE2F900D59FDF /* StatsCard.swift */; };
562+
2647F7BA292BE2F900D59FDF /* AnalyticsReportCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2647F7B9292BE2F900D59FDF /* AnalyticsReportCard.swift */; };
563563
265284022624937600F91BA1 /* AddOnCrossreferenceUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 265284012624937600F91BA1 /* AddOnCrossreferenceUseCase.swift */; };
564564
265284092624ACE900F91BA1 /* AddOnCrossreferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 265284082624ACE900F91BA1 /* AddOnCrossreferenceTests.swift */; };
565565
2655905B27863D1300BB8457 /* MockCollectOrderPaymentUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2655905A27863D1300BB8457 /* MockCollectOrderPaymentUseCase.swift */; };
@@ -642,6 +642,8 @@
642642
26E1BECA251BE5390096D0A1 /* RefundItemTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E1BEC9251BE5390096D0A1 /* RefundItemTableViewCell.swift */; };
643643
26E1BECC251BE5570096D0A1 /* RefundItemTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 26E1BECB251BE5570096D0A1 /* RefundItemTableViewCell.xib */; };
644644
26E1BECE251CD9F80096D0A1 /* RefundItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E1BECD251CD9F80096D0A1 /* RefundItemViewModel.swift */; };
645+
26E7EE6A292D688900793045 /* AnalyticsHubViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E7EE69292D688900793045 /* AnalyticsHubViewModel.swift */; };
646+
26E7EE6C292D894100793045 /* AnalyticsReportCardViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E7EE6B292D894100793045 /* AnalyticsReportCardViewModel.swift */; };
645647
26ED9660274328BC00FA00A1 /* SimplePaymentsSummaryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26ED965F274328BC00FA00A1 /* SimplePaymentsSummaryViewModel.swift */; };
646648
26F65C9825DEDAF0008FAE29 /* GenerateVariationUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26F65C9725DEDAF0008FAE29 /* GenerateVariationUseCase.swift */; };
647649
26F65C9E25DEDE67008FAE29 /* GenerateVariationUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26F65C9D25DEDE67008FAE29 /* GenerateVariationUseCaseTests.swift */; };
@@ -2525,7 +2527,7 @@
25252527
26309F16277D0AEA0012797F /* SafeAreaInsetsKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafeAreaInsetsKey.swift; sourceTree = "<group>"; };
25262528
263EB408242C58EA00F3A15F /* ProductFormActionsFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductFormActionsFactoryTests.swift; sourceTree = "<group>"; };
25272529
2647F7B429280A7F00D59FDF /* AnalyticsHubView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsHubView.swift; sourceTree = "<group>"; };
2528-
2647F7B9292BE2F900D59FDF /* StatsCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsCard.swift; sourceTree = "<group>"; };
2530+
2647F7B9292BE2F900D59FDF /* AnalyticsReportCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsReportCard.swift; sourceTree = "<group>"; };
25292531
265284012624937600F91BA1 /* AddOnCrossreferenceUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddOnCrossreferenceUseCase.swift; sourceTree = "<group>"; };
25302532
265284082624ACE900F91BA1 /* AddOnCrossreferenceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddOnCrossreferenceTests.swift; sourceTree = "<group>"; };
25312533
2655905A27863D1300BB8457 /* MockCollectOrderPaymentUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCollectOrderPaymentUseCase.swift; sourceTree = "<group>"; };
@@ -2606,6 +2608,8 @@
26062608
26E1BEC9251BE5390096D0A1 /* RefundItemTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefundItemTableViewCell.swift; sourceTree = "<group>"; };
26072609
26E1BECB251BE5570096D0A1 /* RefundItemTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RefundItemTableViewCell.xib; sourceTree = "<group>"; };
26082610
26E1BECD251CD9F80096D0A1 /* RefundItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefundItemViewModel.swift; sourceTree = "<group>"; };
2611+
26E7EE69292D688900793045 /* AnalyticsHubViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsHubViewModel.swift; sourceTree = "<group>"; };
2612+
26E7EE6B292D894100793045 /* AnalyticsReportCardViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsReportCardViewModel.swift; sourceTree = "<group>"; };
26092613
26ED965F274328BC00FA00A1 /* SimplePaymentsSummaryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimplePaymentsSummaryViewModel.swift; sourceTree = "<group>"; };
26102614
26F65C9725DEDAF0008FAE29 /* GenerateVariationUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerateVariationUseCase.swift; sourceTree = "<group>"; };
26112615
26F65C9D25DEDE67008FAE29 /* GenerateVariationUseCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerateVariationUseCaseTests.swift; sourceTree = "<group>"; };
@@ -5245,7 +5249,9 @@
52455249
isa = PBXGroup;
52465250
children = (
52475251
2647F7B429280A7F00D59FDF /* AnalyticsHubView.swift */,
5248-
2647F7B9292BE2F900D59FDF /* StatsCard.swift */,
5252+
26E7EE69292D688900793045 /* AnalyticsHubViewModel.swift */,
5253+
2647F7B9292BE2F900D59FDF /* AnalyticsReportCard.swift */,
5254+
26E7EE6B292D894100793045 /* AnalyticsReportCardViewModel.swift */,
52495255
);
52505256
path = "Analytics Hub";
52515257
sourceTree = "<group>";
@@ -9763,6 +9769,7 @@
97639769
57896D6625362B0C000E8C4D /* TitleAndEditableValueTableViewCellViewModel.swift in Sources */,
97649770
0205021E27C8B6C600FB1C6B /* InboxEligibilityUseCase.swift in Sources */,
97659771
26E1BECE251CD9F80096D0A1 /* RefundItemViewModel.swift in Sources */,
9772+
26E7EE6C292D894100793045 /* AnalyticsReportCardViewModel.swift in Sources */,
97669773
6827141128A5410D00E6E3F6 /* NewSimplePaymentsLocationNoticeViewModel.swift in Sources */,
97679774
DE7B479027A153C20018742E /* CouponSearchUICommand.swift in Sources */,
97689775
DE50294D28BEF8F100551736 /* JetpackConnectionWebViewModel.swift in Sources */,
@@ -10179,7 +10186,7 @@
1017910186
02482A8B237BE8C7007E73ED /* LinkSettingsViewController.swift in Sources */,
1018010187
CE227097228F152400C0626C /* WooBasicTableViewCell.swift in Sources */,
1018110188
02C27BCE282CB52F0065471A /* CardPresentPaymentReceiptEmailCoordinator.swift in Sources */,
10182-
2647F7BA292BE2F900D59FDF /* StatsCard.swift in Sources */,
10189+
2647F7BA292BE2F900D59FDF /* AnalyticsReportCard.swift in Sources */,
1018310190
451526392577D89E0076B03C /* AddAttributeViewModel.swift in Sources */,
1018410191
DE0A2EAF281BA278007A8015 /* ProductCategorySelectorViewModel.swift in Sources */,
1018510192
45B9C64323A91CB6007FC4C5 /* PriceInputFormatter.swift in Sources */,
@@ -10564,6 +10571,7 @@
1056410571
020F41E623163C0100776C4D /* TopBannerView.swift in Sources */,
1056510572
DE6906E327D7121800735E3B /* GhostTableViewController.swift in Sources */,
1056610573
02EEB5C42424AFAA00B8A701 /* TextFieldTableViewCell.swift in Sources */,
10574+
26E7EE6A292D688900793045 /* AnalyticsHubViewModel.swift in Sources */,
1056710575
AE457813275644590092F687 /* OrderStatusSection.swift in Sources */,
1056810576
B57C744E20F56E3800EEFC87 /* UITableViewCell+Helpers.swift in Sources */,
1056910577
0295355B245ADF8100BDC42B /* FilterType+Products.swift in Sources */,

0 commit comments

Comments
 (0)