Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Expand Up @@ -27,6 +27,7 @@ final class BookingDetailsViewModel: ObservableObject {

@Published private(set) var navigationTitle = ""
@Published private(set) var sections: [Section] = []
@Published var notice: Notice?

var bookingAttendanceStatus: BookingAttendanceStatus {
booking.attendanceStatus
Expand Down Expand Up @@ -233,14 +234,32 @@ extension BookingDetailsViewModel {
siteID: booking.siteID,
bookingID: booking.bookingID,
status: newStatus
) { error in
if let error {
) { [weak self] error in
if let error, let self {
DDLogError("⛔️ Error updating booking attendance status: \(error)")
// TODO: Show an error notice to the user
displayAttendanceStatusUpdatedErrorNotice(status: newStatus)
}
}
stores.dispatch(action)
}

private func displayAttendanceStatusUpdatedErrorNotice(status: BookingAttendanceStatus) {
let text = String.localizedStringWithFormat(
Localization.bookingAttendanceStatusUpdateFailedMessage,
booking.bookingID
)
self.notice = Notice(
message: text,
feedbackType: .error,
actionTitle: Localization.retryActionTitle
) { [weak self] in
guard let self else {
return
}

updateAttendanceStatus(to: status)
}
}
}

private extension BookingDetailsViewModel {
Expand Down Expand Up @@ -362,5 +381,19 @@ private extension BookingDetailsViewModel {
value: "%1$@ will no longer be able to attend “%2$@” on %3$@.",
comment: "Message for the booking cancellation confirmation alert. %1$@ is customer name, %2$@ is product name, %3$@ is booking date."
)

static let bookingAttendanceStatusUpdateFailedMessage = NSLocalizedString(
"BookingDetailsView.attendanceStatus.updateFailed.message",
value: "Unable to change attendance status of Booking #%1$d",
comment: "Content of error presented when updating the attendance status of a Booking fails. "
+ "It reads: Unable to change status of Booking #{Booking number}. "
+ "Parameters: %1$d - Booking number"
)

static let retryActionTitle = NSLocalizedString(
"BookingDetailsView.retry.action",
value: "Retry",
comment: "Retry Action"
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ struct BookingDetailsView: View {
Text(viewModel.cancellationAlertMessage)
}
.notice($notice)
.notice($viewModel.notice)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,42 @@ final class BookingDetailsViewModelTests: XCTestCase {
XCTAssertEqual(status, newStatus)
}

func test_error_notice_displayed_when_attendance_staus_update_fails() {
// Given
let booking = Booking.fake()
let viewModel = BookingDetailsViewModel(booking: booking, stores: storesManager)
let newStatus = BookingAttendanceStatus.checkedIn
enum TestError: Error { case generic }

// When
viewModel.updateAttendanceStatus(to: newStatus)

// Then
XCTAssertEqual(storesManager.receivedActions.count, 1)
guard let action = storesManager.receivedActions.first as? BookingAction else {
XCTFail("Incorrect action type dispatched")
return
}

guard case let .updateBookingAttendanceStatus(_, _, _, onCompletion) = action else {
XCTFail("Incorrect action case dispatched")
return
}

onCompletion(TestError.generic)

XCTAssertNotNil(viewModel.notice)
XCTAssertEqual(viewModel.notice?.feedbackType, .error)

let messageFormat = NSLocalizedString(
"BookingDetailsView.attendanceStatus.updateFailed.message",
value: "Unable to change attendance status of Booking #%1$d",
comment: ""
)
let expectedMessage = String(format: messageFormat, booking.bookingID)
XCTAssertEqual(viewModel.notice?.message, expectedMessage)
}

func test_init_whenBookingHasStatusAndAttendanceStatus_updatesHeaderContentWithCorrectLocalizedStrings() {
// Given
let booking = Booking.fake().copy(
Expand Down
Loading