Skip to content

Commit 0cac69a

Browse files
committed
Make network call
1 parent 5a7449f commit 0cac69a

File tree

8 files changed

+138
-10
lines changed

8 files changed

+138
-10
lines changed

Modules/Sources/Networking/Remote/BookingsRemote.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ public protocol BookingsRemoteProtocol {
2020
from siteID: Int64,
2121
bookingID: Int64,
2222
attendanceStatus: BookingAttendanceStatus?,
23-
bookingStatus: BookingStatus?
23+
bookingStatus: BookingStatus?,
24+
note: String?
2425
) async throws -> Booking?
2526

2627
func fetchResource(resourceID: Int64,
@@ -152,7 +153,8 @@ public final class BookingsRemote: Remote, BookingsRemoteProtocol {
152153
from siteID: Int64,
153154
bookingID: Int64,
154155
attendanceStatus: BookingAttendanceStatus?,
155-
bookingStatus: BookingStatus?
156+
bookingStatus: BookingStatus?,
157+
note: String?
156158
) async throws -> Booking? {
157159
let path = "\(Path.bookings)/\(bookingID)"
158160
var parameters: [String: String] = [:]
@@ -165,6 +167,10 @@ public final class BookingsRemote: Remote, BookingsRemoteProtocol {
165167
parameters[ParameterKey.status] = bookingStatus.rawValue
166168
}
167169

170+
if let note {
171+
parameters[ParameterKey.note] = note
172+
}
173+
168174
let request = JetpackRequest(
169175
wooApiVersion: .wcBookings,
170176
method: .put,
@@ -259,5 +265,6 @@ public extension BookingsRemote {
259265
static let attendanceStatus = "attendance_status"
260266
static let paymentStatus = "booking_status" // to be updated later when payment filtering is supported
261267
static let status: String = "status"
268+
static let note: String = "note"
262269
}
263270
}

Modules/Sources/WooFoundationCore/Analytics/WooAnalyticsStat.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,6 @@ public enum WooAnalyticsStat: String {
617617
case interacRefundCanceled = "interac_refund_cancelled"
618618

619619
// MARK: Push Notifications Events
620-
//
621620
case pushNotificationReceived = "push_notification_received"
622621
case pushNotificationAlertPressed = "push_notification_alert_pressed"
623622
case pushNotificationOSAlertAllowed = "push_notification_os_alert_allowed"

Modules/Sources/Yosemite/Actions/BookingAction.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,16 @@ public enum BookingAction: Action {
9191
case markBookingAsPaid(siteID: Int64,
9292
bookingID: Int64,
9393
onCompletion: (Error?) -> Void)
94+
95+
/// Updates a booking attendance status.
96+
///
97+
/// - Parameter siteID: The site ID of the booking.
98+
/// - Parameter bookingID: The ID of the booking to be updated.
99+
/// - Parameter note: The new note.
100+
/// - Parameter onCompletion: called when update completes, returns an error in case of a failure.
101+
///
102+
case updateBookingNote(siteID: Int64,
103+
bookingID: Int64,
104+
note: String,
105+
onCompletion: (Error?) -> Void)
94106
}

Modules/Sources/Yosemite/Stores/BookingStore.swift

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ public class BookingStore: Store {
8282
bookingID: bookingID,
8383
onCompletion: onCompletion
8484
)
85+
case .updateBookingNote(let siteID, let bookingID, let note, let onCompletion):
86+
updateBookingNote(
87+
siteID: siteID,
88+
bookingID: bookingID,
89+
note: note,
90+
onCompletion: onCompletion
91+
)
8592
}
8693
}
8794
}
@@ -308,6 +315,7 @@ private extension BookingStore {
308315
bookingID: bookingID,
309316
attendanceStatus: status,
310317
bookingStatus: nil,
318+
note: nil,
311319
) {
312320
await self.upsertStoredBookingsInBackground(
313321
readOnlyBookings: [remoteBooking],
@@ -333,6 +341,54 @@ private extension BookingStore {
333341
}
334342
}
335343

344+
func updateBookingNote(
345+
siteID: Int64,
346+
bookingID: Int64,
347+
note: String,
348+
onCompletion: @escaping (Error?) -> Void
349+
) {
350+
updateBookingNoteLocally(
351+
siteID: siteID,
352+
bookingID: bookingID,
353+
note: note
354+
) { [weak self] previousNote in
355+
guard let self else {
356+
return onCompletion(UpdateBookingStatusError.undefinedState)
357+
}
358+
359+
Task { @MainActor in
360+
do {
361+
if let remoteBooking = try await self.remote.updateBooking(
362+
from: siteID,
363+
bookingID: bookingID,
364+
attendanceStatus: nil,
365+
bookingStatus: nil,
366+
note: note,
367+
) {
368+
await self.upsertStoredBookingsInBackground(
369+
readOnlyBookings: [remoteBooking],
370+
readOnlyOrders: [],
371+
siteID: siteID
372+
)
373+
374+
onCompletion(nil)
375+
} else {
376+
return onCompletion(UpdateBookingStatusError.missingRemoteBooking)
377+
}
378+
} catch {
379+
/// Revert Optimistic Update
380+
self.updateBookingNoteLocally(
381+
siteID: siteID,
382+
bookingID: bookingID,
383+
note: note
384+
) { _ in
385+
onCompletion(error)
386+
}
387+
}
388+
}
389+
}
390+
}
391+
336392
/// Updates local (Storage) Booking attendance status
337393
func updateBookingAttendanceStatusLocally(
338394
siteID: Int64,
@@ -361,6 +417,33 @@ private extension BookingStore {
361417
}, on: .main)
362418
}
363419

