@@ -16,16 +16,50 @@ final class NewOrderViewModel: ObservableObject {
1616
1717 private var cancellables : Set < AnyCancellable > = [ ]
1818
19+ enum Flow : Equatable {
20+ case creation
21+ case editing( initialOrder: Order )
22+ }
23+
24+ /// Current flow. For editing stores existing order state prior to applying any edits.
25+ ///
26+ let flow : Flow
27+
1928 /// Indicates whether user has made any changes
2029 ///
2130 var hasChanges : Bool {
22- orderSynchronizer. order != OrderFactory . emptyNewOrder
31+ switch flow {
32+ case . creation:
33+ return orderSynchronizer. order != OrderFactory . emptyNewOrder
34+ case . editing( let initialOrder) :
35+ return orderSynchronizer. order != initialOrder
36+ }
37+ }
38+
39+ /// Indicates whether view can be dismissed.
40+ ///
41+ var canBeDismissed : Bool {
42+ switch flow {
43+ case . creation: // Creation can be dismissed when there aren't changes pending to commit.
44+ return !hasChanges
45+ case . editing: // Editing can always be dismissed because changes are committed instantly.
46+ return true
47+ }
2348 }
2449
2550 /// Indicates whether the cancel button is visible.
2651 ///
2752 var shouldShowCancelButton : Bool {
28- featureFlagService. isFeatureFlagEnabled ( . splitViewInOrdersTab)
53+ featureFlagService. isFeatureFlagEnabled ( . splitViewInOrdersTab) && flow == . creation
54+ }
55+
56+ var title : String {
57+ switch flow {
58+ case . creation:
59+ return Localization . titleForNewOrder
60+ case . editing( let order) :
61+ return String . localizedStringWithFormat ( Localization . titleWithOrderNumber, order. number)
62+ }
2963 }
3064
3165 /// Active navigation bar trailing item.
@@ -46,9 +80,15 @@ final class NewOrderViewModel: ObservableObject {
4680
4781 /// Order creation date. For new order flow it's always current date.
4882 ///
49- let dateString : String = {
50- DateFormatter . mediumLengthLocalizedDateFormatter. string ( from: Date ( ) )
51- } ( )
83+ var dateString : String {
84+ switch flow {
85+ case . creation:
86+ return DateFormatter . mediumLengthLocalizedDateFormatter. string ( from: Date ( ) )
87+ case . editing( let order) :
88+ let formatter = DateFormatter . dateAndTimeFormatter
89+ return formatter. string ( from: order. dateCreated)
90+ }
91+ }
5292
5393 /// Representation of order status display properties.
5494 ///
@@ -195,17 +235,23 @@ final class NewOrderViewModel: ObservableObject {
195235 private let orderSynchronizer : OrderSynchronizer
196236
197237 init ( siteID: Int64 ,
238+ flow: Flow = . creation,
198239 stores: StoresManager = ServiceLocator . stores,
199240 storageManager: StorageManagerType = ServiceLocator . storageManager,
200241 currencySettings: CurrencySettings = ServiceLocator . currencySettings,
201242 analytics: Analytics = ServiceLocator . analytics,
202243 featureFlagService: FeatureFlagService = ServiceLocator . featureFlagService) {
203244 self . siteID = siteID
245+ self . flow = flow
204246 self . stores = stores
205247 self . storageManager = storageManager
206248 self . currencyFormatter = CurrencyFormatter ( currencySettings: currencySettings)
207249 self . analytics = analytics
208- self . orderSynchronizer = RemoteOrderSynchronizer ( siteID: siteID, stores: stores, currencySettings: currencySettings)
250+ if case let . editing( initialOrder) = flow {
251+ self . orderSynchronizer = RemoteOrderSynchronizer ( siteID: siteID, initialOrder: initialOrder, stores: stores, currencySettings: currencySettings)
252+ } else {
253+ self . orderSynchronizer = RemoteOrderSynchronizer ( siteID: siteID, initialOrder: nil , stores: stores, currencySettings: currencySettings)
254+ }
209255 self . featureFlagService = featureFlagService
210256
211257 // Set a temporary initial view model, as a workaround to avoid making it optional.
@@ -300,7 +346,7 @@ final class NewOrderViewModel: ObservableObject {
300346
301347 switch result {
302348 case . success( let newOrder) :
303- self . onOrderCreated ( newOrder)
349+ self . onFinished ( newOrder)
304350 self . trackCreateOrderSuccess ( )
305351 case . failure( let error) :
306352 self . notice = NoticeFactory . createOrderErrorNotice ( error, order: self . orderSynchronizer. order)
@@ -311,9 +357,11 @@ final class NewOrderViewModel: ObservableObject {
311357 trackCreateButtonTapped ( )
312358 }
313359
314- /// Assign this closure to be notified when a new order is created
360+ /// Assign this closure to be notified when the flow has finished.
361+ /// For creation it means that the order has been created.
362+ /// For edition it means that the merchant has finished editing the order.
315363 ///
316- var onOrderCreated : ( Order ) -> Void = { _ in }
364+ var onFinished : ( Order ) -> Void = { _ in }
317365
318366 /// Updates the order status & tracks its event
319367 ///
@@ -349,6 +397,7 @@ extension NewOrderViewModel {
349397 ///
350398 enum NavigationItem : Equatable {
351399 case create
400+ case done
352401 case loading
353402 }
354403
@@ -500,13 +549,18 @@ private extension NewOrderViewModel {
500549 /// Calculates what navigation trailing item should be shown depending on our internal state.
501550 ///
502551 func configureNavigationTrailingItem( ) {
503- Publishers . CombineLatest ( orderSynchronizer. orderPublisher, $performingNetworkRequest)
504- . map { order, performingNetworkRequest -> NavigationItem in
552+ Publishers . CombineLatest3 ( orderSynchronizer. orderPublisher, $performingNetworkRequest, Just ( flow ) )
553+ . map { order, performingNetworkRequest, flow -> NavigationItem in
505554 guard !performingNetworkRequest else {
506555 return . loading
507556 }
508557
509- return . create
558+ switch flow {
559+ case . creation:
560+ return . create
561+ case . editing:
562+ return . done
563+ }
510564 }
511565 . assign ( to: & $navigationTrailingItem)
512566 }
@@ -841,6 +895,8 @@ extension NewOrderViewModel {
841895
842896private extension NewOrderViewModel {
843897 enum Localization {
898+ static let titleForNewOrder = NSLocalizedString ( " New Order " , comment: " Title for the order creation screen " )
899+ static let titleWithOrderNumber = NSLocalizedString ( " Order #%1$@ " , comment: " Order number title. Parameters: %1$@ - order number " )
844900 static let errorMessageOrderCreation = NSLocalizedString ( " Unable to create new order " , comment: " Notice displayed when order creation fails " )
845901 static let errorMessageOrderSync = NSLocalizedString ( " Unable to load taxes for order " ,
846902 comment: " Notice displayed when taxes cannot be synced for new order " )
0 commit comments