Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import SwiftUI

struct POSSettingsLocalCatalogDetailView: View {
// TODO: WOOMOB-1335 - implement full sync cellular data setting functionality
@State private var allowFullSyncOnCellular: Bool = true

var body: some View {
NavigationStack {
VStack(spacing: POSSpacing.none) {
POSPageHeaderView(title: Localization.localCatalogTitle)
.foregroundColor(.posSurface)
.accessibilityAddTraits(.isHeader)

ScrollView {
VStack(spacing: POSSpacing.medium) {
catalogStatus
managingDataUsage
manualCatalogUpdate
}
}
.background(Style.backgroundColor)
}
}
}
}

private extension POSSettingsLocalCatalogDetailView {
@ViewBuilder
var catalogStatus: some View {
VStack(spacing: POSSpacing.none) {
sectionHeaderView(title: Localization.catalogStatus)

VStack(spacing: POSSpacing.medium) {
// TODO: WOOMOB-1100 - replace with catalog data
fieldRowView(label: Localization.catalogSize, value: "1,250 products, 3,420 variations")
fieldRowView(label: Localization.lastIncrementalUpdate, value: "5 minutes ago")
fieldRowView(label: Localization.lastFullSync, value: "Today at 2:34 PM")
}
.padding(.bottom, POSPadding.medium)
}
}

@ViewBuilder
var managingDataUsage: some View {
VStack(spacing: POSSpacing.none) {
sectionHeaderView(title: Localization.managingDataUsage)

VStack(spacing: POSSpacing.medium) {
toggleRowView(label: Localization.allowFullSyncOnCellular, isOn: $allowFullSyncOnCellular)
}
.padding(.bottom, POSPadding.medium)
}
}

@ViewBuilder
var manualCatalogUpdate: some View {
VStack(spacing: POSSpacing.none) {
sectionHeaderView(title: Localization.manualCatalogUpdate)

VStack(spacing: POSSpacing.medium) {
Text(Localization.manualUpdateInfo)
.font(.posCaptionRegular)
.foregroundStyle(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)

Button(action: {
// Handle refresh catalog action
}) {
Text(Localization.refreshCatalog)
}
.buttonStyle(POSFilledButtonStyle(size: .normal))
}
.padding(.horizontal, POSPadding.medium)
.padding(.bottom, POSPadding.medium)
}
}

@ViewBuilder
func sectionHeaderView(title: String) -> some View {
ZStack {
Style.backgroundColor
Text(title)
.font(.posBodyLargeBold)
.foregroundColor(.posOnSurface)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, POSPadding.medium)
.padding(.vertical, POSPadding.small)
}
}

@ViewBuilder
func fieldRowView(label: String, value: String) -> some View {
VStack(alignment: .leading, spacing: POSPadding.small) {
Text(label)
.font(.posBodyMediumRegular())
Text(value)
.font(.posBodyMediumRegular())
.foregroundStyle(.secondary)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, POSPadding.medium)
}

@ViewBuilder
func toggleRowView(label: String, isOn: Binding<Bool>) -> some View {
HStack {
Text(label)
.font(.posBodyMediumRegular())
Spacer()
Toggle("", isOn: isOn)
.toggleStyle(SwitchToggleStyle())
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, POSPadding.medium)
}
}

