Skip to content

Commit d8d49ac

Browse files
authored
Merge pull request #8215 from woocommerce/issue/8198-products-card-ui
Analytics Hub: Products Card UI
2 parents db568f9 + f052ed0 commit d8d49ac

File tree

7 files changed

+163
-17
lines changed

7 files changed

+163
-17
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ struct AnalyticsHubView: View {
5858
Divider()
5959
}
6060

61+
VStack(spacing: Layout.dividerSpacing) {
62+
Divider()
63+
64+
AnalyticsProductCard(viewModel: viewModel.productCard)
65+
.padding(.horizontal, insets: safeAreaInsets)
66+
.background(Color(uiColor: .listForeground))
67+
68+
Divider()
69+
}
70+
6171
Spacer()
6272
}
6373
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ final class AnalyticsHubViewModel: ObservableObject {
5353
currentRangeSubtitle: "Jan 1 - Nov 23, 2022",
5454
previousRangeSubtitle: "Jan 1 - Nov 23, 2021")
5555

56+
/// Products Card ViewModel
57+
///
58+
@Published var productCard = AnalyticsProductCardViewModel(itemsSold: "3,234",
59+
delta: "+43%",
60+
deltaBackgroundColor: .withColorStudio(.green, shade: .shade50))
61+
5662
// MARK: Private data
5763

5864
/// Order stats for the current selected time period
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import SwiftUI
2+
3+
/// Products Card on the Analytics Hub
4+
///
5+
struct AnalyticsProductCard: View {
6+
7+
/// Items sold quantity. Needs to be formatted.
8+
///
9+
let itemsSold: String
10+
11+
/// Delta Tag Value. Needs to be formatted
12+
let delta: String
13+
14+
/// Delta Tag background color.
15+
let deltaBackgroundColor: UIColor
16+
17+
var body: some View {
18+
VStack(alignment: .leading) {
19+
20+
Text(Localization.title)
21+
.foregroundColor(Color(.text))
22+
.footnoteStyle()
23+
24+
Text(Localization.itemsSold)
25+
.headlineStyle()
26+
.padding(.top, Layout.titleSpacing)
27+
.padding(.bottom, Layout.columnSpacing)
28+
29+
HStack {
30+
Text(itemsSold)
31+
.titleStyle()
32+
.frame(maxWidth: .infinity, alignment: .leading)
33+
34+
DeltaTag(value: delta, backgroundColor: deltaBackgroundColor)
35+
}
36+
}
37+
.padding(Layout.cardPadding)
38+
}
39+
}
40+
41+
// MARK: Constants
42+
private extension AnalyticsProductCard {
43+
enum Localization {
44+
static let title = NSLocalizedString("Products", comment: "Title for the products card on the analytics hub screen.").localizedUppercase
45+
static let itemsSold = NSLocalizedString("Items Sold", comment: "Title for the items sold column on the products card on the analytics hub screen.")
46+
}
47+
48+
enum Layout {
49+
static let titleSpacing: CGFloat = 24
50+
static let cardPadding: CGFloat = 16
51+
static let columnSpacing: CGFloat = 10
52+
}
53+
}
54+
55+
56+
// MARK: Previews
57+
struct AnalyticsProductCardPreviews: PreviewProvider {
58+
static var previews: some View {
59+
AnalyticsProductCard(itemsSold: "2,234", delta: "+23%", deltaBackgroundColor: .withColorStudio(.green, shade: .shade50))
60+
.previewLayout(.sizeThatFits)
61+
}
62+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import Foundation
2+
import class UIKit.UIColor
3+
4+
/// Analytics Hub Product Card ViewModel.
5+
/// Used to transmit analytics products data.
6+
///
7+
struct AnalyticsProductCardViewModel {
8+
/// Items Sold Value
9+
///
10+
let itemsSold: String
11+
12+
/// Items Sold Delta
13+
///
14+
let delta: String
15+
16+
/// Delta background color.
17+
///
18+
let deltaBackgroundColor: UIColor
19+
}
20+
21+
/// Convenience extension to create an `AnalyticsReportCard` from a view model.
22+
///
23+
extension AnalyticsProductCard {
24+
init(viewModel: AnalyticsProductCardViewModel) {
25+
self.itemsSold = viewModel.itemsSold
26+
self.delta = viewModel.delta
27+
self.deltaBackgroundColor = viewModel.deltaBackgroundColor
28+
}
29+
}

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

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -56,29 +56,12 @@ struct AnalyticsReportCard: View {
5656
}
5757
}
5858

