Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
0e02cf2
Develop a compact version of ItemListErrorCardView to use in smaller …
staskus Sep 10, 2025
126066e
Allow configuring PointOfSaleItemListEmptyView with a protocol
staskus Sep 10, 2025
03b624c
Create PointOfSaleOrderListEmptyViewModel
staskus Sep 10, 2025
19ed405
Adjust PointOfSaleOrderListView to properly display empty and error v…
staskus Sep 10, 2025
60e85e1
Create previews for various PointOfSaleOrderListView states
staskus Sep 11, 2025
d0c3ed0
Remove unused code
staskus Sep 11, 2025
23ff8e9
Further adjustments to compact ItemListErrorCardView design
staskus Sep 11, 2025
2ba8654
Rename empty, error, and inlineError views to indicate reusability
staskus Sep 11, 2025
c267a93
Add padding to PointOfSaleOrderListView
staskus Sep 11, 2025
15003d1
Updated empty view when there are no orders loaded
staskus Sep 11, 2025
14d8703
Remove search button if orders don't exist
staskus Sep 11, 2025
b28a188
Remove errorImage
staskus Sep 11, 2025
4544006
Merge branch 'trunk' into woomob-1136-woo-poshistorical-orders-order-…
staskus Sep 15, 2025
ea6e0df
Add fullscreen error view of PointOfSaleOrderListView
staskus Sep 15, 2025
57ca0df
Remove unnecessary VStack
staskus Sep 15, 2025
32085af
Extract a list view into a separate view
staskus Sep 15, 2025
1b37a57
PointOfSaleItemListEmptyViewModel -> POSListEmptyViewModel
staskus Sep 15, 2025
d3f2e23
Merge branch 'trunk' into woomob-1136-woo-poshistorical-orders-order-…
staskus Sep 15, 2025
b8ef8ca
Rename PointOfSaleOrderList to POSOrderList
staskus Sep 15, 2025
b6996cd
Update Previews
staskus Sep 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import SwiftUI

