diff --git a/Modules/Sources/Experiments/DefaultFeatureFlagService.swift b/Modules/Sources/Experiments/DefaultFeatureFlagService.swift index 12c5660b659..5c4cea27888 100644 --- a/Modules/Sources/Experiments/DefaultFeatureFlagService.swift +++ b/Modules/Sources/Experiments/DefaultFeatureFlagService.swift @@ -95,7 +95,7 @@ public struct DefaultFeatureFlagService: FeatureFlagService { case .pointOfSaleOrdersi2: return true case .pointOfSaleSettingsi1: - return false + return buildConfig == .localDeveloper || buildConfig == .alpha case .orderAddressMapSearch: return true case .pointOfSaleHistoricalOrdersi1: diff --git a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift deleted file mode 100644 index 0c5f5f4edae..00000000000 --- a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift +++ /dev/null @@ -1,21 +0,0 @@ -import SwiftUI - -struct PointOfSaleSettingsView: View { - @Environment(\.dismiss) private var dismiss - var body: some View { - NavigationView { - Text("Settings") - .toolbar { - ToolbarItem(placement: .navigationBarTrailing) { - Button("Done") { - dismiss() - } - } - } - } - } -} - -#Preview { - PointOfSaleSettingsView() -} diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHardwareDetailView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHardwareDetailView.swift new file mode 100644 index 00000000000..aa9ea0f0225 --- /dev/null +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHardwareDetailView.swift @@ -0,0 +1,38 @@ +import SwiftUI + +struct PointOfSaleSettingsHardwareDetailView: View { + @State private var navigationPath: [PointOfSaleSettingsView.HardwareDestination] = [] + + var body: some View { + NavigationStack(path: $navigationPath) { + List(PointOfSaleSettingsView.HardwareDestination.allCases) { destination in + NavigationLink(value: destination) { + HStack(alignment: .firstTextBaseline) { + Image(systemName: destination.icon) + .font(.posBodyLargeRegular()) + VStack(alignment: .leading, spacing: POSPadding.xSmall) { + Text(destination.title) + .font(.posBodyLargeRegular()) + Text(destination.subtitle) + .font(.posBodyMediumRegular()) + .foregroundStyle(.secondary) + } + } + } + } + .navigationDestination(for: PointOfSaleSettingsView.HardwareDestination.self) { destination in + VStack(spacing: POSSpacing.medium) { + Image(systemName: destination.icon).font(.largeTitle) + .font(.posBodyLargeRegular()) + Text("\(destination.title) settings") + .font(.posBodyMediumRegular()) + Text("Some placeholder") + .font(.posBodyMediumRegular()) + .foregroundStyle(.secondary) + } + .padding() + .navigationTitle(destination.title) + } + } + } +} diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHelpDetailView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHelpDetailView.swift new file mode 100644 index 00000000000..50ce18ccd82 --- /dev/null +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHelpDetailView.swift @@ -0,0 +1,16 @@ +import SwiftUI + +struct PointOfSaleSettingsHelpDetailView: View { + var body: some View { + NavigationStack { + VStack(alignment: .leading) { + Text("Help Settings") + .font(.title2) + Text("Help-related configuration") + .font(.caption) + .foregroundStyle(.secondary) + } + .padding() + } + } +} diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift new file mode 100644 index 00000000000..2192d786ce3 --- /dev/null +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift @@ -0,0 +1,16 @@ +import SwiftUI + +struct PointOfSaleSettingsStoreDetailView: View { + var body: some View { + NavigationStack { + VStack(alignment: .leading) { + Text("Store Settings") + .font(.title2) + Text("Store-related configuration") + .font(.caption) + .foregroundStyle(.secondary) + } + .padding() + } + } +} diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift new file mode 100644 index 00000000000..e653db70344 --- /dev/null +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift @@ -0,0 +1,223 @@ +import SwiftUI + +struct PointOfSaleSettingsView: View { + @Environment(\.dismiss) private var dismiss + @State private var selection: SidebarNavigation? = .store + + var body: some View { + POSPageHeaderView( + title: Localization.navigationTitle, + trailingContent: { + Button(action: { dismiss() }) { + Text(Image(systemName: "xmark")) + .font(.posButtonSymbolLarge) + } + .foregroundColor(.posOnSurface) + }) + HStack(spacing: POSSpacing.none) { + VStack(alignment: .leading, spacing: POSSpacing.none) { + List(selection: $selection) { + Section { + ForEach([SidebarNavigation.store, SidebarNavigation.hardware], id: \.self) { item in + HStack { + Image(systemName: item.icon) + .font(.posBodyLargeRegular()) + VStack(alignment: .leading) { + Text(item.title) + .font(.posBodyLargeRegular()) + Text(item.subtitle) + .font(.posBodyMediumRegular()) + .foregroundStyle(.secondary) + } + } + .tag(item) + } + } + } + .safeAreaInset(edge: .bottom) { + Button { + selection = .help + } label: { + HStack { + Image(systemName: SidebarNavigation.help.icon) + .font(.posBodyLargeRegular()) + .foregroundStyle(selection == .help ? .white : .primary) + VStack(alignment: .leading) { + Text(SidebarNavigation.help.title) + .font(.posBodyLargeRegular()) + .foregroundStyle(selection == .help ? .white : .primary) + Text(SidebarNavigation.help.subtitle) + .font(.posBodyMediumRegular()) + .foregroundStyle(selection == .help ? .secondary : .secondary) + } + Spacer() + } + .padding(.vertical, POSPadding.small) + .padding(.horizontal, POSPadding.medium) + .contentShape(Rectangle()) + } + .buttonStyle(.plain) + .background( + RoundedRectangle(cornerRadius: POSCornerRadiusStyle.large.value, style: .continuous) + .fill(selection == .help ? Color.accentColor : Color.clear) + ) + } + } + Group { + switch selection { + case .store: + PointOfSaleSettingsStoreDetailView() + case .hardware: + PointOfSaleSettingsHardwareDetailView() + case .help: + PointOfSaleSettingsHelpDetailView() + default: + EmptyView() + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + } +} + +extension PointOfSaleSettingsView { + enum HardwareDestination: Identifiable, CaseIterable { + case cardReaders + case scanners + + var id: Self { self } + + var title: String { + switch self { + case .cardReaders: + return Localization.hardwareNavigationCardReaderTitle + case .scanners: + return Localization.hardwareNavigationBarcodeTitle + } + } + + var subtitle: String { + switch self { + case .cardReaders: + return Localization.hardwareNavigationCardReaderSubtitle + case .scanners: + return Localization.hardwareNavigationBarcodeSubtitle + } + } + + var icon: String { + switch self { + case .cardReaders: + return "creditcard" + case .scanners: + return "qrcode.viewfinder" + } + } + } +} + +private extension PointOfSaleSettingsView { + enum SidebarNavigation: String, CaseIterable, Identifiable { + case store + case hardware + case help + + var id: Self { self } + + var title: String { + switch self { + case .store: return Localization.sidebarNavigationStoreTitle + case .hardware: return Localization.sidebarNavigationHardwareTitle + case .help: return Localization.sidebarNavigationHelpTitle + } + } + + var subtitle: String { + switch self { + case .store: return Localization.sidebarNavigationStoreSubtitle + case .hardware: return Localization.sidebarNavigationHardwareSubtitle + case .help: return Localization.sidebarNavigationHelpSubtitle + } + } + + var icon: String { + switch self { + case .store: return "bag" + case .hardware: return "wrench.and.screwdriver" + case .help: return "questionmark.circle" + } + } + } + + enum Localization { + static let navigationTitle = NSLocalizedString( + "pointOfSaleSettingsView.navigationTitle", + value: "Settings", + comment: "Title of the Point of Sale settings view." + ) + + static let sidebarNavigationStoreTitle = NSLocalizedString( + "pointOfSaleSettingsView.sidebarNavigationStoreTitle", + value: "Store", + comment: "Title of the Store section within Point of Sale settings." + ) + + static let sidebarNavigationHardwareTitle = NSLocalizedString( + "pointOfSaleSettingsView.sidebarNavigationHardwareTitle", + value: "Hardware", + comment: "Title of the Hardware section within Point of Sale settings." + ) + + static let sidebarNavigationHelpTitle = NSLocalizedString( + "pointOfSaleSettingsView.sidebarNavigationHelpTitle", + value: "Help", + comment: "Title of the Help section within Point of Sale settings." + ) + + static let sidebarNavigationStoreSubtitle = NSLocalizedString( + "pointOfSaleSettingsView.sidebarNavigationStoreSubtitle", + value: "Store configuration and settings", + comment: "Description of the settings to be found within the Store section." + ) + + static let sidebarNavigationHardwareSubtitle = NSLocalizedString( + "pointOfSaleSettingsView.sidebarNavigationHardwareSubtitle", + value: "Manage hardware connections", + comment: "Description of the settings to be found within the Hardware section." + ) + + static let sidebarNavigationHelpSubtitle = NSLocalizedString( + "pointOfSaleSettingsView.sidebarNavigationHelpSubtitle", + value: "Get help and support", + comment: "Description of the Help section in Point of Sale settings." + ) + + static let hardwareNavigationBarcodeTitle = NSLocalizedString( + "pointOfSaleSettingsView.hardwareNavigationBarcodeTitle", + value: "Barcode scanners", + comment: "Navigation title of Barcode scanner settings." + ) + + static let hardwareNavigationCardReaderTitle = NSLocalizedString( + "pointOfSaleSettingsView.hardwareNavigationCardReaderTitle", + value: "Card readers", + comment: "Navigation title of Card reader settings." + ) + + static let hardwareNavigationCardReaderSubtitle = NSLocalizedString( + "pointOfSaleSettingsView.hardwareNavigationCardReaderSubtitle", + value: "Manage card reader connections", + comment: "Description of Card reader settings for connections." + ) + + static let hardwareNavigationBarcodeSubtitle = NSLocalizedString( + "pointOfSaleSettingsView.hardwareNavigationBarcodeSubtitle", + value: "Configure barcode scanner settings", + comment: "Description of Barcode scanner settings configuration." + ) + } +} + +#Preview { + PointOfSaleSettingsView() +} diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index 0aa1fff372e..767780d07d5 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -1599,6 +1599,9 @@ 68674D312B6C895D00E93FBD /* ReceiptEligibilityUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68674D302B6C895D00E93FBD /* ReceiptEligibilityUseCaseTests.swift */; }; 686A71B62DC9E5C10006E835 /* POSItemActionHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 686A71B52DC9E5C10006E835 /* POSItemActionHandlerTests.swift */; }; 686A71B82DC9EB710006E835 /* MockPOSSearchHistoryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 686A71B72DC9EB6D0006E835 /* MockPOSSearchHistoryService.swift */; }; + 68707A172E570EB200500CD8 /* PointOfSaleSettingsHardwareDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68707A162E570EB000500CD8 /* PointOfSaleSettingsHardwareDetailView.swift */; }; + 68707A192E570F0200500CD8 /* PointOfSaleSettingsHelpDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68707A182E570F0000500CD8 /* PointOfSaleSettingsHelpDetailView.swift */; }; + 68707A1B2E570F2300500CD8 /* PointOfSaleSettingsStoreDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68707A1A2E570F2200500CD8 /* PointOfSaleSettingsStoreDetailView.swift */; }; 68709D3D2A2ED94900A7FA6C /* UpgradesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68709D3C2A2ED94900A7FA6C /* UpgradesView.swift */; }; 68709D402A2EE2DC00A7FA6C /* UpgradesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68709D3F2A2EE2DC00A7FA6C /* UpgradesViewModel.swift */; }; 6879B8DB287AFFA100A0F9A8 /* CardReaderManualsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6879B8DA287AFFA100A0F9A8 /* CardReaderManualsViewModelTests.swift */; }; @@ -4772,6 +4775,9 @@ 68674D302B6C895D00E93FBD /* ReceiptEligibilityUseCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReceiptEligibilityUseCaseTests.swift; sourceTree = ""; }; 686A71B52DC9E5C10006E835 /* POSItemActionHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSItemActionHandlerTests.swift; sourceTree = ""; }; 686A71B72DC9EB6D0006E835 /* MockPOSSearchHistoryService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPOSSearchHistoryService.swift; sourceTree = ""; }; + 68707A162E570EB000500CD8 /* PointOfSaleSettingsHardwareDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleSettingsHardwareDetailView.swift; sourceTree = ""; }; + 68707A182E570F0000500CD8 /* PointOfSaleSettingsHelpDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleSettingsHelpDetailView.swift; sourceTree = ""; }; + 68707A1A2E570F2200500CD8 /* PointOfSaleSettingsStoreDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleSettingsStoreDetailView.swift; sourceTree = ""; }; 68709D3C2A2ED94900A7FA6C /* UpgradesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpgradesView.swift; sourceTree = ""; }; 68709D3F2A2EE2DC00A7FA6C /* UpgradesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpgradesViewModel.swift; sourceTree = ""; }; 6879B8DA287AFFA100A0F9A8 /* CardReaderManualsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardReaderManualsViewModelTests.swift; sourceTree = ""; }; @@ -7174,7 +7180,6 @@ 68A345632D029E09002EE324 /* PaymentButtons.swift */, 026826A52BF59DF60036F959 /* PointOfSaleDashboardView.swift */, 68E141DA2D13107200A70D5B /* PointOfSaleCollectCashView.swift */, - 683D41172E4D9B570024CFE4 /* PointOfSaleSettingsView.swift */, DA013F502C65125100D9A391 /* PointOfSaleExitPosAlertView.swift */, DA0DBE2E2C4FC61D00DF14C0 /* POSFloatingControlView.swift */, 20D3D42A2C64D7CC004CE6E3 /* SimpleProductsOnlyInformation.swift */, @@ -7189,6 +7194,7 @@ 68D8FBD02BFEF9C700477C42 /* TotalsView.swift */, 68AF3C3A2D01481A006F1ED2 /* POSReceiptEligibilityBanner.swift */, DA1D68C12C36F0980097859A /* PointOfSaleAssets.swift */, + 68707A152E570E7D00500CD8 /* Settings */, ); path = Presentation; sourceTree = ""; @@ -9908,6 +9914,17 @@ path = Testing; sourceTree = ""; }; + 68707A152E570E7D00500CD8 /* Settings */ = { + isa = PBXGroup; + children = ( + 683D41172E4D9B570024CFE4 /* PointOfSaleSettingsView.swift */, + 68707A1A2E570F2200500CD8 /* PointOfSaleSettingsStoreDetailView.swift */, + 68707A182E570F0000500CD8 /* PointOfSaleSettingsHelpDetailView.swift */, + 68707A162E570EB000500CD8 /* PointOfSaleSettingsHardwareDetailView.swift */, + ); + path = Settings; + sourceTree = ""; + }; 68709D3E2A2EE2C000A7FA6C /* InAppPurchases */ = { isa = PBXGroup; children = ( @@ -15770,6 +15787,7 @@ 02695770237281A9001BA0BF /* AztecTextViewAttachmentHandler.swift in Sources */, CCCFFC5A2934EF5E006130AF /* StatsIntervalDataParser.swift in Sources */, 01BE94002DDCB1110063541C /* Error+Connectivity.swift in Sources */, + 68707A1B2E570F2300500CD8 /* PointOfSaleSettingsStoreDetailView.swift in Sources */, DE5746342B4512900034B10D /* BlazeBudgetSettingView.swift in Sources */, 26771A14256FFA8700EE030E /* IssueRefundCoordinatingController.swift in Sources */, 027A2E162513356100DA6ACB /* AppleIDCredentialChecker.swift in Sources */, @@ -16760,6 +16778,7 @@ 024DF31423742B7A006658FE /* AztecUnderlineFormatBarCommand.swift in Sources */, 020564982D5DC96600E51059 /* POSShadowStyle.swift in Sources */, CE32B10D20BEDE1C006FBCF4 /* TwoColumnSectionHeaderView.swift in Sources */, + 68707A192E570F0200500CD8 /* PointOfSaleSettingsHelpDetailView.swift in Sources */, AE7C957D27C3F187007E8E12 /* FeeOrDiscountLineDetailsViewModel.swift in Sources */, 4520A15C2721B2A9001FA573 /* FilterOrderListViewModel.swift in Sources */, B582F95920FFCEAA0060934A /* UITableViewHeaderFooterView+Helpers.swift in Sources */, @@ -16892,6 +16911,7 @@ 6850C5F62B6A51C90026A93B /* ReceiptEligibilityUseCase.swift in Sources */, 028CB70F290138EF00331C09 /* Publisher+Concurrency.swift in Sources */, 311F827426CD897900DF5BAD /* CardReaderSettingsAlertsProvider.swift in Sources */, + 68707A172E570EB200500CD8 /* PointOfSaleSettingsHardwareDetailView.swift in Sources */, CC4D1D8625E6CDDE00B6E4E7 /* RenameAttributesViewModel.swift in Sources */, DEFA3D932897D8930076FAE1 /* NoWooErrorViewModel.swift in Sources */, 209B15672AD85F070094152A /* OperatingSystemVersion+Localization.swift in Sources */,