59-
private struct DeltaTag: View {
60-
61-
let value: String
62-
let backgroundColor: UIColor
63-
64-
var body: some View {
65-
Text(value)
66-
.padding(AnalyticsReportCard.Layout.deltaBackgroundPadding)
67-
.foregroundColor(Color(.textInverted))
68-
.captionStyle()
69-
.background(Color(backgroundColor))
70-
.cornerRadius(AnalyticsReportCard.Layout.deltaCornerRadius)
71-
}
72-
}
73-
7459
// MARK: Constants
7560
private extension AnalyticsReportCard {
7661
enum Layout {
7762
static let titleSpacing: CGFloat = 24
7863
static let cardPadding: CGFloat = 16
7964
static let columnSpacing: CGFloat = 10
80-
static let deltaBackgroundPadding = EdgeInsets(top: 2, leading: 8, bottom: 2, trailing: 8)
81-
static let deltaCornerRadius: CGFloat = 4.0
8265
}
8366
}
8467

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import SwiftUI
2+
3+
/// Reusable tag view.
4+
/// Useful to indicate growth rates.
5+
///
6+
struct DeltaTag: View {
7+
8+
/// Value to display. Needs to be already formatted
9+
///
10+
let value: String
11+
12+
/// Tag color.
13+
///
14+
let backgroundColor: UIColor
15+
16+
var body: some View {
17+
Text(value)
18+
.padding(Layout.backgroundPadding)
19+
.foregroundColor(Color(.textInverted))
20+
.captionStyle()
21+
.background(Color(backgroundColor))
22+
.cornerRadius(Layout.cornerRadius)
23+
}
24+
}
25+
26+
// MARK: Constants
27+
private extension DeltaTag {
28+
enum Layout {
29+
static let backgroundPadding = EdgeInsets(top: 2, leading: 8, bottom: 2, trailing: 8)
30+
static let cornerRadius: CGFloat = 4.0
31+
}
32+
}
33+
34+
// MARK: Peviews
35+
struct DeltaTagPreviews: PreviewProvider {
36+
static var previews: some View {
37+
VStack {
38+
DeltaTag(value: "+3.23%", backgroundColor: .systemGreen)
39+
40+
DeltaTag(value: "-3.23%", backgroundColor: .systemRed)
41+
}
42+
.previewLayout(.sizeThatFits)
43+
}
44+
}

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,9 @@
646646
26E1BECE251CD9F80096D0A1 /* RefundItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E1BECD251CD9F80096D0A1 /* RefundItemViewModel.swift */; };
647647
26E7EE6A292D688900793045 /* AnalyticsHubViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E7EE69292D688900793045 /* AnalyticsHubViewModel.swift */; };
648648
26E7EE6C292D894100793045 /* AnalyticsReportCardViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E7EE6B292D894100793045 /* AnalyticsReportCardViewModel.swift */; };
649+
26E7EE6E29300E8100793045 /* AnalyticsProductCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E7EE6D29300E8100793045 /* AnalyticsProductCard.swift */; };
650+
26E7EE7029300F6200793045 /* DeltaTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E7EE6F29300F6200793045 /* DeltaTag.swift */; };
651+
26E7EE7229301EBC00793045 /* AnalyticsProductCardViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E7EE7129301EBC00793045 /* AnalyticsProductCardViewModel.swift */; };
649652
26ED9660274328BC00FA00A1 /* SimplePaymentsSummaryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26ED965F274328BC00FA00A1 /* SimplePaymentsSummaryViewModel.swift */; };
650653
26F65C9825DEDAF0008FAE29 /* GenerateVariationUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26F65C9725DEDAF0008FAE29 /* GenerateVariationUseCase.swift */; };
651654
26F65C9E25DEDE67008FAE29 /* GenerateVariationUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26F65C9D25DEDE67008FAE29 /* GenerateVariationUseCaseTests.swift */; };
@@ -2623,6 +2626,9 @@
26232626
26E1BECD251CD9F80096D0A1 /* RefundItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefundItemViewModel.swift; sourceTree = "<group>"; };
26242627
26E7EE69292D688900793045 /* AnalyticsHubViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsHubViewModel.swift; sourceTree = "<group>"; };
26252628
26E7EE6B292D894100793045 /* AnalyticsReportCardViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsReportCardViewModel.swift; sourceTree = "<group>"; };
2629+
26E7EE6D29300E8100793045 /* AnalyticsProductCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsProductCard.swift; sourceTree = "<group>"; };
2630+
26E7EE6F29300F6200793045 /* DeltaTag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeltaTag.swift; sourceTree = "<group>"; };
2631+
26E7EE7129301EBC00793045 /* AnalyticsProductCardViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsProductCardViewModel.swift; sourceTree = "<group>"; };
26262632
26ED965F274328BC00FA00A1 /* SimplePaymentsSummaryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimplePaymentsSummaryViewModel.swift; sourceTree = "<group>"; };
26272633
26F65C9725DEDAF0008FAE29 /* GenerateVariationUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerateVariationUseCase.swift; sourceTree = "<group>"; };
26282634
26F65C9D25DEDE67008FAE29 /* GenerateVariationUseCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerateVariationUseCaseTests.swift; sourceTree = "<group>"; };
@@ -5277,6 +5283,8 @@
52775283
26E7EE6B292D894100793045 /* AnalyticsReportCardViewModel.swift */,
52785284
B60B5025292D308A00178C26 /* AnalyticsTimeRangeCard.swift */,
52795285
B6A10E9B292E5DEE00790797 /* AnalyticsTimeRangeCardViewModel.swift */,
5286+
26E7EE6D29300E8100793045 /* AnalyticsProductCard.swift */,
5287+
26E7EE7129301EBC00793045 /* AnalyticsProductCardViewModel.swift */,
52805288
);
52815289
path = "Analytics Hub";
52825290
sourceTree = "<group>";
@@ -6119,6 +6127,7 @@
61196127
02EAA4C92911004B00918DAB /* TextFieldStyles.swift */,
61206128
036CA6F029229C9E00E4DF4F /* IndefiniteCircularProgressViewStyle.swift */,
61216129
DE2FE5872925DD950018040A /* JetpackInstallHeaderView.swift */,
6130+
26E7EE6F29300F6200793045 /* DeltaTag.swift */,
61226131
);
61236132
path = "SwiftUI Components";
61246133
sourceTree = "<group>";
@@ -9789,6 +9798,7 @@
97899798
03EF24FC28BF996F006A033E /* InPersonPaymentsCashOnDeliveryPaymentGatewayHelpers.swift in Sources */,
97909799
57896D6625362B0C000E8C4D /* TitleAndEditableValueTableViewCellViewModel.swift in Sources */,
97919800
0205021E27C8B6C600FB1C6B /* InboxEligibilityUseCase.swift in Sources */,
9801+
26E7EE6E29300E8100793045 /* AnalyticsProductCard.swift in Sources */,
97929802
26E1BECE251CD9F80096D0A1 /* RefundItemViewModel.swift in Sources */,
97939803
26E7EE6C292D894100793045 /* AnalyticsReportCardViewModel.swift in Sources */,
97949804
6827141128A5410D00E6E3F6 /* NewSimplePaymentsLocationNoticeViewModel.swift in Sources */,
@@ -10333,6 +10343,7 @@
1033310343
E1E649E92846188C0070B194 /* BetaFeature.swift in Sources */,
1033410344
0286B27B23C7051F003D784B /* ProductImagesCollectionViewController.swift in Sources */,
1033510345
E107FCE126C12B2700BAF51B /* InPersonPaymentsCountryNotSupported.swift in Sources */,
10346+
26E7EE7229301EBC00793045 /* AnalyticsProductCardViewModel.swift in Sources */,
1033610347
027A2E142513124E00DA6ACB /* Keychain+Entries.swift in Sources */,
1033710348
268EC45F26CEA50C00716F5C /* EditCustomerNote.swift in Sources */,
1033810349
4535EE7E281BE04A004212B4 /* CouponAmountInputFormatter.swift in Sources */,
@@ -10445,6 +10456,7 @@
1044510456
020886572499E643001D784E /* ProductExternalLinkViewController.swift in Sources */,
1044610457
DEC2962526C122DF005A056B /* ShippingLabelCustomsFormInputViewModel.swift in Sources */,
1044710458
02F4F50F237AFC1E00E13A9C /* ImageAndTitleAndTextTableViewCell.swift in Sources */,
10459+
26E7EE7029300F6200793045 /* DeltaTag.swift in Sources */,
1044810460
021E2A1C23AA0DD100B1DE07 /* ProductBackordersSettingListSelectorCommand.swift in Sources */,
1044910461
26F94E21267A41BE00DB6CCF /* ProductAddOnsListViewModel.swift in Sources */,
1045010462
45F5A3C123DF206B007D40E5 /* ShippingInputFormatter.swift in Sources */,

0 commit comments

Comments
 (0)