@@ -4,11 +4,19 @@ import SwiftUI // Added for withAnimation
44
55final class BookingDetailsViewModel : ObservableObject {
66 private let stores : StoresManager
7+ private lazy var resultsController = BookingDetailsResultsController ( booking: booking)
78
89 private let booking : Booking
910 private let headerContent : HeaderContent
1011 private let customerContent = CustomerContent ( )
11- private( set) var order : Order ?
12+ private( set) var order : Order ? {
13+ didSet {
14+ guard let order else {
15+ return
16+ }
17+ updateCustomerInfo ( from: order)
18+ }
19+ }
1220
1321 let navigationTitle : String
1422 @Published private( set) var sections : [ Section ] = [ ]
@@ -19,9 +27,14 @@ final class BookingDetailsViewModel: ObservableObject {
1927 self . headerContent = HeaderContent ( booking)
2028 navigationTitle = Self . navigationTitle ( for: booking)
2129 setupSections ( )
30+ configureResultsController ( )
2231 }
32+ }
33+
34+ // MARK: Private
2335
24- private func setupSections( ) {
36+ private extension BookingDetailsViewModel {
37+ func setupSections( ) {
2538 let headerSection = Section (
2639 content: . header( headerContent)
2740 )
@@ -55,151 +68,76 @@ final class BookingDetailsViewModel: ObservableObject {
5568 bookingNotes
5669 ]
5770 }
58- }
5971
60- // MARK: Local Data
72+ func configureResultsController( ) {
73+ resultsController. configure { [ weak self] in
74+ self ? . order = self ? . resultsController. order
75+ }
76+ self . order = resultsController. order
77+ }
6178
62- extension BookingDetailsViewModel {
63- func loadLocalData( ) {
64- loadCustomerData ( )
79+ func updateCustomerInfo( from order: Order ) {
80+ guard let billingAddress = order. billingAddress else {
81+ return
82+ }
83+
84+ customerContent. update ( with: billingAddress)
85+ headerContent. update ( with: billingAddress)
86+ insertCustomerSectionIfAbsent ( )
6587 }
66- }
6788
68- private extension BookingDetailsViewModel {
69- func loadCustomerData ( ) {
70- guard booking . customerID > 0 else {
89+ func insertCustomerSectionIfAbsent ( ) {
90+ // Avoid adding if it already exists
91+ guard !sections . contains ( where : { if case . customer = $0 . content { return true } else { return false } } ) else {
7192 return
7293 }
7394
74- let action = CustomerAction . loadCustomer ( siteID: booking. siteID, customerID: booking. customerID) { [ weak self] result in
75- guard let self = self else { return }
76- if case . success( let customer) = result {
77- Task {
78- await self . updateCustomerSection ( with: customer)
79- await self . updateHeader ( with: customer)
80- }
81- }
95+ let customerSection = Section (
96+ header: . title( Localization . customerSectionHeaderTitle. uppercased ( ) ) ,
97+ content: . customer( customerContent)
98+ )
99+ withAnimation {
100+ sections. insert ( customerSection, at: 2 )
82101 }
83- stores. dispatch ( action)
84102 }
85103}
86104
87105// MARK: Syncing
88106
89107extension BookingDetailsViewModel {
90108 func syncData( ) async {
91- await withTaskGroup ( of: Void . self) { group in
92- group. addTask { await self . syncCustomer ( ) }
93- group. addTask { await self . syncOrder ( ) }
94- }
109+ await syncOrder ( )
95110 }
96111}
97112
98113private extension BookingDetailsViewModel {
99- func syncCustomer( ) async {
100- guard shouldSyncCustomer else {
101- return
102- }
103-
104- do {
105- let fetchedCustomer = try await retrieveCustomer ( )
106- await updateCustomerSection ( with: fetchedCustomer)
107- await updateHeader ( with: fetchedCustomer)
108- } catch {
109- DDLogError ( " ⛔️ Error synchronizing Customer for Booking: \( error) " )
110- }
111- }
112-
113114 func syncOrder( ) async {
114115 guard booking. orderID > 0 else {
115116 return
116117 }
117118
118119 do {
119- let fetchedOrder = try await retrieveOrder ( )
120- await MainActor . run {
121- self . order = fetchedOrder
122- }
120+ try await fetchRemoteOrder ( )
123121 } catch {
124122 DDLogError ( " ⛔️ Error synchronizing Order for Booking: \( error) " )
125123 }
126124 }
127125
128126 @MainActor
129- func retrieveCustomer( ) async throws -> Customer {
130- try await withCheckedThrowingContinuation { continuation in
131- let action = CustomerAction . retrieveCustomer (
132- siteID: booking. siteID,
133- customerID: booking. customerID
134- ) { result in
135- switch result {
136- case . success( let customer) :
137- continuation. resume ( returning: customer)
138- case . failure( let error) :
139- continuation. resume ( throwing: error)
140- }
141- }
142- stores. dispatch ( action)
143- }
144- }
145-
146- @MainActor
147- func retrieveOrder( ) async throws -> Order {
148- enum OrderSyncError : Error {
149- case unknown
150- }
151-
127+ func fetchRemoteOrder( ) async throws {
152128 return try await withCheckedThrowingContinuation { continuation in
153129 let action = OrderAction . retrieveOrder (
154130 siteID: booking. siteID,
155131 orderID: booking. orderID
156- ) { order, error in
157- if let order = order {
158- continuation. resume ( returning: order)
159- } else if let error = error {
132+ ) { _, error in
133+ if let error {
160134 continuation. resume ( throwing: error)
161- } else {
162- continuation. resume ( throwing: OrderSyncError . unknown)
163135 }
136+ continuation. resume ( returning: ( ) )
164137 }
165138 stores. dispatch ( action)
166139 }
167140 }
168-
169- @MainActor
170- func updateCustomerSection( with customer: Customer ) {
171- if let billingAddress = customer. billing {
172- customerContent. update ( with: billingAddress)
173- }
174- insertCustomerSectionIfAbsent ( )
175- }
176-
177- @MainActor
178- func updateHeader( with customer: Customer ) {
179- if let billingAddress = customer. billing {
180- headerContent. update ( with: billingAddress)
181- }
182- }
183-
184- func insertCustomerSectionIfAbsent( ) {
185- // Avoid adding if it already exists
186- guard !sections. contains ( where: { if case . customer = $0. content { return true } else { return false } } ) else {
187- return
188- }
189-
190- let customerSection = Section (
191- header: . title( Localization . customerSectionHeaderTitle. uppercased ( ) ) ,
192- content: . customer( customerContent)
193- )
194- withAnimation {
195- sections. insert ( customerSection, at: 2 )
196- }
197- }
198-
199- /// Returns true when the `customerID` is non-zero and customer section doesn't exist
200- var shouldSyncCustomer : Bool {
201- return booking. customerID > 0
202- }
203141}
204142
205143extension BookingDetailsViewModel {
0 commit comments