@getoccasion/sdk
Version:
An SDK library that enables access to Occasion's application, providing a rich DSL for creating and managing bookings.
168 lines (140 loc) • 4.18 kB
JavaScript
// @todo Remove includes({ product: 'merchant' }) when AR supports owner assignment to has_many children
// in non-load queries
Occasion.__constructCalendar = function __constructCalendar(
month,
{
calendar,
monthlyTimeSlotDaysBatchSize,
monthlyTimeSlotPreloadSize,
preload,
prevPagePromise,
relation,
status,
timeZone
} = {}
) {
var today = moment.tz(timeZone)
status = status || 'bookable'
var lowerRange
if (month) {
lowerRange = month.tz(timeZone)
} else {
lowerRange = today
}
lowerRange = lowerRange.startOf('month')
var upperRange = lowerRange.clone().endOf('month')
var numRequests = Math.ceil(upperRange.diff(lowerRange, 'days') / monthlyTimeSlotDaysBatchSize)
if (numRequests < 1) numRequests = 1
var i = 0
var requests = []
var lower = lowerRange.clone()
var upper = lowerRange.clone().add(monthlyTimeSlotDaysBatchSize, 'days')
while (i < numRequests) {
if (i + 1 == numRequests) upper = upperRange.clone()
requests.push(
relation
.includes({
product: 'merchant'
})
.where({
startsAt: {
ge: lower.toDate(),
le: upper.toDate()
},
status
})
.all()
)
lower.add(monthlyTimeSlotDaysBatchSize, 'days')
upper.add(monthlyTimeSlotDaysBatchSize, 'days')
i++
}
calendar = calendar || {}
if (_.isUndefined(calendar.__currentPage)) calendar.__currentPage = 0
if (_.isUndefined(calendar.__preloadedPages)) calendar.__preloadedPages = 0
calendar.__preloading = true
var currentPromise = Promise.all(requests).then(function(timeSlotsArray) {
var allTimeSlots = ActiveResource.Collection.build(timeSlotsArray)
.map(function(ts) {
return ts.toArray()
})
.flatten()
let startDate = moment(lowerRange).startOf('month')
let endDate = moment(lowerRange).endOf('month')
var response = ActiveResource.CollectionResponse.build()
let day = startDate
while (day.isSameOrBefore(endDate)) {
response.push({
day,
timeSlots: allTimeSlots.select(timeSlot => {
return timeSlot.startsAt.isSame(day, 'day')
})
})
day = day.clone().add(1, 'days')
}
response.hasNextPage = function() {
return true
}
let commonPaginationOptions = {
calendar,
monthlyTimeSlotDaysBatchSize,
monthlyTimeSlotPreloadSize,
relation,
status,
timeZone
}
response.nextPage = function(preloadCount) {
if (!this.nextPromise) {
this.nextPromise = Occasion.__constructCalendar(
moment(upperRange)
.add(1, 'days')
.startOf('month'),
{
...commonPaginationOptions,
preload: preloadCount,
prevPagePromise: currentPromise
}
)
}
if (_.isUndefined(preloadCount)) {
calendar.__currentPage += 1
if (
!calendar.__preloading &&
calendar.__preloadedPages <= calendar.__currentPage + monthlyTimeSlotPreloadSize / 2
) {
calendar.__lastPreloadedPage.nextPage(monthlyTimeSlotPreloadSize)
}
}
return this.nextPromise
}
if (status !== 'bookable' || (month && !month.isSame(today, 'month'))) {
response.hasPrevPage = function() {
return true
}
response.prevPage = function() {
this.prevPromise =
this.prevPromise ||
prevPagePromise ||
Occasion.__constructCalendar(moment(lowerRange).subtract(1, 'months'), {
...commonPaginationOptions,
preload: 0
})
calendar.__currentPage -= 1
return this.prevPromise
}
}
if (monthlyTimeSlotPreloadSize > 0) {
if (_.isUndefined(preload)) {
response.nextPage(monthlyTimeSlotPreloadSize - 1)
} else if (preload > 0) {
response.nextPage(--preload)
} else {
calendar.__preloading = false
}
}
calendar.__preloadedPages += 1
calendar.__lastPreloadedPage = response
return response
})
return currentPromise
}