From 770cc319169928ad8e3bd6385d536bb59fdc56f3 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 21 Aug 2025 12:52:06 +0700 Subject: [PATCH 01/15] initial settings view distribution --- .../PointOfSaleSettingsView.swift | 102 ++++++++++++++++-- 1 file changed, 96 insertions(+), 6 deletions(-) diff --git a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift index 0c5f5f4edae..cda01c81569 100644 --- a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift +++ b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift @@ -2,16 +2,106 @@ import SwiftUI struct PointOfSaleSettingsView: View { @Environment(\.dismiss) private var dismiss + @State private var selection: Sidebar? = .store + + enum Sidebar: String, CaseIterable, Identifiable { + case store + case hardware + case help + + var id: Self { self } + + var title: String { + switch self { + case .store: return "Store" + case .hardware: return "Hardware" + case .help: return "Help" + } + } + + var subtitle: String { + switch self { + case .store: return "Store configuration and settings" + case .hardware: return "Manage hardware connections" + case .help: return "Get help and support" + } + } + + var icon: String { + switch self { + case .store: return "bag" + case .hardware: return "wrench.and.screwdriver" + case .help: return "questionmark.circle" + } + } + } + var body: some View { - NavigationView { - Text("Settings") - .toolbar { - ToolbarItem(placement: .navigationBarTrailing) { - Button("Done") { - dismiss() + NavigationStack { + HStack(spacing: 0) { + // Left (nav) + List(selection: $selection) { + // Store, Hardware + Section { + ForEach([Sidebar.store, Sidebar.hardware], id: \.self) { item in + HStack { + Image(systemName: item.icon) + VStack { + Text(item.title) + Text(item.subtitle) + } + } + .tag(item) } } + // Help + Section { + HStack { + Image(systemName: Sidebar.help.icon) + VStack { + Text(Sidebar.help.title) + Text(Sidebar.help.subtitle) + } + } + .tag(Sidebar.help) + } + } + // Right (detail) + Group { + switch selection { + case .store: + SettingsDetailView() + case .hardware: + SettingsDetailView() + case .help: + SettingsDetailView() + default: + // + EmptyView() + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .toolbar { + ToolbarItem(placement: .topBarTrailing) { + Button("Done") { dismiss() } + } } + } + } + } +} + +struct SettingsDetailView: View { + var body: some View { + NavigationStack { + VStack(alignment: .leading, spacing: 12) { + Text("Some title") + .font(.title2) + Text("Content goes here.") + .foregroundStyle(.secondary) + } + .padding() + .navigationTitle("nav title") } } } From f93dada7eb4c1233dce469027c7ba987903df8b0 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 21 Aug 2025 13:54:12 +0700 Subject: [PATCH 02/15] move elements to private extension. localization --- .../PointOfSaleSettingsView.swift | 125 ++++++++++++------ 1 file changed, 85 insertions(+), 40 deletions(-) diff --git a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift index cda01c81569..e8256cef9a7 100644 --- a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift +++ b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift @@ -2,39 +2,7 @@ import SwiftUI struct PointOfSaleSettingsView: View { @Environment(\.dismiss) private var dismiss - @State private var selection: Sidebar? = .store - - enum Sidebar: String, CaseIterable, Identifiable { - case store - case hardware - case help - - var id: Self { self } - - var title: String { - switch self { - case .store: return "Store" - case .hardware: return "Hardware" - case .help: return "Help" - } - } - - var subtitle: String { - switch self { - case .store: return "Store configuration and settings" - case .hardware: return "Manage hardware connections" - case .help: return "Get help and support" - } - } - - var icon: String { - switch self { - case .store: return "bag" - case .hardware: return "wrench.and.screwdriver" - case .help: return "questionmark.circle" - } - } - } + @State private var selection: SidebarNavigation? = .store var body: some View { NavigationStack { @@ -43,7 +11,7 @@ struct PointOfSaleSettingsView: View { List(selection: $selection) { // Store, Hardware Section { - ForEach([Sidebar.store, Sidebar.hardware], id: \.self) { item in + ForEach([SidebarNavigation.store, SidebarNavigation.hardware], id: \.self) { item in HStack { Image(systemName: item.icon) VStack { @@ -57,13 +25,13 @@ struct PointOfSaleSettingsView: View { // Help Section { HStack { - Image(systemName: Sidebar.help.icon) + Image(systemName: SidebarNavigation.help.icon) VStack { - Text(Sidebar.help.title) - Text(Sidebar.help.subtitle) + Text(SidebarNavigation.help.title) + Text(SidebarNavigation.help.subtitle) } } - .tag(Sidebar.help) + .tag(SidebarNavigation.help) } } // Right (detail) @@ -76,11 +44,11 @@ struct PointOfSaleSettingsView: View { case .help: SettingsDetailView() default: - // EmptyView() } } .frame(maxWidth: .infinity, maxHeight: .infinity) + .navigationTitle(Localization.navigationTitle) .toolbar { ToolbarItem(placement: .topBarTrailing) { Button("Done") { dismiss() } @@ -101,11 +69,88 @@ struct SettingsDetailView: View { .foregroundStyle(.secondary) } .padding() - .navigationTitle("nav title") } } } +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." + ) + } +} + #Preview { PointOfSaleSettingsView() } From 239a39bebcff81f90d8c09e74f45086819ca4c0e Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 21 Aug 2025 14:00:17 +0700 Subject: [PATCH 03/15] make subviews --- .../PointOfSaleSettingsView.swift | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift index e8256cef9a7..22dd4a92c55 100644 --- a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift +++ b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift @@ -38,11 +38,11 @@ struct PointOfSaleSettingsView: View { Group { switch selection { case .store: - SettingsDetailView() + PointOfSaleSettingsStoreDetailView() case .hardware: - SettingsDetailView() + PointOfSaleSettingsHardwareDetailView() case .help: - SettingsDetailView() + PointOfSaleSettingsHelpDetailView() default: EmptyView() } @@ -59,13 +59,41 @@ struct PointOfSaleSettingsView: View { } } -struct SettingsDetailView: View { +struct PointOfSaleSettingsStoreDetailView: View { var body: some View { NavigationStack { VStack(alignment: .leading, spacing: 12) { - Text("Some title") + Text("Store Settings") .font(.title2) - Text("Content goes here.") + Text("Store-related configuration") + .foregroundStyle(.secondary) + } + .padding() + } + } +} + +struct PointOfSaleSettingsHardwareDetailView: View { + var body: some View { + NavigationStack { + VStack(alignment: .leading, spacing: 12) { + Text("Hardware Settings") + .font(.title2) + Text("Hardware-related configuration") + .foregroundStyle(.secondary) + } + .padding() + } + } +} + +struct PointOfSaleSettingsHelpDetailView: View { + var body: some View { + NavigationStack { + VStack(alignment: .leading, spacing: 12) { + Text("Help Settings") + .font(.title2) + Text("Help-related configuration") .foregroundStyle(.secondary) } .padding() From a2cd1a4d092a0f0e2481590b2fdf93ec5720e34a Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 21 Aug 2025 14:24:59 +0700 Subject: [PATCH 04/15] initial POS styles --- .../POS/Presentation/PointOfSaleSettingsView.swift | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift index 22dd4a92c55..b60932462ba 100644 --- a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift +++ b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift @@ -14,9 +14,13 @@ struct PointOfSaleSettingsView: View { ForEach([SidebarNavigation.store, SidebarNavigation.hardware], id: \.self) { item in HStack { Image(systemName: item.icon) - VStack { + .font(.posBodyLargeRegular()) + VStack(alignment: .leading) { Text(item.title) + .font(.posBodyLargeRegular()) Text(item.subtitle) + .font(.posBodyMediumRegular()) + .foregroundStyle(.secondary) } } .tag(item) @@ -26,9 +30,13 @@ struct PointOfSaleSettingsView: View { Section { HStack { Image(systemName: SidebarNavigation.help.icon) - VStack { + .font(.posBodyLargeRegular()) + VStack(alignment: .leading) { Text(SidebarNavigation.help.title) + .font(.posBodyLargeRegular()) Text(SidebarNavigation.help.subtitle) + .font(.posBodyMediumRegular()) + .foregroundStyle(.secondary) } } .tag(SidebarNavigation.help) @@ -49,6 +57,7 @@ struct PointOfSaleSettingsView: View { } .frame(maxWidth: .infinity, maxHeight: .infinity) .navigationTitle(Localization.navigationTitle) + .font(.posHeadingRegular) .toolbar { ToolbarItem(placement: .topBarTrailing) { Button("Done") { dismiss() } From 0d3d6bd172e9f5ddf6c6b3d462efe895912fc6d5 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 21 Aug 2025 14:43:57 +0700 Subject: [PATCH 05/15] attempt to push Help to bottom of the view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It doesn’t seem to be straight-forward to push one of the elements of a List down to the bottom, while keeping the rest at the top, so “Help” has to be outside the List. --- .../PointOfSaleSettingsView.swift | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift index b60932462ba..27ed60268d7 100644 --- a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift +++ b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift @@ -6,28 +6,27 @@ struct PointOfSaleSettingsView: View { var body: some View { NavigationStack { - HStack(spacing: 0) { - // Left (nav) - List(selection: $selection) { - // Store, Hardware - Section { - ForEach([SidebarNavigation.store, SidebarNavigation.hardware], id: \.self) { item in - HStack { - Image(systemName: item.icon) - .font(.posBodyLargeRegular()) - VStack(alignment: .leading) { - Text(item.title) + HStack(spacing: POSSpacing.none) { + VStack { + 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) } } - // Help - Section { + .safeAreaInset(edge: .bottom) { HStack { Image(systemName: SidebarNavigation.help.icon) .font(.posBodyLargeRegular()) @@ -38,11 +37,13 @@ struct PointOfSaleSettingsView: View { .font(.posBodyMediumRegular()) .foregroundStyle(.secondary) } + Spacer() } - .tag(SidebarNavigation.help) + .padding(.vertical, POSPadding.small) + .padding(.horizontal, POSPadding.medium) + .onTapGesture { selection = .help } } } - // Right (detail) Group { switch selection { case .store: @@ -71,7 +72,7 @@ struct PointOfSaleSettingsView: View { struct PointOfSaleSettingsStoreDetailView: View { var body: some View { NavigationStack { - VStack(alignment: .leading, spacing: 12) { + VStack(alignment: .leading) { Text("Store Settings") .font(.title2) Text("Store-related configuration") @@ -85,7 +86,7 @@ struct PointOfSaleSettingsStoreDetailView: View { struct PointOfSaleSettingsHardwareDetailView: View { var body: some View { NavigationStack { - VStack(alignment: .leading, spacing: 12) { + VStack(alignment: .leading) { Text("Hardware Settings") .font(.title2) Text("Hardware-related configuration") @@ -99,7 +100,7 @@ struct PointOfSaleSettingsHardwareDetailView: View { struct PointOfSaleSettingsHelpDetailView: View { var body: some View { NavigationStack { - VStack(alignment: .leading, spacing: 12) { + VStack(alignment: .leading) { Text("Help Settings") .font(.title2) Text("Help-related configuration") From ceb4e1b8970358ae5c8b42644c6373e2dc289148 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 21 Aug 2025 15:02:29 +0700 Subject: [PATCH 06/15] wrap help section in button --- .../PointOfSaleSettingsView.swift | 38 +++++++++++++------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift index 27ed60268d7..235acb4802d 100644 --- a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift +++ b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift @@ -27,21 +27,32 @@ struct PointOfSaleSettingsView: View { } } .safeAreaInset(edge: .bottom) { - HStack { - Image(systemName: SidebarNavigation.help.icon) - .font(.posBodyLargeRegular()) - VStack(alignment: .leading) { - Text(SidebarNavigation.help.title) + Button { + selection = .help + } label: { + HStack { + Image(systemName: SidebarNavigation.help.icon) .font(.posBodyLargeRegular()) - Text(SidebarNavigation.help.subtitle) - .font(.posBodyMediumRegular()) - .foregroundStyle(.secondary) + .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() } - Spacer() + .padding(.vertical, POSPadding.small) + .padding(.horizontal, POSPadding.medium) + .contentShape(Rectangle()) } - .padding(.vertical, POSPadding.small) - .padding(.horizontal, POSPadding.medium) - .onTapGesture { selection = .help } + .buttonStyle(.plain) + .background( + RoundedRectangle(cornerRadius: POSCornerRadiusStyle.large.value, style: .continuous) + .fill(selection == .help ? Color.accentColor : Color.clear) + ) } } Group { @@ -76,6 +87,7 @@ struct PointOfSaleSettingsStoreDetailView: View { Text("Store Settings") .font(.title2) Text("Store-related configuration") + .font(.caption) .foregroundStyle(.secondary) } .padding() @@ -90,6 +102,7 @@ struct PointOfSaleSettingsHardwareDetailView: View { Text("Hardware Settings") .font(.title2) Text("Hardware-related configuration") + .font(.caption) .foregroundStyle(.secondary) } .padding() @@ -104,6 +117,7 @@ struct PointOfSaleSettingsHelpDetailView: View { Text("Help Settings") .font(.title2) Text("Help-related configuration") + .font(.caption) .foregroundStyle(.secondary) } .padding() From 96edc8e8fec2b868c7a9c52f0e6d074ea93a6c8d Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 21 Aug 2025 15:20:14 +0700 Subject: [PATCH 07/15] nav stack for hardware details view We also remove the navigation stack from the settings view as a parent, otherwise is part of the nav stack, and presenting any other destination would cover it full-screen. We only make the details right-side part of the nav stack instead. --- .../PointOfSaleSettingsView.swift | 180 +++++++++++------- 1 file changed, 115 insertions(+), 65 deletions(-) diff --git a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift index 235acb4802d..aa80b0ba321 100644 --- a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift +++ b/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift @@ -5,75 +5,73 @@ struct PointOfSaleSettingsView: View { @State private var selection: SidebarNavigation? = .store var body: some View { - NavigationStack { - HStack(spacing: POSSpacing.none) { - VStack { - 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(spacing: POSSpacing.none) { + VStack { + List(selection: $selection) { + Section { + ForEach([SidebarNavigation.store, SidebarNavigation.hardware], id: \.self) { item in HStack { - Image(systemName: SidebarNavigation.help.icon) + Image(systemName: item.icon) .font(.posBodyLargeRegular()) - .foregroundStyle(selection == .help ? .white : .primary) VStack(alignment: .leading) { - Text(SidebarNavigation.help.title) + Text(item.title) .font(.posBodyLargeRegular()) - .foregroundStyle(selection == .help ? .white : .primary) - Text(SidebarNavigation.help.subtitle) + Text(item.subtitle) .font(.posBodyMediumRegular()) - .foregroundStyle(selection == .help ? .secondary : .secondary) + .foregroundStyle(.secondary) } - Spacer() } - .padding(.vertical, POSPadding.small) - .padding(.horizontal, POSPadding.medium) - .contentShape(Rectangle()) + .tag(item) } - .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() + .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) + ) } - .frame(maxWidth: .infinity, maxHeight: .infinity) - .navigationTitle(Localization.navigationTitle) - .font(.posHeadingRegular) - .toolbar { - ToolbarItem(placement: .topBarTrailing) { - Button("Done") { dismiss() } - } + } + Group { + switch selection { + case .store: + PointOfSaleSettingsStoreDetailView() + case .hardware: + PointOfSaleSettingsHardwareDetailView() + case .help: + PointOfSaleSettingsHelpDetailView() + default: + EmptyView() + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .navigationTitle(Localization.navigationTitle) + .font(.posHeadingRegular) + .toolbar { + ToolbarItem(placement: .topBarTrailing) { + Button("Done") { dismiss() } } } } @@ -96,16 +94,38 @@ struct PointOfSaleSettingsStoreDetailView: View { } struct PointOfSaleSettingsHardwareDetailView: View { + @State private var navigationPath: [PointOfSaleSettingsView.HardwareDestination] = [] + var body: some View { - NavigationStack { - VStack(alignment: .leading) { - Text("Hardware Settings") - .font(.title2) - Text("Hardware-related configuration") - .font(.caption) - .foregroundStyle(.secondary) + 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: 4) { + Text(destination.title) + .font(.posBodyLargeRegular()) + Text(destination.subtitle) + .font(.posBodyMediumRegular()) + .foregroundStyle(.secondary) + } + } + } + } + .navigationDestination(for: PointOfSaleSettingsView.HardwareDestination.self) { destination in + VStack(spacing: 16) { + 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) } - .padding() } } } @@ -125,6 +145,36 @@ struct PointOfSaleSettingsHelpDetailView: View { } } +extension PointOfSaleSettingsView { + enum HardwareDestination: Identifiable, CaseIterable { + case cardReaders + case scanners + + var id: Self { self } + + var title: String { + switch self { + case .scanners: return "Barcode scanners" + case .cardReaders: return "Card Readers" + } + } + + var subtitle: String { + switch self { + case .scanners: return "Configure barcode scanner settings" + case .cardReaders: return "Manage card reader connections" + } + } + + var icon: String { + switch self { + case .scanners: return "qrcode.viewfinder" + case .cardReaders: return "creditcard" + } + } + } +} + private extension PointOfSaleSettingsView { enum SidebarNavigation: String, CaseIterable, Identifiable { case store From 738ab10dfd98c62962b6196d40458bce0c52deb5 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 21 Aug 2025 15:32:56 +0700 Subject: [PATCH 08/15] extract subviews to files and cleanup --- ...ointOfSaleSettingsHardwareDetailView.swift | 38 ++++++ .../PointOfSaleSettingsHelpDetailView.swift | 16 +++ .../PointOfSaleSettingsStoreDetailView.swift | 16 +++ .../PointOfSaleSettingsView.swift | 109 ++++++------------ .../WooCommerce.xcodeproj/project.pbxproj | 22 +++- 5 files changed, 127 insertions(+), 74 deletions(-) create mode 100644 WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHardwareDetailView.swift create mode 100644 WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHelpDetailView.swift create mode 100644 WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift rename WooCommerce/Classes/POS/Presentation/{ => Settings}/PointOfSaleSettingsView.swift (70%) 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/PointOfSaleSettingsView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift similarity index 70% rename from WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift rename to WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift index aa80b0ba321..d0e23526553 100644 --- a/WooCommerce/Classes/POS/Presentation/PointOfSaleSettingsView.swift +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift @@ -78,73 +78,6 @@ struct PointOfSaleSettingsView: View { } } -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() - } - } -} - -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: 4) { - Text(destination.title) - .font(.posBodyLargeRegular()) - Text(destination.subtitle) - .font(.posBodyMediumRegular()) - .foregroundStyle(.secondary) - } - } - } - } - .navigationDestination(for: PointOfSaleSettingsView.HardwareDestination.self) { destination in - VStack(spacing: 16) { - 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) - } - } - } -} - -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() - } - } -} - extension PointOfSaleSettingsView { enum HardwareDestination: Identifiable, CaseIterable { case cardReaders @@ -154,22 +87,28 @@ extension PointOfSaleSettingsView { var title: String { switch self { - case .scanners: return "Barcode scanners" - case .cardReaders: return "Card Readers" + case .cardReaders: + return Localization.hardwareNavigationCardReaderTitle + case .scanners: + return Localization.hardwareNavigationBarcodeTitle } } var subtitle: String { switch self { - case .scanners: return "Configure barcode scanner settings" - case .cardReaders: return "Manage card reader connections" + case .cardReaders: + return Localization.hardwareNavigationBarcodeSubtitle + case .scanners: + return Localization.hardwareNavigationBarcodeSubtitle } } var icon: String { switch self { - case .scanners: return "qrcode.viewfinder" - case .cardReaders: return "creditcard" + case .cardReaders: + return "creditcard" + case .scanners: + return "qrcode.viewfinder" } } } @@ -250,6 +189,30 @@ 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." + ) } } 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 */, From f89e6954dce8965f6c330f921e3a2b321f43d680 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 21 Aug 2025 16:16:44 +0700 Subject: [PATCH 09/15] move dismissal to subviews MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dismissal does not show anymore in the parent settings view since we don’t us a navigation stack, and we cannot use a navigation stack otherwise the destinations will be presented full-screen, so we move dismissal to each subview. --- .../Settings/PointOfSaleSettingsHardwareDetailView.swift | 6 ++++++ .../Settings/PointOfSaleSettingsHelpDetailView.swift | 7 +++++++ .../Settings/PointOfSaleSettingsStoreDetailView.swift | 7 +++++++ .../Presentation/Settings/PointOfSaleSettingsView.swift | 8 -------- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHardwareDetailView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHardwareDetailView.swift index aa9ea0f0225..83ede51e1b6 100644 --- a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHardwareDetailView.swift +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHardwareDetailView.swift @@ -1,6 +1,7 @@ import SwiftUI struct PointOfSaleSettingsHardwareDetailView: View { + @Environment(\.dismiss) private var dismiss @State private var navigationPath: [PointOfSaleSettingsView.HardwareDestination] = [] var body: some View { @@ -20,6 +21,11 @@ struct PointOfSaleSettingsHardwareDetailView: View { } } } + .toolbar { + ToolbarItem(placement: .topBarTrailing) { + Button("Done") { dismiss() } + } + } .navigationDestination(for: PointOfSaleSettingsView.HardwareDestination.self) { destination in VStack(spacing: POSSpacing.medium) { Image(systemName: destination.icon).font(.largeTitle) diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHelpDetailView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHelpDetailView.swift index 50ce18ccd82..01df920c508 100644 --- a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHelpDetailView.swift +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsHelpDetailView.swift @@ -1,6 +1,8 @@ import SwiftUI struct PointOfSaleSettingsHelpDetailView: View { + @Environment(\.dismiss) private var dismiss + var body: some View { NavigationStack { VStack(alignment: .leading) { @@ -11,6 +13,11 @@ struct PointOfSaleSettingsHelpDetailView: View { .foregroundStyle(.secondary) } .padding() + .toolbar { + ToolbarItem(placement: .topBarTrailing) { + Button("Done") { dismiss() } + } + } } } } diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift index 2192d786ce3..ca66ec7a5fd 100644 --- a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift @@ -1,6 +1,8 @@ import SwiftUI struct PointOfSaleSettingsStoreDetailView: View { + @Environment(\.dismiss) private var dismiss + var body: some View { NavigationStack { VStack(alignment: .leading) { @@ -11,6 +13,11 @@ struct PointOfSaleSettingsStoreDetailView: View { .foregroundStyle(.secondary) } .padding() + .toolbar { + ToolbarItem(placement: .topBarTrailing) { + Button("Done") { dismiss() } + } + } } } } diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift index d0e23526553..b1aa39a9bb2 100644 --- a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift @@ -1,7 +1,6 @@ import SwiftUI struct PointOfSaleSettingsView: View { - @Environment(\.dismiss) private var dismiss @State private var selection: SidebarNavigation? = .store var body: some View { @@ -67,13 +66,6 @@ struct PointOfSaleSettingsView: View { } } .frame(maxWidth: .infinity, maxHeight: .infinity) - .navigationTitle(Localization.navigationTitle) - .font(.posHeadingRegular) - .toolbar { - ToolbarItem(placement: .topBarTrailing) { - Button("Done") { dismiss() } - } - } } } } From d818027abd5f973a39d146905fca12f26ee61dec Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 21 Aug 2025 16:43:21 +0700 Subject: [PATCH 10/15] restore header navigationTitle --- .../Presentation/Settings/PointOfSaleSettingsView.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift index b1aa39a9bb2..f1e4118bb92 100644 --- a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift @@ -5,7 +5,12 @@ struct PointOfSaleSettingsView: View { var body: some View { HStack(spacing: POSSpacing.none) { - VStack { + VStack(alignment: .leading, spacing: POSSpacing.none) { + Text(Localization.navigationTitle) + .font(.posHeadingRegular) + .padding(.horizontal, POSPadding.medium) + .padding(.top, POSPadding.medium) + List(selection: $selection) { Section { ForEach([SidebarNavigation.store, SidebarNavigation.hardware], id: \.self) { item in From 71ade8c2100c367c2a2579585326094d6c144bd4 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 21 Aug 2025 16:45:38 +0700 Subject: [PATCH 11/15] fix unused string --- .../POS/Presentation/Settings/PointOfSaleSettingsView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift index f1e4118bb92..8cdf5365f41 100644 --- a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsView.swift @@ -94,7 +94,7 @@ extension PointOfSaleSettingsView { var subtitle: String { switch self { case .cardReaders: - return Localization.hardwareNavigationBarcodeSubtitle + return Localization.hardwareNavigationCardReaderSubtitle case .scanners: return Localization.hardwareNavigationBarcodeSubtitle } From 8fd076be2e0c9477708fbd4132a212b1caf04149 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Fri, 22 Aug 2025 09:49:49 +0700 Subject: [PATCH 12/15] update store details --- .../PointOfSaleSettingsStoreDetailView.swift | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift index ca66ec7a5fd..92a4d47ec2d 100644 --- a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift @@ -3,12 +3,39 @@ import SwiftUI struct PointOfSaleSettingsStoreDetailView: View { @Environment(\.dismiss) private var dismiss + var storeName: String { + guard let site = ServiceLocator.stores.sessionManager.defaultSite else { + return "Not set" + } + return site.name + } + + var storeAddress: String { + SiteAddress().address + } + + var storeEmail: String { + "Not set" // TBD + } + var body: some View { NavigationStack { VStack(alignment: .leading) { - Text("Store Settings") + Text("Store Information") .font(.title2) - Text("Store-related configuration") + + Text("Store name") + Text(storeName) + .font(.caption) + .foregroundStyle(.secondary) + + Text("Address") + Text(storeAddress) + .font(.caption) + .foregroundStyle(.secondary) + + Text("Email") + Text(storeEmail) .font(.caption) .foregroundStyle(.secondary) } @@ -21,3 +48,8 @@ struct PointOfSaleSettingsStoreDetailView: View { } } } + + +#Preview { + PointOfSaleSettingsStoreDetailView() +} From 023d0d1b02a04da446af8a60d7d6a267d9208313 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Fri, 22 Aug 2025 10:31:03 +0700 Subject: [PATCH 13/15] check for woo version when rendering store receipts --- .../PointOfSaleSettingsStoreDetailView.swift | 98 +++++++++++++++---- 1 file changed, 81 insertions(+), 17 deletions(-) diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift index 92a4d47ec2d..03ee797ddfb 100644 --- a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift @@ -1,7 +1,9 @@ +import Yosemite import SwiftUI struct PointOfSaleSettingsStoreDetailView: View { @Environment(\.dismiss) private var dismiss + @State private var shouldShowReceiptInformation = false var storeName: String { guard let site = ServiceLocator.stores.sessionManager.defaultSite else { @@ -21,23 +23,57 @@ struct PointOfSaleSettingsStoreDetailView: View { var body: some View { NavigationStack { VStack(alignment: .leading) { - Text("Store Information") - .font(.title2) - - Text("Store name") - Text(storeName) - .font(.caption) - .foregroundStyle(.secondary) - - Text("Address") - Text(storeAddress) - .font(.caption) - .foregroundStyle(.secondary) - - Text("Email") - Text(storeEmail) - .font(.caption) - .foregroundStyle(.secondary) + Group { + Text("Store Information") + .font(.title2) + + Text("Store name") + Text(storeName) + .font(.caption) + .foregroundStyle(.secondary) + + Text("Address") + Text(storeAddress) + .font(.caption) + .foregroundStyle(.secondary) + + Text("Email") + Text(storeEmail) + .font(.caption) + .foregroundStyle(.secondary) + } + + Group { + Spacer() + Text("Receipt Information") + .font(.title2) + Text("Store name") + Text("WIP") + .font(.caption) + .foregroundStyle(.secondary) + + Text("Physical address") + Text("WIP") + .font(.caption) + .foregroundStyle(.secondary) + + Text("Phone number") + Text("WIP") + .font(.caption) + .foregroundStyle(.secondary) + + Text("Email") + Text("WIP") + .font(.caption) + .foregroundStyle(.secondary) + + Text("Refund & Returns Policy") + Text("WIP") + .font(.caption) + .foregroundStyle(.secondary) + + } + .renderedIf(shouldShowReceiptInformation) } .padding() .toolbar { @@ -46,6 +82,34 @@ struct PointOfSaleSettingsStoreDetailView: View { } } } + .task { + shouldShowReceiptInformation = await isPluginSupported(.wooCommerce, minimumVersion: "10.0") + /** + TODO - WOOMOB-1160: retrieval for woocommerce_pos_ settings + woocommerce_pos_store_name + woocommerce_pos_store_address + woocommerce_pos_store_phone + woocommerce_pos_store_email + woocommerce_pos_refund_returns_policy + */ + } + } +} + +private extension PointOfSaleSettingsStoreDetailView { + @MainActor + func isPluginSupported(_ plugin: Plugin, minimumVersion: String) async -> Bool { + let siteID = ServiceLocator.stores.sessionManager.defaultSite?.siteID ?? 0 + let storageManager = ServiceLocator.storageManager + let pluginsService = PluginsService(storageManager: storageManager) + guard let systemPlugin = pluginsService.loadPluginInStorage(siteID: siteID, plugin: plugin, isActive: true), + systemPlugin.active else { + return false + } + + let isSupported = VersionHelpers.isVersionSupported(version: systemPlugin.version, + minimumRequired: minimumVersion) + return isSupported } } From 95da679ed1b539cefd1679c72743b3e1141453dc Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Fri, 22 Aug 2025 10:31:13 +0700 Subject: [PATCH 14/15] enable ff for dev --- Modules/Sources/Experiments/DefaultFeatureFlagService.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Sources/Experiments/DefaultFeatureFlagService.swift b/Modules/Sources/Experiments/DefaultFeatureFlagService.swift index e434670d3c9..2767ae50941 100644 --- a/Modules/Sources/Experiments/DefaultFeatureFlagService.swift +++ b/Modules/Sources/Experiments/DefaultFeatureFlagService.swift @@ -104,7 +104,7 @@ public struct DefaultFeatureFlagService: FeatureFlagService { case .pointOfSaleBarcodeScanningi2: return true case .pointOfSaleSettingsi1: - return false + return buildConfig == .localDeveloper || buildConfig == .alpha case .orderAddressMapSearch: return true default: From 8e62676c3e8fef3c6216085f0a60ffbae446d399 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Mon, 25 Aug 2025 10:56:22 +0700 Subject: [PATCH 15/15] fetch pos settings --- .../PointOfSaleSettingsStoreDetailView.swift | 55 ++++++++++++++----- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift index 03ee797ddfb..7ce33e6b0eb 100644 --- a/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift +++ b/WooCommerce/Classes/POS/Presentation/Settings/PointOfSaleSettingsStoreDetailView.swift @@ -4,6 +4,8 @@ import SwiftUI struct PointOfSaleSettingsStoreDetailView: View { @Environment(\.dismiss) private var dismiss @State private var shouldShowReceiptInformation = false + @State private var posSettings: PointOfSaleSettings = .empty + @State private var isLoadingSettings = true var storeName: String { guard let site = ServiceLocator.stores.sessionManager.defaultSite else { @@ -42,33 +44,33 @@ struct PointOfSaleSettingsStoreDetailView: View { .font(.caption) .foregroundStyle(.secondary) } - + Group { Spacer() Text("Receipt Information") .font(.title2) Text("Store name") - Text("WIP") + Text(isLoadingSettings ? "Loading..." : posSettings.storeName) .font(.caption) .foregroundStyle(.secondary) Text("Physical address") - Text("WIP") + Text(isLoadingSettings ? "Loading..." : posSettings.storeAddress) .font(.caption) .foregroundStyle(.secondary) Text("Phone number") - Text("WIP") + Text(isLoadingSettings ? "Loading..." : posSettings.storePhone) .font(.caption) .foregroundStyle(.secondary) Text("Email") - Text("WIP") + Text(isLoadingSettings ? "Loading..." : posSettings.storeEmail) .font(.caption) .foregroundStyle(.secondary) Text("Refund & Returns Policy") - Text("WIP") + Text(isLoadingSettings ? "Loading..." : posSettings.refundReturnsPolicy) .font(.caption) .foregroundStyle(.secondary) @@ -84,18 +86,43 @@ struct PointOfSaleSettingsStoreDetailView: View { } .task { shouldShowReceiptInformation = await isPluginSupported(.wooCommerce, minimumVersion: "10.0") - /** - TODO - WOOMOB-1160: retrieval for woocommerce_pos_ settings - woocommerce_pos_store_name - woocommerce_pos_store_address - woocommerce_pos_store_phone - woocommerce_pos_store_email - woocommerce_pos_refund_returns_policy - */ + } + .task { + let siteID = ServiceLocator.stores.sessionManager.defaultSite?.siteID ?? 0 + let action = SettingAction.retrievePointOfSaleSettings(siteID: siteID) { result in + switch result { + case .success(let siteSettings): + self.posSettings = PointOfSaleSettings(from: siteSettings) + self.isLoadingSettings = false + case .failure(let error): + DDLogError("Failed to load POS settings: \(error)") + self.posSettings = .empty + self.isLoadingSettings = false + } + } + ServiceLocator.stores.dispatch(action) } } } +struct PointOfSaleSettings { + let storeName: String + let storeAddress: String + let storePhone: String + let storeEmail: String + let refundReturnsPolicy: String + + init(from siteSettings: [SiteSetting]) { + self.storeName = siteSettings.first { $0.settingID == "woocommerce_pos_store_name" }?.value ?? "Not set" + self.storeAddress = siteSettings.first { $0.settingID == "woocommerce_pos_store_address" }?.value ?? "Not set" + self.storePhone = siteSettings.first { $0.settingID == "woocommerce_pos_store_phone" }?.value ?? "Not set" + self.storeEmail = siteSettings.first { $0.settingID == "woocommerce_pos_store_email" }?.value ?? "Not set" + self.refundReturnsPolicy = siteSettings.first { $0.settingID == "woocommerce_pos_refund_returns_policy" }?.value ?? "Not set" + } + + static let empty = PointOfSaleSettings(from: []) +} + private extension PointOfSaleSettingsStoreDetailView { @MainActor func isPluginSupported(_ plugin: Plugin, minimumVersion: String) async -> Bool {