struct PointOfSaleItemListEmptyView: View {
protocol POSEmptyViewModelProtocol {
var title: String { get }
var subtitle: String { get }
var hint: String? { get }
var buttonTitle: String? { get }
var iconName: String { get }
}

struct POSListEmptyView: View {
@Environment(\.dynamicTypeSize) private var dynamicTypeSize
@Environment(\.floatingControlAreaSize) private var floatingControlAreaSize: CGSize
private let viewModel: PointOfSaleItemListEmptyViewModel
private let viewModel: any POSEmptyViewModelProtocol

private let onAction: (() -> Void)?

@State private var viewWidth: CGFloat = 0

@Environment(\.keyboardObserver) private var keyboard

init(viewModel: PointOfSaleItemListEmptyViewModel, onAction: (() -> Void)? = nil) {
init(viewModel: any POSEmptyViewModelProtocol, onAction: (() -> Void)? = nil) {
self.viewModel = viewModel
self.onAction = onAction
}
Expand Down Expand Up @@ -84,7 +92,7 @@ struct PointOfSaleItemListEmptyView: View {
}
}

private extension PointOfSaleItemListEmptyView {
private extension POSListEmptyView {
enum Constants {
static let iconSize: CGFloat = 88
}
Expand Down Expand Up @@ -243,7 +251,7 @@ struct PointOfSaleItemListEmptyViewModel {
// MARK: - Preview

#Preview {
PointOfSaleItemListEmptyView(
POSListEmptyView(
viewModel: PointOfSaleItemListEmptyViewModel(
itemListType: .coupons(search: false),
baseItem: .root
Expand All @@ -252,10 +260,14 @@ struct PointOfSaleItemListEmptyViewModel {
}

#Preview {
PointOfSaleItemListEmptyView(
POSListEmptyView(
viewModel: PointOfSaleItemListEmptyViewModel(
itemListType: .products(search: true),
baseItem: .root
)
) {}
}

// MARK: - Protocol Conformance

extension PointOfSaleItemListEmptyViewModel: POSEmptyViewModelProtocol {}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct PointOfSaleItemListFullscreenErrorView: View {

var body: some View {
PointOfSaleItemListFullscreenView {
PointOfSaleItemListErrorView(error: error, onAction: onAction)
POSListErrorView(error: error, onAction: onAction)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ private enum Localization {
#Preview {
PointOfSaleItemListFullscreenView(
content: {
PointOfSaleItemListErrorView(
POSListErrorView(
error: .init(errorType: .productsLoadError, title: "Error", subtitle: "Something went wrong", buttonText: "Fix it"))
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private extension ChildItemList {
var emptyView: some View {
VStack {
headerView
PointOfSaleItemListEmptyView(
POSListEmptyView(
viewModel: PointOfSaleItemListEmptyViewModel(
itemListType: .products(search: false),
baseItem: node)) {
Expand All @@ -106,7 +106,7 @@ private extension ChildItemList {
Spacer()
}

PointOfSaleItemListErrorView(error: error, onAction: {
POSListErrorView(error: error, onAction: {
Task {
await itemsController.loadItems(base: node)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ struct ItemList<HeaderView: View>: View {
GhostItemCardView()
}
case .inlineError(_, let errorState, .pagination):
ItemListErrorCardView(errorState: errorState,
POSListInlineErrorView(errorState: errorState,
buttonAction: {
Task { @MainActor in
await itemsController.loadNextItems(base: node)
Expand All @@ -127,7 +127,7 @@ struct ItemList<HeaderView: View>: View {
@ViewBuilder var headerRows: some View {
switch state {
case .inlineError(_, let errorState, .refresh):
ItemListErrorCardView(errorState: errorState,
POSListInlineErrorView(errorState: errorState,
buttonAction: {
Task { @MainActor in
await itemsController.loadItems(base: .root)
Expand Down

This file was deleted.

8 changes: 4 additions & 4 deletions WooCommerce/Classes/POS/Presentation/ItemListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ private extension ItemListView {
var emptyView: some View {
switch selectedItemListType {
case .products:
PointOfSaleItemListEmptyView(
POSListEmptyView(
viewModel: PointOfSaleItemListEmptyViewModel(
itemListType: selectedItemListType,
baseItem: .root)) {
Expand All @@ -302,7 +302,7 @@ private extension ItemListView {
}
}
case .coupons:
PointOfSaleItemListEmptyView(
POSListEmptyView(
viewModel: PointOfSaleItemListEmptyViewModel(
itemListType: selectedItemListType,
baseItem: .root)) {
Expand All @@ -315,14 +315,14 @@ private extension ItemListView {
func errorView(_ errorState: PointOfSaleErrorState) -> some View {
switch errorState.errorType {
case .couponsDisabled:
PointOfSaleItemListErrorView(error: errorState, onAction: {
POSListErrorView(error: errorState, onAction: {
Task {
await posModel.couponsController.enableCoupons()
ServiceLocator.analytics.track(.couponSettingEnabled)
}
})
default:
PointOfSaleItemListErrorView(error: errorState, onAction: {
POSListErrorView(error: errorState, onAction: {
Task {
await itemsController(selectedItemListType).loadItems(base: .root)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@ import SwiftUI

struct PointOfSaleOrderDetailsEmptyView: View {
var body: some View {
// TODO: WOOMOB-1136
VStack(spacing: 0) {
POSPageHeaderView(
title: "Orders",
title: Localization.title,
backButtonConfiguration: nil
)

VStack {
Spacer()
Text("No Orders Loaded")

Text(Localization.noOrderToDisplay)
.font(.posBodyLargeRegular())
.foregroundStyle(Color.posOnSurfaceVariantHighest)
.multilineTextAlignment(.center)

Spacer()
}
}
Expand All @@ -22,6 +24,20 @@ struct PointOfSaleOrderDetailsEmptyView: View {
}
}

private enum Localization {
static let title = NSLocalizedString(
"pos.orderDetailsEmptyView.ordersTitle",
value: "Order",
comment: "Title at the header for the Order Details empty view."
)

static let noOrderToDisplay = NSLocalizedString(
"pos.orderDetailsEmptyView.noOrderToDisplay",
value: "No order to display",
comment: "Text appearing in the order details pane when there are no orders available."
)
}

#if DEBUG
#Preview {
PointOfSaleOrderDetailsEmptyView()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import Foundation

struct POSOrderListEmptyViewModel: POSListEmptyViewModelProtocol {
let isSearching: Bool

var title: String {
isSearching ? Localization.emptyOrdersSearchTitle : Localization.emptyOrdersTitle
}

var subtitle: String {
isSearching ? Localization.emptyOrdersSearchSubtitle : Localization.emptyOrdersSubtitle
}

var hint: String? {
isSearching ? Localization.emptyOrdersSearchHint : nil
}

var buttonTitle: String? {
isSearching ? nil : Localization.emptyOrdersButtonTitle
}

var iconName: String {
PointOfSaleAssets.magnifierNotFound.imageName
}
}

private enum Localization {
static let emptyOrdersTitle = NSLocalizedString(
"pos.orderListView.emptyOrdersTitle",
value: "No orders yet",
comment: "Title appearing when there are no orders to display."
)

static let emptyOrdersSubtitle = NSLocalizedString(
"pos.orderListView.emptyOrdersSubtitle",
value: "Orders will appear here once you start processing sales on the POS.",
comment: "Subtitle appearing when there are no orders to display."
)

static let emptyOrdersButtonTitle = NSLocalizedString(
"pos.orderListView.emptyOrdersButtonTitle",
value: "Refresh",
comment: "Button text for refreshing orders when list is empty."
)

static let emptyOrdersSearchTitle = NSLocalizedString(
"pos.orderListView.emptyOrdersSearchTitle",
value: "No orders found",
comment: "Title appearing when order search returns no results."
)

static let emptyOrdersSearchSubtitle = NSLocalizedString(
"pos.orderListView.emptyOrdersSearchSubtitle",
value: "We couldn't find any orders matching your search.",
comment: "Subtitle appearing when order search returns no results."
)

static let emptyOrdersSearchHint = NSLocalizedString(
"pos.orderListView.emptyOrdersSearchHint",
value: "Try adjusting your search term.",
comment: "Hint text suggesting to modify search terms when no orders are found."
)
}
Loading