private extension POSSettingsLocalCatalogDetailView {
enum Style {
static let backgroundColor = Color.posOnSecondaryContainer
}

enum Localization {
static let localCatalogTitle = NSLocalizedString(
"posSettingsLocalCatalogDetailView.title",
value: "Catalog Settings",
comment: "Navigation title for the local catalog details in POS settings."
)

static let catalogStatus = NSLocalizedString(
"posSettingsLocalCatalogDetailView.catalogStatus",
value: "Catalog Status",
comment: "Section title for catalog status in Point of Sale settings."
)

static let managingDataUsage = NSLocalizedString(
"posSettingsLocalCatalogDetailView.managingDataUsage",
value: "Managing data usage",
comment: "Section title for managing data usage in Point of Sale settings."
)

static let lastIncrementalUpdate = NSLocalizedString(
"posSettingsLocalCatalogDetailView.lastIncrementalUpdate",
value: "Last incremental update",
comment: "Label for last incremental update field in Point of Sale settings."
)

static let lastFullSync = NSLocalizedString(
"posSettingsLocalCatalogDetailView.lastFullSync",
value: "Last full sync",
comment: "Label for last full sync field in Point of Sale settings."
)

static let catalogSize = NSLocalizedString(
"posSettingsLocalCatalogDetailView.catalogSize",
value: "Catalog size",
comment: "Label for catalog size field in Point of Sale settings."
)


static let allowFullSyncOnCellular = NSLocalizedString(
"posSettingsLocalCatalogDetailView.allowFullSyncOnCellular",
value: "Allow full sync on cellular data",
comment: "Label for allow full sync on cellular data toggle in Point of Sale settings."
)


static let manualCatalogUpdate = NSLocalizedString(
"posSettingsLocalCatalogDetailView.manualCatalogUpdate",
value: "Manual Catalog Update",
comment: "Section title for manual catalog update in Point of Sale settings."
)

static let manualUpdateInfo = NSLocalizedString(
"posSettingsLocalCatalogDetailView.manualUpdateInfo",
value: "Use this refresh only when something seems off - POS keeps data current automatically.",
comment: "Info text explaining when to use manual catalog update."
)

static let refreshCatalog = NSLocalizedString(
"posSettingsLocalCatalogDetailView.refreshCatalog",
value: "Refresh catalog",
comment: "Button text for refreshing the catalog manually."
)
}
}

#if DEBUG
#Preview {
POSSettingsLocalCatalogDetailView()
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ extension PointOfSaleSettingsView {
}
)

// TODO: WOOMOB-1287 - integrate with local catalog feature eligibility
if ServiceLocator.featureFlagService.isFeatureFlagEnabled(.pointOfSaleLocalCatalogi1) {
PointOfSaleSettingsCard(
item: .localCatalog,
isSelected: selection == .localCatalog,
onTap: {
selection = .localCatalog
}
)
}

Spacer()

