Skip to content

Commit 2e9f89b

Browse files
authored
Bookings: Fetch filtered bookings on time tabs (#16206)
2 parents 27936e8 + 2ea7c68 commit 2e9f89b

File tree

5 files changed

+329
-26
lines changed

5 files changed

+329
-26
lines changed

WooCommerce/Classes/Bookings/BookingList/BookingListContainerView.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ private extension BookingListContainerView {
8989
height: Layout.selectedTabIndicatorHeight)
9090
.offset(x: tabIndicatorOffset(containerWidth: geometry.size.width,
9191
tabCount: BookingListTab.allCases.count,
92-
selectedIndex: viewModel.selectedTab.rawValue))
92+
selectedIndex: viewModel.selectedTab.rawValue),
93+
y: -Layout.selectedTabIndicatorHeight / 2)
9394
.animation(.easeInOut(duration: 0.3), value: viewModel.selectedTab.rawValue)
9495
}
9596
}

WooCommerce/Classes/Bookings/BookingList/BookingListContainerViewModel.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ enum BookingListTab: Int, CaseIterable {
3131
case upcoming
3232
case all
3333

34+
static let utcTimeZone: TimeZone = {
35+
guard let timeZone = TimeZone(identifier: "UTC") else {
36+
fatalError("Unable to set up UTC time zone")
37+
}
38+
return timeZone
39+
}()
40+
3441
var title: String {
3542
switch self {
3643
case .today: Localization.today
@@ -39,6 +46,21 @@ enum BookingListTab: Int, CaseIterable {
3946
}
4047
}
4148

49+
func startDateBefore(currentDate: Date) -> Date? {
50+
switch self {
51+
case .today: currentDate.endOfDay(timezone: Self.utcTimeZone).addingTimeInterval(1)
52+
case .upcoming, .all: nil
53+
}
54+
}
55+
56+
func startDateAfter(currentDate: Date) -> Date? {
57+
switch self {
58+
case .today: currentDate.startOfDay(timezone: Self.utcTimeZone).addingTimeInterval(-1)
59+
case .upcoming: currentDate.endOfDay(timezone: Self.utcTimeZone)
60+
case .all: nil
61+
}
62+
}
63+
4264
private enum Localization {
4365
static let today = NSLocalizedString(
4466
"bookingListView.today",

WooCommerce/Classes/Bookings/BookingList/BookingListView.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@ struct BookingListView: View {
2424
}
2525
}
2626
.task {
27-
// Only load first page if no content is available.
28-
if viewModel.bookings.isEmpty {
29-
viewModel.loadBookings()
30-
}
27+
viewModel.loadBookings()
3128
}
3229
}
3330
}
@@ -58,7 +55,9 @@ private extension BookingListView {
5855
func bookingItem(_ booking: Booking) -> some View {
5956
VStack(spacing: 0) {
6057
VStack(alignment: .leading) {
61-
Text(booking.startDate.formatted(date: .numeric, time: .shortened))
58+
Text(booking.startDate.toString(dateStyle: .short,
59+
timeStyle: .short,
60+
timeZone: BookingListTab.utcTimeZone))
6261
.font(.body)
6362
.fontWeight(.medium)
6463
.frame(maxWidth: .infinity, alignment: .leading)

WooCommerce/Classes/Bookings/BookingList/BookingListViewModel.swift

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ final class BookingListViewModel: ObservableObject {
1111
private let type: BookingListTab
1212
private let stores: StoresManager
1313
private let storage: StorageManagerType
14+
private let currentDate: Date
15+
16+
private static let refreshCacheReason = "refresh-cache"
1417

1518
/// Keeps track of the current state of the syncing
1619
@Published private(set) var syncState: SyncState = .empty
@@ -24,22 +27,31 @@ final class BookingListViewModel: ObservableObject {
2427

2528
/// Booking ResultsController.
2629
private lazy var resultsController: ResultsController<StorageBooking> = {
27-
let predicate = NSPredicate(format: "siteID == %lld", siteID)
28-
let sortDescriptorByDate = NSSortDescriptor(key: "dateCreated", ascending: false)
30+
var predicates = [NSPredicate(format: "siteID == %lld", siteID)]
31+
if let before = type.startDateBefore(currentDate: currentDate) {
32+
predicates.append(NSPredicate(format: "startDate < %@", before as NSDate))
33+
}
34+
if let after = type.startDateAfter(currentDate: currentDate) {
35+
predicates.append(NSPredicate(format: "startDate > %@", after as NSDate))
36+
}
37+
let combinedPredicate = NSCompoundPredicate(type: .and, subpredicates: predicates)
38+
let sortDescriptorByDate = NSSortDescriptor(key: "startDate", ascending: false)
2939
let resultsController = ResultsController<StorageBooking>(storageManager: storage,
30-
matching: predicate,
40+
matching: combinedPredicate,
3141
sortedBy: [sortDescriptorByDate])
3242
return resultsController
3343
}()
3444

3545
init(siteID: Int64,
3646
type: BookingListTab,
3747
stores: StoresManager = ServiceLocator.stores,
38-
storage: StorageManagerType = ServiceLocator.storageManager) {
48+
storage: StorageManagerType = ServiceLocator.storageManager,
49+
currentDate: Date = Date()) {
3950
self.siteID = siteID
4051
self.type = type
4152
self.stores = stores
4253
self.storage = storage
54+
self.currentDate = currentDate
4355
self.paginationTracker = PaginationTracker(pageFirstIndex: pageFirstIndex)
4456

4557
configureResultsController()
@@ -60,7 +72,7 @@ final class BookingListViewModel: ObservableObject {
6072
@MainActor
6173
func onRefreshAction() async {
6274
await withCheckedContinuation { continuation in
63-
paginationTracker.resync(reason: nil) {
75+
paginationTracker.resync(reason: Self.refreshCacheReason) {
6476
continuation.resume(returning: ())
6577
}
6678
}
@@ -92,20 +104,23 @@ private extension BookingListViewModel {
92104

93105
/// Updates row view models and sync state.
94106
func updateResults() {
95-
/// TODO: update logic for fetching bookings
96-
if type == .all {
97-
bookings = resultsController.fetchedObjects
98-
} else {
99-
bookings = []
100-
}
107+
bookings = resultsController.fetchedObjects
101108
transitionToResultsUpdatedState()
102109
}
103110
}
104111

105112
extension BookingListViewModel: PaginationTrackerDelegate {
106113
func sync(pageNumber: Int, pageSize: Int, reason: String?, onCompletion: SyncCompletion?) {
107114
transitionToSyncingState()
108-
let action = BookingAction.synchronizeBookings(siteID: siteID, pageNumber: pageNumber, pageSize: pageSize) { [weak self] result in
115+
let shouldClearCache = reason == Self.refreshCacheReason
116+
let action = BookingAction.synchronizeBookings(
117+
siteID: siteID,
118+
pageNumber: pageNumber,
119+
pageSize: pageSize,
120+
startDateBefore: type.startDateBefore(currentDate: currentDate)?.ISO8601Format(),
121+
startDateAfter: type.startDateAfter(currentDate: currentDate)?.ISO8601Format(),
122+
shouldClearCache: shouldClearCache
123+
) { [weak self] result in
109124
switch result {
110125
case .success(let hasNextPage):
111126
onCompletion?(.success(hasNextPage))

0 commit comments

Comments
 (0)