From 60c27ce919774b6bd911f961e0bac9f9cbd3cea4 Mon Sep 17 00:00:00 2001 From: Marek Piasecki Date: Thu, 12 Jan 2023 13:29:58 +0100 Subject: [PATCH] processing bookings into 'free time' slots --- src/api/bookings.json | 10 +++++ src/api/bookings_2023_02_01.json | 9 ++++ src/router.imba | 4 +- src/ui/choose-slot.imba | 71 ++++++++++++++++++++++++++++++++ src/ui/date-input.imba | 5 ++- src/ui/plus-minus.imba | 11 ++++- src/ui/slot-size-input.imba | 7 ++-- src/views/choose-slot.imba | 2 + 8 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 src/api/bookings.json create mode 100644 src/api/bookings_2023_02_01.json create mode 100644 src/ui/choose-slot.imba diff --git a/src/api/bookings.json b/src/api/bookings.json new file mode 100644 index 0000000..70dfa41 --- /dev/null +++ b/src/api/bookings.json @@ -0,0 +1,10 @@ +[ + { "id": "8c73d0ca-d999-4081-1558-e5ee6a40fcc2", "start": "2023-01-31T23:00:00.000Z", "end": "2023-02-01T06:00:00.000Z" }, + { "id": "4b24e6ab-bdc6-6b2c-e405-a8e01f0fde84", "start": "2023-02-01T09:00:00.000Z", "end": "2023-02-01T10:00:00.000Z" }, + { "id": "086e3a96-2c74-3d2a-e839-ad10c82626d5", "start": "2023-02-01T10:15:00.000Z", "end": "2023-02-01T10:45:00.000Z" }, + { "id": "087ddebe-dd41-7e39-bda8-f617d8c4385d", "start": "2023-02-01T11:30:00.000Z", "end": "2023-02-01T13:00:00.000Z" }, + { "id": "5117e557-8d86-4180-9326-1ce0cf733982", "start": "2023-02-01T13:00:00.000Z", "end": "2023-02-01T13:10:00.000Z" }, + { "id": "9e323a9e-adf9-605f-9386-c939a9a6af3f", "start": "2023-02-01T13:55:00.000Z", "end": "2023-02-01T14:30:00.000Z" }, + { "id": "bd8fc476-ac50-3327-4ece-d73897796852", "start": "2023-02-01T20:00:00.000Z", "end": "2023-02-01T22:30:00.000Z" }, + { "id": "0510de47-c86e-a64c-bb86-461c039b1012", "start": "2023-02-02T10:00:00.000Z", "end": "2023-02-02T20:00:00.000Z" } +] diff --git a/src/api/bookings_2023_02_01.json b/src/api/bookings_2023_02_01.json new file mode 100644 index 0000000..df30412 --- /dev/null +++ b/src/api/bookings_2023_02_01.json @@ -0,0 +1,9 @@ +[ + { "id": "8c73d0ca-d999-4081-1558-e5ee6a40fcc2", "start": "2023-01-31T23:00:00.000Z", "end": "2023-02-01T06:00:00.000Z" }, + { "id": "4b24e6ab-bdc6-6b2c-e405-a8e01f0fde84", "start": "2023-02-01T09:00:00.000Z", "end": "2023-02-01T10:00:00.000Z" }, + { "id": "086e3a96-2c74-3d2a-e839-ad10c82626d5", "start": "2023-02-01T10:15:00.000Z", "end": "2023-02-01T10:45:00.000Z" }, + { "id": "087ddebe-dd41-7e39-bda8-f617d8c4385d", "start": "2023-02-01T11:30:00.000Z", "end": "2023-02-01T13:00:00.000Z" }, + { "id": "5117e557-8d86-4180-9326-1ce0cf733982", "start": "2023-02-01T13:00:00.000Z", "end": "2023-02-01T13:10:00.000Z" }, + { "id": "9e323a9e-adf9-605f-9386-c939a9a6af3f", "start": "2023-02-01T13:55:00.000Z", "end": "2023-02-01T14:30:00.000Z" }, + { "id": "bd8fc476-ac50-3327-4ece-d73897796852", "start": "2023-02-01T20:00:00.000Z", "end": "2023-02-01T22:30:00.000Z" } +] diff --git a/src/router.imba b/src/router.imba index 31d24fc..d7605e2 100644 --- a/src/router.imba +++ b/src/router.imba @@ -21,8 +21,8 @@ global css body jc@portrait:flex-end .active filter:hue-rotate(45deg) bxs:md .clickable us:none cursor@hover:pointer o@hover:0.7 tween:opacity 300ms - .bordered bd: 2px solid violet5 rd: 10px - .bordered-complex > bdr: 2px solid violet5 bdl: 2px solid violet5 + .bordered bd:2px solid violet5 rd:10px + .bordered-complex > bd: 2px solid violet5 bdy:none @first bdt:2px solid violet6 rd:20px 20px 0 0 @last bdb:2px solid violet6 rd:0 0 20px 20px diff --git a/src/ui/choose-slot.imba b/src/ui/choose-slot.imba new file mode 100644 index 0000000..7384289 --- /dev/null +++ b/src/ui/choose-slot.imba @@ -0,0 +1,71 @@ +import bookings from "../api/bookings_2023_02_01.json" # bookings.where ending_date >= $date and starting_date <= $date sort b sort_by starting_date + +# make objects +for booking in bookings + booking.start = new Date(booking.start) + booking.end = new Date(booking.end) + +import sh from "../ui/slot-size-input.imba" + +let h = + resolution: 15minutes + date: do R.param('alt-day') || R.param('date') + next_day: do + return #next_day if #next_day + let day = new Date(h.date!) + day.setDate(day.getDate! + 1) + #next_day = day + + slots: do + #slots ||= h.calculate_slots! + + calculate_slots: do + let slots = [] + unless bookings.length + slots.push start: h.date!, end: h.next_day! + else + let first = bookings[0] + if first.start > h.date! + slots.push start: h.date!, end: first.start + + bookings.forEach do |booking,i| + let next = bookings[i+1] + if next + slots.push start: booking.end, end: next.start + + let last = bookings[-1] + + if last.end < h.next_day! + slots.push start: last.end, end: h.next_day! + + for slot in slots + h.adjust(slot, 'start') + h.adjust(slot, 'end') + + slot['duration'] = h.calculate_duration(slot) for slot in slots + slots + + adjust: do |slot, param| + let min = Number(slot[param]) + let min_mod = min % h.resolution + if min_mod != 0 + slot[param] = new Date(min + ( param == 'start' ? h.resolution : 0 ) - min_mod) + + calculate_duration: do |slot| + Number(slot.end) - Number(slot.start) + + duration: do + h._duration ||= h.calculate_duration end: R.param('size'), start: sh.zero! + +tag choose-slot + def render + h._duration = 0 # reset cache + + if h.slots!.length + for d in h.slots! + if d.duration > h.duration! +

