diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHardwareDetailView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHardwareDetailView.swift index aa9ea0f0225..489e6d4fa3f 100644 --- a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHardwareDetailView.swift +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHardwareDetailView.swift @@ -1,12 +1,17 @@ import SwiftUI +import enum Yosemite.AppSettingsAction struct PointOfSaleSettingsHardwareDetailView: View { - @State private var navigationPath: [PointOfSaleSettingsView.HardwareDestination] = [] + @State private var navigationPath: [NavigationDestination] = [] + @State private var lastKnownLoadedCardReader: String? + @State private var showBarcodeScanningSetupModal: Bool = false + @State private var showBarcodeScanningDocumentationModal: Bool = false + @State private var showCardReaderDocumentationModal: Bool = false var body: some View { NavigationStack(path: $navigationPath) { - List(PointOfSaleSettingsView.HardwareDestination.allCases) { destination in - NavigationLink(value: destination) { + List(HardwareDestination.allCases) { destination in + NavigationLink(value: NavigationDestination.hardware(destination)) { HStack(alignment: .firstTextBaseline) { Image(systemName: destination.icon) .font(.posBodyLargeRegular()) @@ -20,19 +25,295 @@ struct PointOfSaleSettingsHardwareDetailView: View { } } } - .navigationDestination(for: PointOfSaleSettingsView.HardwareDestination.self) { destination in - VStack(spacing: POSSpacing.medium) { - Image(systemName: destination.icon).font(.largeTitle) + .navigationDestination(for: NavigationDestination.self) { destination in + switch destination { + case .hardware(.cardReaders): + cardReadersView + case .hardware(.scanners): + scannersView + } + } + .posModal(isPresented: $showBarcodeScanningSetupModal) { + PointOfSaleBarcodeScannerSetup(isPresented: $showBarcodeScanningSetupModal) + } + .posFullScreenCover(isPresented: $showBarcodeScanningDocumentationModal) { + SafariView(url: WooConstants.URLs.pointOfSaleDocumentation.asURL()) + } + } + } + + private func handleScannerDestination(_ destination: ScannerDestination) { + switch destination { + case .setup: + showBarcodeScanningSetupModal = true + case .documentation: + showBarcodeScanningDocumentationModal = true + } + } + + private var cardReadersView: some View { + VStack(spacing: POSSpacing.large) { + VStack(spacing: POSSpacing.medium) { + VStack(spacing: POSPadding.small) { + Text(Localization.cardReadersDescription) .font(.posBodyLargeRegular()) - Text("\(destination.title) settings") + .multilineTextAlignment(.center) + Text(Localization.cardReadersSubtitle1) + .font(.posBodyMediumRegular()) + .foregroundStyle(.secondary) + .multilineTextAlignment(.center) + Text(Localization.cardReadersSubtitle2) .font(.posBodyMediumRegular()) - Text("Some placeholder") + .foregroundStyle(.secondary) + .multilineTextAlignment(.center) + Text(Localization.cardReadersSubtitle3) .font(.posBodyMediumRegular()) .foregroundStyle(.secondary) + .multilineTextAlignment(.center) + } + } + .padding() + + if let lastKnownLoadedCardReader { + HStack { + Text("Model: \(lastKnownLoadedCardReader)") + .font(.posBodyMediumRegular()) + .foregroundStyle(.secondary) + .multilineTextAlignment(.center) + } + } + + List { + Button { + showCardReaderDocumentationModal = true + } label: { + HStack(alignment: .firstTextBaseline) { + Image(systemName: "doc.text") + .font(.posBodyLargeRegular()) + VStack(alignment: .leading, spacing: POSPadding.xSmall) { + Text(Localization.cardReaderDocumentationTitle) + .font(.posBodyLargeRegular()) + Text(Localization.cardReaderDocumentationSubtitle) + .font(.posBodyMediumRegular()) + .foregroundStyle(.secondary) + } + } + } + .buttonStyle(.plain) + } + } + .navigationTitle(Localization.cardReadersTitle) + .posFullScreenCover(isPresented: $showCardReaderDocumentationModal) { + SafariView(url: WooConstants.URLs.inPersonPaymentsLearnMoreWCPay.asURL()) + } + .task { @MainActor in + // TODO: WOOMOB-1172 + let action = AppSettingsAction.loadCardReader { reader in + switch reader { + case let .success(foundReader): + lastKnownLoadedCardReader = foundReader + case let .failure(error): + debugPrint(error) } - .padding() - .navigationTitle(destination.title) } + ServiceLocator.stores.dispatch(action) } } + + private var scannersView: some View { + List(ScannerDestination.allCases) { destination in + Button { + handleScannerDestination(destination) + } label: { + 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) + } + } + } + .buttonStyle(.plain) + } + .navigationTitle(Localization.scannersTitle) + } + +} + +extension PointOfSaleSettingsHardwareDetailView { + 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" + } + } + } + + enum NavigationDestination: Hashable { + case hardware(HardwareDestination) + } + + enum ScannerDestination: Identifiable, CaseIterable { + case setup + case documentation + + var id: Self { self } + + var title: String { + switch self { + case .setup: + return Localization.scannerSetupTitle + case .documentation: + return Localization.scannerDocumentationTitle + } + } + + var subtitle: String { + switch self { + case .setup: + return Localization.scannerSetupSubtitle + case .documentation: + return Localization.scannerDocumentationSubtitle + } + } + + var icon: String { + switch self { + case .setup: + return "gearshape" + case .documentation: + return "doc.text" + } + } + } +} + +private extension PointOfSaleSettingsHardwareDetailView { + enum Localization { + static let cardReadersTitle = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.cardReadersTitle", + value: "Card readers", + comment: "Navigation title for card readers settings in Point of Sale." + ) + + static let scannersTitle = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.scannersTitle", + value: "Barcode scanners", + comment: "Navigation title for barcode scanners settings in Point of Sale." + ) + + static let scannerSetupTitle = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.scannerSetupTitle", + value: "Scanner Setup", + comment: "Title for scanner setup option in barcode scanners settings in Point of Sale." + ) + + static let scannerSetupSubtitle = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.scannerSetupSubtitle", + value: "Configure and test your barcode scanner", + comment: "Subtitle describing scanner setup in Point of Sale settings." + ) + + static let scannerDocumentationTitle = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.scannerDocumentationTitle", + value: "Documentation", + comment: "Title for barcode scanner documentation option in Point of Sale settings." + ) + + static let scannerDocumentationSubtitle = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.scannerDocumentationSubtitle", + value: "Learn more about barcode scanning in POS", + comment: "Subtitle describing barcode scanner documentation in Point of Sale settings." + ) + + static let cardReadersDescription = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.cardReadersDescription", + value: "Accept secure and fast payments in person", + comment: "Main description for card readers functionality in Point of Sale settings." + ) + + static let cardReadersSubtitle1 = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.cardReadersSubtitle.1", + value: "Make sure the card reader is charged", + comment: "Subtitle describing card reader connection in Point of Sale settings." + ) + + static let cardReadersSubtitle2 = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.cardReadersSubtitle.2", + value: "Turn the card reader on, and place it next to the mobile device", + comment: "Subtitle describing card reader connection in Point of Sale settings." + ) + + static let cardReadersSubtitle3 = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.cardReadersSubtitle.3", + value: "Turn the mobile device bluetooth on", + comment: "Subtitle describing card reader connection in Point of Sale settings." + ) + + static let cardReaderDocumentationTitle = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.cardReaderDocumentationTitle", + value: "Documentation", + comment: "Title for card reader documentation option in Point of Sale settings." + ) + + static let cardReaderDocumentationSubtitle = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.cardReaderDocumentationSubtitle", + value: "Learn more about accepting mobile payments", + comment: "Subtitle describing card reader documentation in Point of Sale settings." + ) + + static let hardwareNavigationBarcodeTitle = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.hardwareNavigationBarcodeTitle", + value: "Barcode scanners", + comment: "Navigation title of Barcode scanner settings." + ) + + static let hardwareNavigationCardReaderTitle = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.hardwareNavigationCardReaderTitle", + value: "Card readers", + comment: "Navigation title of Card reader settings." + ) + + static let hardwareNavigationCardReaderSubtitle = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.hardwareNavigationCardReaderSubtitle", + value: "Manage card reader connections", + comment: "Description of Card reader settings for connections." + ) + + static let hardwareNavigationBarcodeSubtitle = NSLocalizedString( + "pointOfSaleSettingsHardwareDetailView.hardwareNavigationBarcodeSubtitle", + value: "Configure barcode scanner settings", + comment: "Description of Barcode scanner settings configuration." + ) + } } diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift index e653db70344..cea2e2a5b31 100644 --- a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift @@ -14,105 +14,84 @@ struct PointOfSaleSettingsView: View { } .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) + GeometryReader { geometry in + 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()) - Text(item.subtitle) - .font(.posBodyMediumRegular()) - .foregroundStyle(.secondary) + VStack(alignment: .leading) { + Text(item.title) + .font(.posBodyLargeRegular()) + Text(item.subtitle) + .font(.posBodyMediumRegular()) + .foregroundStyle(.secondary) + } } + .tag(item) } - .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) + .safeAreaInset(edge: .bottom) { + Button { + selection = .help + } label: { + HStack { + Image(systemName: SidebarNavigation.help.icon) .font(.posBodyLargeRegular()) .foregroundStyle(selection == .help ? .white : .primary) - Text(SidebarNavigation.help.subtitle) - .font(.posBodyMediumRegular()) - .foregroundStyle(selection == .help ? .secondary : .secondary) + 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() } - Spacer() + .padding(.vertical, POSPadding.small) + .padding(.horizontal, POSPadding.medium) + .contentShape(Rectangle()) } - .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) + ) } - .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(width: geometry.size.width * Constants.sidebarWidthFraction) + + detailView + .frame(maxWidth: .infinity, maxHeight: .infinity) } - .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 - } + @ViewBuilder + private var detailView: some View { + switch selection { + case .store: + PointOfSaleSettingsStoreDetailView() + case .hardware: + PointOfSaleSettingsHardwareDetailView() + case .help: + PointOfSaleSettingsHelpDetailView() + default: + EmptyView() } + } +} - var icon: String { - switch self { - case .cardReaders: - return "creditcard" - case .scanners: - return "qrcode.viewfinder" - } - } +extension PointOfSaleSettingsView { + enum Constants { + static let sidebarWidthFraction: CGFloat = 0.35 } } @@ -191,30 +170,6 @@ private extension PointOfSaleSettingsView { 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." - ) } }