PointOfSaleSettingsCard(
Expand All @@ -76,6 +87,8 @@ extension PointOfSaleSettingsView {
PointOfSaleSettingsStoreDetailView(viewModel: settingsController.storeViewModel)
case .hardware:
PointOfSaleSettingsHardwareDetailView(settingsController: settingsController)
case .localCatalog:
POSSettingsLocalCatalogDetailView()
case .help:
PointOfSaleSettingsHelpDetailView()
default:
Expand Down Expand Up @@ -141,6 +154,7 @@ extension PointOfSaleSettingsView {
enum SidebarNavigation: String, CaseIterable, Identifiable {
case store
case hardware
case localCatalog
case help

var id: Self { self }
Expand All @@ -149,6 +163,7 @@ extension PointOfSaleSettingsView {
switch self {
case .store: return Localization.sidebarNavigationStoreTitle
case .hardware: return Localization.sidebarNavigationHardwareTitle
case .localCatalog: return Localization.sidebarNavigationLocalCatalogTitle
case .help: return Localization.sidebarNavigationHelpTitle
}
}
Expand All @@ -157,6 +172,7 @@ extension PointOfSaleSettingsView {
switch self {
case .store: return Localization.sidebarNavigationStoreSubtitle
case .hardware: return Localization.sidebarNavigationHardwareSubtitle
case .localCatalog: return Localization.sidebarNavigationLocalCatalogSubtitle
case .help: return Localization.sidebarNavigationHelpSubtitle
}
}
Expand All @@ -165,6 +181,7 @@ extension PointOfSaleSettingsView {
switch self {
case .store: return "bag"
case .hardware: return "wrench.and.screwdriver"
case .localCatalog: return "internaldrive"
case .help: return "questionmark.circle"
}
}
Expand Down Expand Up @@ -207,6 +224,18 @@ extension PointOfSaleSettingsView {
comment: "Description of the settings to be found within the Hardware section."
)

static let sidebarNavigationLocalCatalogTitle = NSLocalizedString(
"pointOfSaleSettingsView.sidebarNavigationLocalCatalogTitle",
value: "Catalog",
comment: "Title of the Local catalog section within Point of Sale settings."
)

static let sidebarNavigationLocalCatalogSubtitle = NSLocalizedString(
"pointOfSaleSettingsView.sidebarNavigationLocalCatalogSubtitle",
value: "Manage catalog settings",
comment: "Description of the settings to be found within the Local catalog section."
)

static let sidebarNavigationHelpSubtitle = NSLocalizedString(
"pointOfSaleSettingsView.sidebarNavigationHelpSubtitle",
value: "Get help and support",
Expand Down
4 changes: 4 additions & 0 deletions WooCommerce/WooCommerce.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@
023D69442588C6BD00F7DA72 /* ShippingLabelPaperSizeListSelectorCommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 023D69432588C6BD00F7DA72 /* ShippingLabelPaperSizeListSelectorCommandTests.swift */; };
023D69BC2589BF5900F7DA72 /* PrintShippingLabelCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 023D69BB2589BF5900F7DA72 /* PrintShippingLabelCoordinator.swift */; };
023D877925EC8BCB00625963 /* UIScrollView+LargeTitleWorkaround.swift in Sources */ = {isa = PBXBuildFile; fileRef = 023D877825EC8BCB00625963 /* UIScrollView+LargeTitleWorkaround.swift */; };
023DE6262E73FE4600FF6562 /* POSSettingsLocalCatalogDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 023DE6252E73FE4600FF6562 /* POSSettingsLocalCatalogDetailView.swift */; };
023EC2E024DA87460021DA91 /* ProductInventorySettingsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 023EC2DF24DA87460021DA91 /* ProductInventorySettingsViewModelTests.swift */; };
023EC2E224DA8BAB0021DA91 /* MockProductSKUValidationStoresManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 023EC2E124DA8BAB0021DA91 /* MockProductSKUValidationStoresManager.swift */; };
023EC2E424DA95DB0021DA91 /* ProductInventorySettingsViewModel+VariationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 023EC2E324DA95DB0021DA91 /* ProductInventorySettingsViewModel+VariationTests.swift */; };
Expand Down Expand Up @@ -3495,6 +3496,7 @@
023D69432588C6BD00F7DA72 /* ShippingLabelPaperSizeListSelectorCommandTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPaperSizeListSelectorCommandTests.swift; sourceTree = "<group>"; };
023D69BB2589BF5900F7DA72 /* PrintShippingLabelCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrintShippingLabelCoordinator.swift; sourceTree = "<group>"; };
023D877825EC8BCB00625963 /* UIScrollView+LargeTitleWorkaround.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIScrollView+LargeTitleWorkaround.swift"; sourceTree = "<group>"; };
023DE6252E73FE4600FF6562 /* POSSettingsLocalCatalogDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSSettingsLocalCatalogDetailView.swift; sourceTree = "<group>"; };
023EC2DF24DA87460021DA91 /* ProductInventorySettingsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductInventorySettingsViewModelTests.swift; sourceTree = "<group>"; };
023EC2E124DA8BAB0021DA91 /* MockProductSKUValidationStoresManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockProductSKUValidationStoresManager.swift; sourceTree = "<group>"; };
023EC2E324DA95DB0021DA91 /* ProductInventorySettingsViewModel+VariationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProductInventorySettingsViewModel+VariationTests.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -10023,6 +10025,7 @@
68707A152E570E7D00500CD8 /* Settings */ = {
isa = PBXGroup;
children = (
023DE6252E73FE4600FF6562 /* POSSettingsLocalCatalogDetailView.swift */,
683D41172E4D9B570024CFE4 /* PointOfSaleSettingsView.swift */,
68707A1A2E570F2200500CD8 /* PointOfSaleSettingsStoreDetailView.swift */,
685A30602E60908B001E667B /* POSSettingsStoreViewModel.swift */,
Expand Down Expand Up @@ -15731,6 +15734,7 @@
D89CFFDD25B44468000E4683 /* ULAccountMismatchViewController.swift in Sources */,
03E471C6293A2E95001A58AD /* CardPresentModalTapToPayReaderCheckingDeviceSupport.swift in Sources */,
B687940C27699D420092BCA0 /* RefundFeesCalculationUseCase.swift in Sources */,
023DE6262E73FE4600FF6562 /* POSSettingsLocalCatalogDetailView.swift in Sources */,
02EA6BF82435E80600FFF90A /* ImageDownloader.swift in Sources */,
CECC758623D21AC200486676 /* AggregateOrderItem.swift in Sources */,
453326FA2C3C38ED000E4862 /* ProductCreationAIBarProgressStyle.swift in Sources */,
Expand Down