"{d.end}" + else +

"No slot available this day" + + \ No newline at end of file diff --git a/src/ui/date-input.imba b/src/ui/date-input.imba index 8a28361..fdc46bd 100644 --- a/src/ui/date-input.imba +++ b/src/ui/date-input.imba @@ -44,4 +44,7 @@ tag date-input - \ No newline at end of file + +tag simple-date-input + + \ No newline at end of file diff --git a/src/ui/plus-minus.imba b/src/ui/plus-minus.imba index 2351b01..3f5d91c 100644 --- a/src/ui/plus-minus.imba +++ b/src/ui/plus-minus.imba @@ -4,7 +4,7 @@ tag plus-minus prop incr prop decr - css m: 10px + css m:10px > miw:50px h:50px p:19px 5px 0 ta:center fs:180% @@ -19,4 +19,11 @@ tag plus-minus-plus tag plus-minus-minus prop decr - '-' \ No newline at end of file + '-' + +tag plus-minus-v < plus-minus + css d:flex fld:row-reverse fs:x-small + > bd:1.8px solid violet5 bdx:none p:25px 7px 0 0 + @first bdr:1.8px rd:0 20px 20px 0 + @last bdl:1.8px rd:20px 0 0 20px + \ No newline at end of file diff --git a/src/ui/slot-size-input.imba b/src/ui/slot-size-input.imba index 85059bb..d9cea06 100644 --- a/src/ui/slot-size-input.imba +++ b/src/ui/slot-size-input.imba @@ -1,11 +1,11 @@ import './plus-minus.imba' let h = - zero: do new Date(0) + zero: do new Date("1.01.1970") max_size: do #ms ||= R.getters.size "3_0_0", 1 # 3 days validate: do |s| - return R.getters.size("0_0_5", 1) if s < h.zero! + return R.getters.size("0_0_5", 1) if s <= h.zero! return new Date(h.max_size!) if s > h.max_size! s @@ -49,4 +49,5 @@ tag slot-size-input if h.days! > 0 - \ No newline at end of file + + \ No newline at end of file diff --git a/src/views/choose-slot.imba b/src/views/choose-slot.imba index 7d6352b..25d7eb9 100644 --- a/src/views/choose-slot.imba +++ b/src/views/choose-slot.imba @@ -1,5 +1,6 @@ import sh from "../ui/slot-size-input.imba" import "../ui/action-button.imba" +import "../ui/choose-slot.imba" tag view-choose-slot @@ -10,6 +11,7 @@ tag view-choose-slot + "Book slot"