-
Notifications
You must be signed in to change notification settings - Fork 121
[POS Refunds] Order details button #16414
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ struct POSOrderDetailsView: View { | |
| @Environment(\.siteTimezone) private var siteTimezone | ||
| @Environment(POSOrderListModel.self) private var orderListModel | ||
| @Environment(\.posAnalytics) private var analytics | ||
| @Environment(\.posFeatureFlags) private var featureFlags | ||
| @State private var isShowingEmailReceiptView: Bool = false | ||
|
|
||
| private var shouldShowBackButton: Bool { | ||
|
|
@@ -32,9 +33,7 @@ struct POSOrderDetailsView: View { | |
| title: POSOrderListView.Localization.orderTitle(order.number), | ||
| backButtonConfiguration: shouldShowBackButton ? .init(state: .enabled, action: onBack) : nil, | ||
| trailingContent: { | ||
| if actions.isNotEmpty { | ||
| actionsSection(actions) | ||
| } | ||
| actionsSection(actions: availableActions) | ||
| }, | ||
| bottomContent: { | ||
| headerBottomContent(for: order) | ||
|
|
@@ -377,59 +376,98 @@ private extension POSOrderDetailsView { | |
|
|
||
| // MARK: - Actions | ||
| private extension POSOrderDetailsView { | ||
| enum POSOrderDetailsAction: Identifiable, CaseIterable { | ||
| enum POSAction: Identifiable, CaseIterable { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this rename necessary? It makes the |
||
| case issueRefund | ||
| case emailReceipt | ||
|
|
||
| var id: String { title } | ||
|
|
||
| var title: String { | ||
| switch self { | ||
| case .emailReceipt: | ||
| Localization.emailReceiptActionTitle | ||
| case .issueRefund: Localization.issueRefundActionTitle | ||
| case .emailReceipt: Localization.emailReceiptActionTitle | ||
| } | ||
| } | ||
|
|
||
| var accessibilityHint: String { | ||
| switch self { | ||
| case .issueRefund: Localization.issueRefundAccessibilityHint | ||
| case .emailReceipt: Localization.emailReceiptAccessibilityHint | ||
| } | ||
| } | ||
|
|
||
| var priority: Int { | ||
| switch self { | ||
| case .issueRefund: 100 | ||
| case .emailReceipt: 50 | ||
| } | ||
| } | ||
|
|
||
| func available(for order: POSOrder) -> Bool { | ||
| func isAvailable(for order: POSOrder, flags: POSFeatureFlagProviding) -> Bool { | ||
| guard order.status == .completed else { return false } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| switch self { | ||
| case .issueRefund: | ||
| return flags.isFeatureFlagEnabled(.pointOfSaleRefundsi1) | ||
| case .emailReceipt: | ||
| order.status == .completed | ||
| return true | ||
| } | ||
| } | ||
| } | ||
|
|
||
| func handler(for action: POSAction) -> @MainActor () -> Void { | ||
| switch action { | ||
| case .emailReceipt: | ||
| return { | ||
| analytics.track(event: WooAnalyticsEvent.PointOfSale.orderDetailsEmailReceiptTapped()) | ||
| isShowingEmailReceiptView = true | ||
| } | ||
| case .issueRefund: | ||
| return { } | ||
| } | ||
| } | ||
|
|
||
| var actions: [POSOrderDetailsAction] { | ||
| POSOrderDetailsAction.allCases.filter { $0.available(for: order) } | ||
| var availableActions: [POSAction] { | ||
| POSAction.allCases | ||
| .filter { $0.isAvailable(for: order, flags: featureFlags) } | ||
| .sorted { $0.priority > $1.priority } | ||
| } | ||
|
|
||
| @ViewBuilder | ||
| func actionsSection(_ actions: [POSOrderDetailsAction]) -> some View { | ||
| VStack { | ||
| HStack { | ||
| ForEach(actions) { action in | ||
| Button(action: { | ||
| switch action { | ||
| case .emailReceipt: | ||
| analytics.track(event: WooAnalyticsEvent.PointOfSale.orderDetailsEmailReceiptTapped()) | ||
| isShowingEmailReceiptView = true | ||
| func actionsSection(actions: [POSAction]) -> some View { | ||
| if actions.isEmpty { | ||
| EmptyView() | ||
| } else { | ||
| HStack(spacing: POSSpacing.large) { | ||
| let primary = actions[0] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's be explicit on which action is triggering rather than rely on array order, using the specific enum case or others. |
||
| Button(primary.title, action: handler(for: primary)) | ||
| .buttonStyle(POSFilledButtonStyle(size: .extraSmall)) | ||
| .accessibilityHint(primary.accessibilityHint) | ||
| .lineLimit(1) | ||
| .minimumScaleFactor(0.5) | ||
|
|
||
| let overflow = actions.dropFirst() | ||
| if !overflow.isEmpty { | ||
| Menu { | ||
| ForEach(Array(overflow)) { action in | ||
|
Comment on lines
+448
to
+451
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure to understand this bit, could you clarify what it does? Why are we dropping the first result when rendering the menu options? |
||
| Button(action.title, action: handler(for: action)) | ||
| .accessibilityHint(action.accessibilityHint) | ||
| } | ||
| }) { | ||
| Text(Localization.emailReceiptActionTitle) | ||
| .lineLimit(1) | ||
| .minimumScaleFactor(0.5) | ||
| } label: { | ||
| Image(systemName: "ellipsis") | ||
| .font(.posBodyLargeBold) | ||
| .dynamicTypeSize(...DynamicTypeSize.accessibility2) | ||
| .foregroundColor(.posOnSurface) | ||
| .padding(POSPadding.small) | ||
| } | ||
| .buttonStyle(POSFilledButtonStyle(size: .extraSmall)) | ||
| .accessibilityHint(accessibilityHint(for: action)) | ||
| .menuIndicator(.hidden) | ||
| } | ||
| } | ||
| Spacer() | ||
| } | ||
| } | ||
|
|
||
| private func accessibilityHint(for action: POSOrderDetailsAction) -> String { | ||
| switch action { | ||
| case .emailReceipt: | ||
| return Localization.emailReceiptAccessibilityHint | ||
| } | ||
| func emailReceiptAction() { | ||
| analytics.track(event: WooAnalyticsEvent.PointOfSale.orderDetailsEmailReceiptTapped()) | ||
| isShowingEmailReceiptView = true | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -529,6 +567,24 @@ private enum Localization { | |
| comment: "Accessibility hint for email receipt button on order details view" | ||
| ) | ||
|
|
||
| static let issueRefundActionTitle = NSLocalizedString( | ||
| "pos.orderDetailsView.issueRefundAction.title", | ||
| value: "Issue refund", | ||
| comment: "Primary action button to start issuing a refund on the order details view" | ||
| ) | ||
|
|
||
| static let issueRefundAccessibilityHint = NSLocalizedString( | ||
| "pos.orderDetailsView.issueRefundAction.accessibilityHint", | ||
| value: "Start refund flow for this order", | ||
| comment: "Accessibility hint for issue refund button" | ||
| ) | ||
|
|
||
| static let moreActionsA11yLabel = NSLocalizedString( | ||
| "pos.orderDetailsView.moreActions.label", | ||
| value: "More actions", | ||
| comment: "Accessibility label for the overflow actions menu button (three dots)" | ||
| ) | ||
|
|
||
| static func headerBottomContentAccessibilityLabel(date: String, email: String?, status: String) -> String { | ||
| let baseFormat = NSLocalizedString( | ||
| "pos.orderDetailsView.headerBottomContent.accessibilityLabel", | ||
|
|
||

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not necessarily for this PR, but we should move this logic either up to the model or to a helper so can be tested that we're rendering the correct buttons for all order status cases with feature flag on/off.