420+
func updateBookingNoteLocally(
421+
siteID: Int64,
422+
bookingID: Int64,
423+
note: String?,
424+
onCompletion: @escaping (String?) -> Void
425+
) {
426+
storageManager.performAndSave({ storage -> String? in
427+
guard let booking = storage.loadBooking(
428+
siteID: siteID,
429+
bookingID: bookingID
430+
) else {
431+
return note
432+
}
433+
434+
let oldNote = booking.note
435+
booking.note = note
436+
return oldNote
437+
}, completion: { result in
438+
switch result {
439+
case .success(let status):
440+
onCompletion(status)
441+
case .failure:
442+
onCompletion(note)
443+
}
444+
}, on: .main)
445+
}
446+
364447
/// Cancels a booking by updating its status to cancelled.
365448
func cancelBooking(
366449
siteID: Int64,
@@ -373,7 +456,8 @@ private extension BookingStore {
373456
from: siteID,
374457
bookingID: bookingID,
375458
attendanceStatus: nil,
376-
bookingStatus: .cancelled
459+
bookingStatus: .cancelled,
460+
note: nil,
377461
) {
378462
await upsertStoredBookingsInBackground(
379463
readOnlyBookings: [remoteBooking],
@@ -403,7 +487,8 @@ private extension BookingStore {
403487
from: siteID,
404488
bookingID: bookingID,
405489
attendanceStatus: nil,
406-
bookingStatus: .paid
490+
bookingStatus: .paid,
491+
note: nil,
407492
) {
408493
await upsertStoredBookingsInBackground(
409494
readOnlyBookings: [remoteBooking],

WooCommerce/Classes/ViewModels/Booking Details/BookingDetailsViewModel.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,20 @@ extension BookingDetailsViewModel {
248248
stores.dispatch(action)
249249
}
250250

251+
func updateNote(to newNote: String) {
252+
let action = BookingAction.updateBookingNote(
253+
siteID: booking.siteID,
254+
bookingID: booking.bookingID,
255+
note: newNote
256+
) { [weak self] error in
257+
if let error, let self {
258+
DDLogError("⛔️ Error updating booking note: \(error)")
259+
// displayAttendanceStatusUpdatedErrorNotice(status: newStatus)
260+
}
261+
}
262+
stores.dispatch(action)
263+
}
264+
251265
private func displayAttendanceStatusUpdatedErrorNotice(status: BookingAttendanceStatus) {
252266
let text = String.localizedStringWithFormat(
253267
Localization.bookingAttendanceStatusUpdateFailedMessage,

WooCommerce/Classes/ViewRelated/Bookings/Booking Details/BookingDetailsView.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,9 @@ private extension BookingDetailsView {
244244
func bookingNotesView() -> some View {
245245
MultilineEditableTextRow(value: viewModel.note,
246246
placeholder: Localization.bookingNotesRowText,
247-
detailTitle: Localization.bookingNoteNavbarText)
247+
detailTitle: Localization.bookingNoteNavbarText) { newNote in
248+
viewModel.updateNote(to: newNote)
249+
}
248250
}
249251
}
250252

WooCommerce/Classes/ViewRelated/ReusableViews/SwiftUI Components/MultilineEditableTextRow/MultilineEditableTextDetailView.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ struct MultilineEditableTextDetailView: View {
99
@FocusState private var isFocused: Bool
1010

1111
let title: String?
12+
let onCommit: ((String) -> Void)?
1213

13-
init(text: Binding<String>, title: String? = nil) {
14+
init(text: Binding<String>, title: String? = nil, onCommit: ((String) -> Void)? = nil) {
1415
self._text = text
1516
self._editedText = State(initialValue: text.wrappedValue)
1617
self.title = title
18+
self.onCommit = onCommit
1719
}
1820

1921
var body: some View {
@@ -54,6 +56,7 @@ struct MultilineEditableTextDetailView: View {
5456
ToolbarItem(placement: .primaryAction) {
5557
Button(Localization.doneButtonTitle) {
5658
text = editedText
59+
onCommit?(editedText)
5760
dismiss()
5861
}
5962
.fontWeight(.medium)

WooCommerce/Classes/ViewRelated/ReusableViews/SwiftUI Components/MultilineEditableTextRow/MultilineEditableTextRow.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,22 @@ struct MultilineEditableTextRow: View {
44
@State var value: String
55
let placeholder: String
66
let detailTitle: String?
7+
let onCommit: ((String) -> Void)?
78

8-
init(value: String, placeholder: String, detailTitle: String? = nil) {
9-
self.value = value
9+
init(value: String,
10+
placeholder: String,
11+
detailTitle: String? = nil,
12+
onCommit: ((String) -> Void)? = nil
13+
) {
14+
self._value = State(initialValue: value)
1015
self.placeholder = placeholder
1116
self.detailTitle = detailTitle
17+
self.onCommit = onCommit
1218
}
1319

1420
var body: some View {
1521
NavigationLink {
16-
MultilineEditableTextDetailView(text: $value, title: detailTitle)
22+
MultilineEditableTextDetailView(text: $value, title: detailTitle, onCommit: onCommit)
1723
} label: {
1824
content
1925
}

0 commit comments

Comments
 (0)