Skip to content

Commit 3b04ef0

Browse files
authored
Bookings: Persist booking filters (#16316)
2 parents 78fd82f + 69be33e commit 3b04ef0

File tree

14 files changed

+498
-18
lines changed

14 files changed

+498
-18
lines changed

Modules/Sources/Networking/Model/Bookings/Booking.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ enum BookingDecodingError: Error {
216216
//
217217

218218
/// Represents a Booking Status.
219-
public enum BookingStatus: String, CaseIterable {
219+
public enum BookingStatus: String, CaseIterable, Codable {
220220
case complete
221221
case paid
222222
case unpaid
@@ -226,7 +226,7 @@ public enum BookingStatus: String, CaseIterable {
226226
case unknown
227227
}
228228

229-
public enum BookingAttendanceStatus: String, CaseIterable {
229+
public enum BookingAttendanceStatus: String, CaseIterable, Codable {
230230
case booked
231231
case checkedIn = "checked-in"
232232
case cancelled

Modules/Sources/Yosemite/Actions/AppSettingsAction.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,22 @@ public enum AppSettingsAction: Action {
105105
/// Clears all the product filter history for a given site
106106
case resetProductFilterHistory(siteID: Int64, onCompletion: (Error?) -> Void)
107107

108+
// MARK: - Bookings Filters
109+
110+
/// Loads the booking filters
111+
///
112+
case loadBookingFilters(siteID: Int64, onCompletion: (Result<StoredBookingFilters.Filters, Error>) -> Void)
113+
114+
/// Add or Update booking filters
115+
///
116+
case upsertBookingFilters(siteID: Int64,
117+
filters: StoredBookingFilters.Filters,
118+
onCompletion: (Error?) -> Void)
119+
120+
/// Clears all the booking filters
121+
///
122+
case resetBookingFilters
123+
108124
// MARK: - General App Settings
109125

110126
/// Saves the `date` as the last known date that the app was installed. This does not do

Modules/Sources/Yosemite/Model/Bookings/BookingCustomerFilter.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import Foundation
44
///
55
public struct BookingCustomerFilter: Codable, Hashable {
66
/// ID of the customer
7-
/// periphery:ignore - to be used later when applying filter
87
///
98
public let customerID: Int64
109

Modules/Sources/Yosemite/Model/Bookings/BookingProductFilter.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import Foundation
44
///
55
public struct BookingProductFilter: Codable, Hashable {
66
/// ID of the product
7-
/// periphery:ignore - to be used later when applying filter
87
///
98
public let productID: Int64
109

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import Foundation
2+
3+
/// Used to filter bookings by team members
4+
///
5+
public struct BookingTeamMemberFilter: Codable, Hashable {
6+
/// ID of the team member (booking resource)
7+
///
8+
public let resourceID: Int64
9+
10+
/// Name of the team member
11+
///
12+
public let name: String
13+
14+
public init(resourceID: Int64, name: String) {
15+
self.resourceID = resourceID
16+
self.name = name
17+
}
18+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import Foundation
2+
import Codegen
3+
4+
/// Models a dictionary of `siteID` and Booking Filters
5+
/// These entities will be serialised to a plist file
6+
///
7+
public struct StoredBookingFilters: Codable, Equatable, GeneratedFakeable {
8+
9+
/// SiteID: Booking Filters
10+
public let filters: [Int64: Filters]
11+
12+
public init(filters: [Int64: Filters]) {
13+
self.filters = filters
14+
}
15+
16+
public struct Filters: Codable, Equatable {
17+
public let teamMembers: [BookingTeamMemberFilter]
18+
public let products: [BookingProductFilter]
19+
public let attendanceStatuses: [BookingAttendanceStatus]
20+
public let paymentStatuses: [BookingStatus]
21+
public let customers: [BookingCustomerFilter]
22+
public let dateRange: BookingDateRangeFilter?
23+
public let numberOfActiveFilters: Int
24+
25+
public init(teamMembers: [BookingTeamMemberFilter],
26+
products: [BookingProductFilter],
27+
attendanceStatuses: [BookingAttendanceStatus],
28+
paymentStatuses: [BookingStatus],
29+
customers: [BookingCustomerFilter],
30+
dateRange: BookingDateRangeFilter?) {
31+
self.teamMembers = teamMembers
32+
self.products = products
33+
self.attendanceStatuses = attendanceStatuses
34+
self.paymentStatuses = paymentStatuses
35+
self.customers = customers
36+
self.dateRange = dateRange
37+
self.numberOfActiveFilters = {
38+
var total = 0
39+
if teamMembers.isNotEmpty {
40+
total += 1
41+
}
42+
if products.isNotEmpty {
43+
total += 1
44+
}
45+
if attendanceStatuses.isNotEmpty {
46+
total += 1
47+
}
48+
if customers.isNotEmpty {
49+
total += 1
50+
}
51+
if paymentStatuses.isNotEmpty {
52+
total += 1
53+
}
54+
if dateRange != nil {
55+
total += 1
56+
}
57+
58+
return total
59+
}()
60+
}
61+
}
62+
}

Modules/Sources/Yosemite/Stores/AppSettingsStore.swift

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ public class AppSettingsStore: Store {
8383
return documents!.appendingPathComponent(Constants.productFilterHistory)
8484
}()
8585

86+
/// URL to the plist file that we use to determine the booking filters
87+
///
88+
private lazy var bookingFiltersURL: URL = {
89+
let documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
90+
return documents!.appendingPathComponent(Constants.bookingFilters)
91+
}()
92+
8693
/// Registers for supported Actions.
8794
///
8895
override public func registerSupportedActions(in dispatcher: Dispatcher) {
@@ -179,6 +186,12 @@ public class AppSettingsStore: Store {
179186
removeFromProductFilterHistory(filter: filter, onCompletion: onCompletion)
180187
case let .resetProductFilterHistory(siteID, onCompletion):
181188
resetProductFilterHistory(siteID: siteID, onCompletion: onCompletion)
189+
case .loadBookingFilters(let siteID, let onCompletion):
190+
loadBookingFilters(siteID: siteID, onCompletion: onCompletion)
191+
case .upsertBookingFilters(let siteID, let filters, let onCompletion):
192+
upsertBookingFilters(siteID: siteID, filters: filters, onCompletion: onCompletion)
193+
case .resetBookingFilters:
194+
resetBookingFilters()
182195
case .setOrderAddOnsFeatureSwitchState(isEnabled: let isEnabled, onCompletion: let onCompletion):
183196
setOrderAddOnsFeatureSwitchState(isEnabled: isEnabled, onCompletion: onCompletion)
184197
case .loadOrderAddOnsSwitchState(onCompletion: let onCompletion):
@@ -1006,6 +1019,46 @@ private extension AppSettingsStore {
10061019
}
10071020
}
10081021

1022+
// MARK: - Booking Filters
1023+
//
1024+
private extension AppSettingsStore {
1025+
func loadBookingFilters(siteID: Int64, onCompletion: (Result<StoredBookingFilters.Filters, Error>) -> Void) {
1026+
guard let allSavedFilters: StoredBookingFilters = try? fileStorage.data(for: bookingFiltersURL),
1027+
let filtersUnwrapped = allSavedFilters.filters[siteID] else {
1028+
let error = AppSettingsStoreErrors.noBookingFilters
1029+
onCompletion(.failure(error))
1030+
return
1031+
}
1032+
1033+
onCompletion(.success(filtersUnwrapped))
1034+
}
1035+
1036+
func upsertBookingFilters(siteID: Int64, filters: StoredBookingFilters.Filters, onCompletion: (Error?) -> Void) {
1037+
var existingFilters: [Int64: StoredBookingFilters.Filters] = [:]
1038+
if let storedFilters: StoredBookingFilters = try? fileStorage.data(for: bookingFiltersURL) {
1039+
existingFilters = storedFilters.filters
1040+
}
1041+
1042+
existingFilters[siteID] = filters
1043+
1044+
let newStoredBookingFilters = StoredBookingFilters(filters: existingFilters)
1045+
do {
1046+
try fileStorage.write(newStoredBookingFilters, to: bookingFiltersURL)
1047+
onCompletion(nil)
1048+
} catch {
1049+
onCompletion(AppSettingsStoreErrors.writeBookingFilters)
1050+
}
1051+
}
1052+
1053+
func resetBookingFilters() {
1054+
do {
1055+
try fileStorage.deleteFile(at: bookingFiltersURL)
1056+
} catch {
1057+
DDLogError("⛔️ Deleting the booking filters file failed. Error: \(error)")
1058+
}
1059+
}
1060+
}
1061+
10091062
// MARK: - Store settings
10101063
//
10111064
private extension AppSettingsStore {
@@ -1423,6 +1476,8 @@ enum AppSettingsStoreErrors: Error {
14231476
case writeOrderFilterHistory
14241477
case writeProductsSettings
14251478
case writeProductFilterHistory
1479+
case noBookingFilters
1480+
case writeBookingFilters
14261481
case noEligibilityErrorInfo
14271482
}
14281483

@@ -1440,4 +1495,5 @@ private enum Constants {
14401495
static let productsSettings = "products-settings.plist"
14411496
static let orderFilterHistory = "order-filter-history.plist"
14421497
static let productFilterHistory = "product-filter-history.plist"
1498+
static let bookingFilters = "booking-filters.plist"
14431499
}

0 commit comments

Comments
 (0)