cronofy-elements 1.42.0 → 1.44.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.yaml +31 -30
- package/Makefile +6 -12
- package/build/CronofyElements.v1.44.1.js +2 -0
- package/build/{CronofyElements.v1.42.0.js.LICENSE.txt → CronofyElements.v1.44.1.js.LICENSE.txt} +1 -1
- package/build/npm/CronofyElements.js +2 -2
- package/demo/date-time-picker.ejs +83 -23
- package/package.json +57 -57
- package/src/js/components/DateTimePicker/DateTimePicker.js +5 -0
- package/src/js/components/DateTimePicker/Details.js +5 -3
- package/src/js/components/DateTimePicker/SequencedSlotButton.js +71 -0
- package/src/js/components/DateTimePicker/SlotsList.js +6 -1
- package/src/js/components/DateTimePicker/Wrapper.js +21 -19
- package/src/js/components/DateTimePicker/contexts/status-reducer.js +30 -8
- package/src/js/components/DateTimePicker/utils/slots.js +69 -3
- package/src/js/helpers/connections.js +38 -0
- package/src/js/helpers/init.DateTimePicker.js +4 -0
- package/tests/DateTimePicker/SequencedSlotButton.test.js +130 -0
- package/tests/DateTimePicker/contexts/status-reducer.test.js +265 -67
- package/tests/DateTimePicker/dummy-data.js +277 -0
- package/tests/DateTimePicker/utils.test.js +53 -1
- package/build/CronofyElements.v1.42.0.js +0 -2
|
@@ -22,25 +22,6 @@
|
|
|
22
22
|
<div id="cronofy-date-time-picker-two"></div>
|
|
23
23
|
<hr>
|
|
24
24
|
<div class="wrapper">
|
|
25
|
-
<div class="column">
|
|
26
|
-
<h2>Consectetur adipisicing elit</h2>
|
|
27
|
-
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. <a href="/">Voluptate sed ex totam odit</a> quae hic voluptatibus, quisquam dicta animi laborum velit laboriosam, placeat suscipit tenetur voluptates! Illo tempora minus animi.</p>
|
|
28
|
-
<p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Quidem consequuntur repudiandae nesciunt, totam dicta earum deleniti magnam eveniet eligendi sunt adipisci veniam esse aliquid aperiam corporis optio fuga tempora sit!</p>
|
|
29
|
-
</div>
|
|
30
|
-
<div class="column">
|
|
31
|
-
<h2>Est deserunt non quis do quis nostrud ad exercitation proident incididunt.</h2>
|
|
32
|
-
<p>Excepturi dicta neque ut, a expedita quaerat, tempore dolor placeat quibusdam cumque ipsam cum officia voluptate, ea fuga optio necessitatibus inventore tempora?</p>
|
|
33
|
-
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Natus nisi eveniet voluptas provident esse beatae minus at error dignissimos neque? Temporibus velit numquam aut labore porro neque ipsum, deleniti a?</p>
|
|
34
|
-
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Eum sunt eligendi, error quos nulla dolorem alias corrupti iste fugiat deleniti nam unde, porro provident a voluptatem at voluptates, dolores sed!</p>
|
|
35
|
-
</div>
|
|
36
|
-
</div>
|
|
37
|
-
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Natus nisi eveniet voluptas provident esse beatae minus at error dignissimos neque? Temporibus velit numquam aut labore porro neque ipsum, deleniti a?</p>
|
|
38
|
-
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Debitis saepe maxime corporis nemo hic rerum porro in repudiandae? Libero eligendi impedit reiciendis exercitationem fuga ex eos aliquid itaque facere corrupti.</p>
|
|
39
|
-
<hr>
|
|
40
|
-
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Eum sunt eligendi, error quos nulla dolorem alias corrupti iste fugiat deleniti nam unde, porro provident a voluptatem at voluptates, dolores sed!</p>
|
|
41
|
-
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatum commodi fuga laboriosam? Quas officiis doloremque iure modi, ipsam dolore ad illum saepe et voluptatum quis tempore ullam dolor, sequi nulla!</p>
|
|
42
|
-
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Eum sunt eligendi, error quos nulla dolorem alias corrupti iste fugiat deleniti nam unde, porro provident a voluptatem at voluptates, dolores sed!</p>
|
|
43
|
-
|
|
44
25
|
<script>
|
|
45
26
|
const locale = "<%= locale %>";
|
|
46
27
|
|
|
@@ -64,10 +45,83 @@
|
|
|
64
45
|
return output.utc().format();
|
|
65
46
|
};
|
|
66
47
|
|
|
48
|
+
const sequencedAvailabilityQuery = {
|
|
49
|
+
sequence: [
|
|
50
|
+
{
|
|
51
|
+
sequence_id: "test",
|
|
52
|
+
ordinal: 1,
|
|
53
|
+
participants: [
|
|
54
|
+
{
|
|
55
|
+
required: "all",
|
|
56
|
+
members: [
|
|
57
|
+
{
|
|
58
|
+
sub: "<%= sub %>",
|
|
59
|
+
// managed_availability: true,
|
|
60
|
+
// availability_rule_ids: ["weekly_work_hours"]
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
required_duration: { minutes: 5 },
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
sequence_id: "test-1",
|
|
69
|
+
ordinal: 2,
|
|
70
|
+
participants: [
|
|
71
|
+
{
|
|
72
|
+
required: "all",
|
|
73
|
+
members: [
|
|
74
|
+
{
|
|
75
|
+
sub: "<%= sub %>",
|
|
76
|
+
// managed_availability: true,
|
|
77
|
+
// availability_rule_ids: ["weekly_work_hours"]
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
required_duration: { minutes: 45 },
|
|
83
|
+
start_interval: { minutes: 5 },
|
|
84
|
+
buffer: {
|
|
85
|
+
before: {
|
|
86
|
+
minimum: { minutes: 15 }
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
sequence_id: "test-2",
|
|
92
|
+
ordinal: 3,
|
|
93
|
+
participants: [
|
|
94
|
+
{
|
|
95
|
+
required: "all",
|
|
96
|
+
members: [
|
|
97
|
+
{
|
|
98
|
+
sub: "<%= sub %>",
|
|
99
|
+
// managed_availability: true,
|
|
100
|
+
// availability_rule_ids: ["weekly_work_hours"]
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
required_duration: { minutes: 30 },
|
|
106
|
+
start_interval: { minutes: 10 },
|
|
107
|
+
buffer: {
|
|
108
|
+
before: {
|
|
109
|
+
minimum: { minutes: 15 }
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
],
|
|
115
|
+
query_periods: [
|
|
116
|
+
{ start: slotTimes(01,"08:00"), end: slotTimes(31,"17:00") }
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
|
|
67
120
|
CronofyElements.DateTimePicker({
|
|
68
121
|
element_token: "<%= date_time_picker_token %>",
|
|
69
122
|
target_id: 'cronofy-date-time-picker',
|
|
70
123
|
api_domain:"<%= api_domain %>",
|
|
124
|
+
//availability_query: sequencedAvailabilityQuery,
|
|
71
125
|
availability_query: {
|
|
72
126
|
// response_format: "slots",
|
|
73
127
|
participants: [
|
|
@@ -152,8 +206,7 @@
|
|
|
152
206
|
],
|
|
153
207
|
required_duration: { minutes: 30 },
|
|
154
208
|
query_periods: [
|
|
155
|
-
{ start: slotTimes(1,"23:00"), end: slotTimes(
|
|
156
|
-
{ start: slotTimes(2,"23:00"), end: slotTimes(3,"01:00") }
|
|
209
|
+
{ start: slotTimes(1,"23:00"), end: slotTimes(100,"01:00") },
|
|
157
210
|
]
|
|
158
211
|
},
|
|
159
212
|
config: {
|
|
@@ -162,8 +215,15 @@
|
|
|
162
215
|
styles: {
|
|
163
216
|
prefix: "SP2",
|
|
164
217
|
colors: {
|
|
165
|
-
|
|
166
|
-
|
|
218
|
+
button: "#9977FF",
|
|
219
|
+
buttonActive: "#5088FF",
|
|
220
|
+
buttonHover: "#AACCFF",
|
|
221
|
+
buttonHoverText: "#50AAFF",
|
|
222
|
+
buttonTextHover: "#AA50FF",
|
|
223
|
+
neutralDark: "#403040",
|
|
224
|
+
neutral: "#A03040",
|
|
225
|
+
neutralLight: "#F05080",
|
|
226
|
+
|
|
167
227
|
}
|
|
168
228
|
},
|
|
169
229
|
callback: slot => console.log('callback',slot),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cronofy-elements",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.44.1",
|
|
4
4
|
"description": "Fast track scheduling with Cronofy's embeddable UI Elements",
|
|
5
5
|
"main": "build/npm/CronofyElements.js",
|
|
6
6
|
"scripts": {
|
|
@@ -45,61 +45,61 @@
|
|
|
45
45
|
"author": "",
|
|
46
46
|
"license": "ISC",
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@babel/cli": "^7.
|
|
49
|
-
"@babel/core": "^7.12
|
|
50
|
-
"@babel/plugin-proposal-class-properties": "^7.12
|
|
51
|
-
"@babel/plugin-proposal-object-rest-spread": "^7.12
|
|
52
|
-
"@babel/polyfill": "^7.12
|
|
53
|
-
"@babel/preset-env": "^7.12
|
|
54
|
-
"@babel/preset-react": "^7.12
|
|
55
|
-
"@emotion/babel-preset-css-prop": "^10.2
|
|
56
|
-
"@emotion/core": "^10.1
|
|
57
|
-
"@emotion/jest": "^11.3
|
|
58
|
-
"@testing-library/jest-dom": "^5.11
|
|
59
|
-
"@testing-library/react": "^11.2
|
|
60
|
-
"autoprefixer": "^10.2
|
|
61
|
-
"babel-eslint": "^10.1
|
|
62
|
-
"babel-loader": "^8.2
|
|
63
|
-
"babel-plugin-emotion": "^10.0
|
|
64
|
-
"core-js": "^3.8
|
|
65
|
-
"css-loader": "^5.2
|
|
66
|
-
"deepmerge": "^2.2
|
|
67
|
-
"ejs": "^2.7
|
|
68
|
-
"eslint": "^7.32
|
|
69
|
-
"eslint-config-prettier": "^8.3
|
|
70
|
-
"eslint-loader": "^4.0
|
|
71
|
-
"eslint-plugin-import": "
|
|
72
|
-
"eslint-plugin-jsx-a11y": "
|
|
73
|
-
"eslint-plugin-prettier": "
|
|
74
|
-
"eslint-plugin-react": "
|
|
75
|
-
"eslint-plugin-unused-imports": "
|
|
76
|
-
"express": "^4.16
|
|
77
|
-
"fs": "0.0.1-security",
|
|
78
|
-
"git-revision-webpack-plugin": "^5.0
|
|
79
|
-
"jest": "^26.6
|
|
80
|
-
"jest-fetch-mock": "^3.0
|
|
81
|
-
"moment": "^2.29
|
|
82
|
-
"moment-timezone": "^0.5
|
|
83
|
-
"moment-timezone-data-webpack-plugin": "^1.5
|
|
84
|
-
"node-fetch": "^2.3
|
|
85
|
-
"node-sass": "^6.0
|
|
86
|
-
"path": "^0.12
|
|
87
|
-
"polished": "^2.3
|
|
88
|
-
"postcss-loader": "^5.3
|
|
89
|
-
"prettier": "2.0
|
|
90
|
-
"react": "^16.14
|
|
91
|
-
"react-custom-scrollbars": "^4.2
|
|
92
|
-
"react-day-picker": "^7.4
|
|
93
|
-
"react-dom": "^16.14
|
|
94
|
-
"react-emotion": "^9.2
|
|
95
|
-
"react-select": "^2.4
|
|
96
|
-
"react-transition-group": "^4.4
|
|
97
|
-
"sass-loader": "^
|
|
98
|
-
"style-loader": "^
|
|
99
|
-
"terser-webpack-plugin": "^5.1
|
|
100
|
-
"webpack": "^5.37
|
|
101
|
-
"webpack-bundle-analyzer": "^4.4
|
|
102
|
-
"webpack-cli": "^4.7
|
|
103
|
-
"whatwg-fetch": "^3.5
|
|
48
|
+
"@babel/cli": "^7.16",
|
|
49
|
+
"@babel/core": "^7.12",
|
|
50
|
+
"@babel/plugin-proposal-class-properties": "^7.12",
|
|
51
|
+
"@babel/plugin-proposal-object-rest-spread": "^7.12",
|
|
52
|
+
"@babel/polyfill": "^7.12",
|
|
53
|
+
"@babel/preset-env": "^7.12",
|
|
54
|
+
"@babel/preset-react": "^7.12",
|
|
55
|
+
"@emotion/babel-preset-css-prop": "^10.2",
|
|
56
|
+
"@emotion/core": "^10.1",
|
|
57
|
+
"@emotion/jest": "^11.3",
|
|
58
|
+
"@testing-library/jest-dom": "^5.11",
|
|
59
|
+
"@testing-library/react": "^11.2",
|
|
60
|
+
"autoprefixer": "^10.2",
|
|
61
|
+
"babel-eslint": "^10.1",
|
|
62
|
+
"babel-loader": "^8.2",
|
|
63
|
+
"babel-plugin-emotion": "^10.0",
|
|
64
|
+
"core-js": "^3.8",
|
|
65
|
+
"css-loader": "^5.2",
|
|
66
|
+
"deepmerge": "^2.2",
|
|
67
|
+
"ejs": "^2.7",
|
|
68
|
+
"eslint": "^7.32",
|
|
69
|
+
"eslint-config-prettier": "^8.3",
|
|
70
|
+
"eslint-loader": "^4.0",
|
|
71
|
+
"eslint-plugin-import": ">2.24",
|
|
72
|
+
"eslint-plugin-jsx-a11y": ">6.4",
|
|
73
|
+
"eslint-plugin-prettier": ">3.4",
|
|
74
|
+
"eslint-plugin-react": ">7.24",
|
|
75
|
+
"eslint-plugin-unused-imports": ">1.1",
|
|
76
|
+
"express": "^4.16",
|
|
77
|
+
"fs": ">0.0.1-security",
|
|
78
|
+
"git-revision-webpack-plugin": "^5.0",
|
|
79
|
+
"jest": "^26.6",
|
|
80
|
+
"jest-fetch-mock": "^3.0",
|
|
81
|
+
"moment": "^2.29",
|
|
82
|
+
"moment-timezone": "^0.5",
|
|
83
|
+
"moment-timezone-data-webpack-plugin": "^1.5",
|
|
84
|
+
"node-fetch": "^2.3",
|
|
85
|
+
"node-sass": "^6.0",
|
|
86
|
+
"path": "^0.12",
|
|
87
|
+
"polished": "^2.3",
|
|
88
|
+
"postcss-loader": "^5.3",
|
|
89
|
+
"prettier": "2.0",
|
|
90
|
+
"react": "^16.14",
|
|
91
|
+
"react-custom-scrollbars": "^4.2",
|
|
92
|
+
"react-day-picker": "^7.4",
|
|
93
|
+
"react-dom": "^16.14",
|
|
94
|
+
"react-emotion": "^9.2",
|
|
95
|
+
"react-select": "^2.4",
|
|
96
|
+
"react-transition-group": "^4.4",
|
|
97
|
+
"sass-loader": "^12.1",
|
|
98
|
+
"style-loader": "^3.0",
|
|
99
|
+
"terser-webpack-plugin": "^5.1",
|
|
100
|
+
"webpack": "^5.37",
|
|
101
|
+
"webpack-bundle-analyzer": "^4.4",
|
|
102
|
+
"webpack-cli": "^4.7",
|
|
103
|
+
"whatwg-fetch": "^3.5"
|
|
104
104
|
}
|
|
105
105
|
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
parseTzList,
|
|
7
7
|
getInitialSelectedTzid,
|
|
8
8
|
getMonthsLoadingFromQuery,
|
|
9
|
+
getDurationFromQuery,
|
|
9
10
|
} from "./utils/slots";
|
|
10
11
|
import { getMonthsInDisplay, parseTimeSlots } from "./utils/calendar";
|
|
11
12
|
|
|
@@ -30,6 +31,8 @@ const DateTimePicker = ({ options }) => {
|
|
|
30
31
|
selectedDateObject?.format("YYYY-MM")
|
|
31
32
|
);
|
|
32
33
|
|
|
34
|
+
const duration = getDurationFromQuery(options.query);
|
|
35
|
+
|
|
33
36
|
const endDateObject = moment(options.config.endDate, "YYYY-MM-DD");
|
|
34
37
|
const startDateObject = moment(options.config.startDate, "YYYY-MM-DD");
|
|
35
38
|
const currentMonthObject = selectedDateObject ?? startDateObject;
|
|
@@ -61,6 +64,7 @@ const DateTimePicker = ({ options }) => {
|
|
|
61
64
|
: () => options.log.info("No `callback` option has been provided"),
|
|
62
65
|
columnView: "loading", // loading | error | slots | confirm | no-slots
|
|
63
66
|
daySlots: [],
|
|
67
|
+
duration,
|
|
64
68
|
locale: options.locale,
|
|
65
69
|
mode: options.config.mode, // confirm (default) | no_confirm
|
|
66
70
|
query: options.query,
|
|
@@ -75,6 +79,7 @@ const DateTimePicker = ({ options }) => {
|
|
|
75
79
|
endDateObject,
|
|
76
80
|
focusedSlot: false,
|
|
77
81
|
availableDays: [],
|
|
82
|
+
sequenced_availability: options.query.sequence ? true : false,
|
|
78
83
|
slots: {},
|
|
79
84
|
slotFetchCount: 0,
|
|
80
85
|
slotInjectionPoint: undefined,
|
|
@@ -17,9 +17,11 @@ const Details = ({ duration, locale }) => {
|
|
|
17
17
|
<TimeZoneSelector locale={locale} />
|
|
18
18
|
</div>
|
|
19
19
|
<div className={theme.classBuilder("details--duration")}>
|
|
20
|
-
|
|
21
|
-
<
|
|
22
|
-
|
|
20
|
+
{duration && (
|
|
21
|
+
<p>
|
|
22
|
+
<strong>{i18n.t("duration_label")}:</strong> {duration} {i18n.t("minutes")}
|
|
23
|
+
</p>
|
|
24
|
+
)}
|
|
23
25
|
</div>
|
|
24
26
|
</div>
|
|
25
27
|
);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from "react";
|
|
2
|
+
import moment from "moment-timezone";
|
|
3
|
+
|
|
4
|
+
import { useI18n } from "../../contexts/i18n-context";
|
|
5
|
+
import { useStatus } from "./contexts/status-context";
|
|
6
|
+
import { useTheme } from "./contexts/theme-context";
|
|
7
|
+
import { useTz } from "./contexts/tz-context";
|
|
8
|
+
|
|
9
|
+
const SequencedSlotButton = ({ slot }) => {
|
|
10
|
+
const i18n = useI18n();
|
|
11
|
+
const theme = useTheme();
|
|
12
|
+
const [status, dispatchStatus] = useStatus();
|
|
13
|
+
const [tz] = useTz();
|
|
14
|
+
|
|
15
|
+
const slotButtonRef = useRef();
|
|
16
|
+
|
|
17
|
+
const startArray = slot.map(a => a.start);
|
|
18
|
+
const endArray = slot.map(a => a.end);
|
|
19
|
+
|
|
20
|
+
const start = startArray.reduce((prev, current) => {
|
|
21
|
+
return prev < current ? prev : current;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const end = endArray.reduce((prev, current) => {
|
|
25
|
+
return prev > current ? prev : current;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const handleSlotSelection = slot => {
|
|
29
|
+
const selectedSlot = {
|
|
30
|
+
start,
|
|
31
|
+
end,
|
|
32
|
+
sequence: slot,
|
|
33
|
+
};
|
|
34
|
+
dispatchStatus({ type: "SELECT_SLOT", slot: selectedSlot, tzid: tz.selectedTzid.tzid });
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (status.focusedSlot === start) {
|
|
39
|
+
slotButtonRef.current.focus();
|
|
40
|
+
}
|
|
41
|
+
}, [status.focusedSlot]);
|
|
42
|
+
|
|
43
|
+
let classStub = "time-slot";
|
|
44
|
+
if (status.selected.start === start) classStub = classStub + " time-slot--selected";
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<button
|
|
48
|
+
className={theme.classBuilder(classStub)}
|
|
49
|
+
onClick={() => handleSlotSelection(slot)}
|
|
50
|
+
ref={slotButtonRef}
|
|
51
|
+
>
|
|
52
|
+
<span className={theme.classBuilder("visually-hidden")}>
|
|
53
|
+
{i18n.t("select_time_slot")}
|
|
54
|
+
</span>
|
|
55
|
+
{i18n.customFormatedTimeZone(
|
|
56
|
+
moment(start, "YYYY-MM-DDTHH:mm:00Z"),
|
|
57
|
+
tz.selectedTzid.tzid,
|
|
58
|
+
"LT"
|
|
59
|
+
)}
|
|
60
|
+
{" - "}
|
|
61
|
+
{i18n.customFormatedTimeZone(
|
|
62
|
+
moment(end, "YYYY-MM-DDTHH:mm:00Z"),
|
|
63
|
+
tz.selectedTzid.tzid,
|
|
64
|
+
"LT"
|
|
65
|
+
)}{" "}
|
|
66
|
+
{`(${moment(start, "YYYY-MM-DDTHH:mm:00Z").tz(tz.selectedTzid.tzid).format("z")})`}
|
|
67
|
+
</button>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export default SequencedSlotButton;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
3
|
import SlotButton from "./SlotButton";
|
|
4
|
+
import SequencedSlotButton from "./SequencedSlotButton";
|
|
4
5
|
|
|
5
6
|
import { useI18n } from "../../contexts/i18n-context";
|
|
6
7
|
import { useStatus } from "./contexts/status-context";
|
|
@@ -14,7 +15,11 @@ const SlotsList = () => {
|
|
|
14
15
|
const renderSlots = status.daySlots.map((slot, key) => {
|
|
15
16
|
return (
|
|
16
17
|
<li key={key} className={theme.classBuilder("slot-list--item")}>
|
|
17
|
-
|
|
18
|
+
{status.sequenced_availability ? (
|
|
19
|
+
<SequencedSlotButton slot={slot} />
|
|
20
|
+
) : (
|
|
21
|
+
<SlotButton slot={slot} />
|
|
22
|
+
)}
|
|
18
23
|
</li>
|
|
19
24
|
);
|
|
20
25
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from "react";
|
|
2
2
|
import moment from "moment";
|
|
3
3
|
|
|
4
|
-
import { getSlots } from "./utils/slots";
|
|
4
|
+
import { getSequencedSlots, getSlots } from "./utils/slots";
|
|
5
5
|
|
|
6
6
|
import Calendar from "./Calendar";
|
|
7
7
|
import Confirm from "./Confirm";
|
|
@@ -31,26 +31,20 @@ const Wrapper = () => {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
const fetchMonthSlots = (query, month) => {
|
|
34
|
-
|
|
34
|
+
const fetch = status.sequenced_availability ? getSequencedSlots : getSlots;
|
|
35
|
+
|
|
36
|
+
return fetch({
|
|
35
37
|
query,
|
|
36
38
|
auth: status.auth,
|
|
37
39
|
tzid: status.tzid,
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
month: month,
|
|
45
|
-
});
|
|
46
|
-
})
|
|
47
|
-
.catch(res => {
|
|
48
|
-
dispatchStatus({
|
|
49
|
-
type: "ERROR_LOADING_SLOTS",
|
|
50
|
-
error: res,
|
|
51
|
-
month: month,
|
|
52
|
-
});
|
|
40
|
+
}).then(res => {
|
|
41
|
+
dispatchStatus({
|
|
42
|
+
type: "SET_SLOTS",
|
|
43
|
+
slots: res,
|
|
44
|
+
tzid: tz.selectedTzid.tzid,
|
|
45
|
+
month: month,
|
|
53
46
|
});
|
|
47
|
+
});
|
|
54
48
|
};
|
|
55
49
|
|
|
56
50
|
const currentMonth = status.months.find(m => m.current);
|
|
@@ -60,7 +54,15 @@ const Wrapper = () => {
|
|
|
60
54
|
.then(() => {
|
|
61
55
|
// Get slots for remianing months
|
|
62
56
|
const remainingMonths = status.months.filter(month => !month.current);
|
|
63
|
-
remainingMonths.forEach(month =>
|
|
57
|
+
remainingMonths.forEach(month =>
|
|
58
|
+
fetchMonthSlots(month.query, month.month).catch(res => {
|
|
59
|
+
dispatchStatus({
|
|
60
|
+
type: "ERROR_LOADING_SLOTS",
|
|
61
|
+
error: res,
|
|
62
|
+
month: month.month,
|
|
63
|
+
});
|
|
64
|
+
})
|
|
65
|
+
);
|
|
64
66
|
})
|
|
65
67
|
.catch(error => {
|
|
66
68
|
dispatchStatus({ type: "ERROR_GETTING_SLOTS", error });
|
|
@@ -172,7 +174,7 @@ const Wrapper = () => {
|
|
|
172
174
|
|
|
173
175
|
return (
|
|
174
176
|
<section className={theme.classBuilder()} style={theme.customProperties}>
|
|
175
|
-
<Details duration={status.
|
|
177
|
+
<Details duration={status.duration} locale={status.locale} />
|
|
176
178
|
<div className={theme.classBuilder("wrapper")}>
|
|
177
179
|
<div
|
|
178
180
|
className={
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
getAvailableDays,
|
|
7
7
|
getLocalDayFromUtc,
|
|
8
8
|
removeMonthFromLoading,
|
|
9
|
+
addSequencedSlotsToObject,
|
|
9
10
|
} from "../utils/slots";
|
|
10
11
|
import { getMonthsInDisplay, parseTimeSlots } from "../utils/calendar";
|
|
11
12
|
|
|
@@ -43,6 +44,7 @@ export const statusReducer = (state, action) => {
|
|
|
43
44
|
notification: {
|
|
44
45
|
type: "error",
|
|
45
46
|
message: "There was an error getting the slots",
|
|
47
|
+
body: action.error.body,
|
|
46
48
|
},
|
|
47
49
|
};
|
|
48
50
|
state.callback(notification);
|
|
@@ -66,6 +68,12 @@ export const statusReducer = (state, action) => {
|
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
case "NO_SLOTS_FOUND": {
|
|
71
|
+
const notification = {
|
|
72
|
+
notification: {
|
|
73
|
+
type: "no_slots_found",
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
state.callback(notification);
|
|
69
77
|
return { ...state, columnView: "no-slots" };
|
|
70
78
|
}
|
|
71
79
|
|
|
@@ -91,21 +99,31 @@ export const statusReducer = (state, action) => {
|
|
|
91
99
|
|
|
92
100
|
case "SET_SLOTS": {
|
|
93
101
|
if (!action.slots.length > 0) {
|
|
94
|
-
|
|
102
|
+
const monthsLoading = removeMonthFromLoading(state.monthsLoading, action.month);
|
|
103
|
+
return {
|
|
104
|
+
...state,
|
|
105
|
+
monthsLoading,
|
|
106
|
+
slotFetchCount: state.slotFetchCount + 1,
|
|
107
|
+
};
|
|
95
108
|
}
|
|
96
109
|
|
|
97
|
-
const slotsObject =
|
|
98
|
-
|
|
99
|
-
|
|
110
|
+
const slotsObject = state.sequenced_availability
|
|
111
|
+
? addSequencedSlotsToObject(state.slots, action.slots)
|
|
112
|
+
: addSlotsToObject(state.slots, action.slots);
|
|
113
|
+
const availableDays = getAvailableDays(slotsObject, action.tzid);
|
|
100
114
|
const monthsLoading = removeMonthFromLoading(state.monthsLoading, action.month);
|
|
101
115
|
|
|
116
|
+
const injectionPoint = state.sequenced_availability
|
|
117
|
+
? getLocalDayFromUtc(action.slots[0].sequence[0].start, action.tzid)
|
|
118
|
+
: getLocalDayFromUtc(action.slots[0].start, action.tzid);
|
|
119
|
+
|
|
102
120
|
return {
|
|
103
121
|
...state,
|
|
104
|
-
availableDays
|
|
122
|
+
availableDays,
|
|
105
123
|
monthsLoading,
|
|
106
124
|
slots: slotsObject,
|
|
107
125
|
slotFetchCount: state.slotFetchCount + 1,
|
|
108
|
-
slotInjectionPoint:
|
|
126
|
+
slotInjectionPoint: injectionPoint,
|
|
109
127
|
};
|
|
110
128
|
}
|
|
111
129
|
|
|
@@ -118,13 +136,17 @@ export const statusReducer = (state, action) => {
|
|
|
118
136
|
|
|
119
137
|
case "SELECT_DAY": {
|
|
120
138
|
const daySlots = getSlotsByDay(state.slots, action.day, action.tzid);
|
|
121
|
-
const focusedSlot =
|
|
139
|
+
const focusedSlot = state.sequenced_availability
|
|
140
|
+
? daySlots[0]?.reduce((prev, current) => {
|
|
141
|
+
return prev.start < current.start ? prev.start : current.start;
|
|
142
|
+
})
|
|
143
|
+
: daySlots[0]?.start;
|
|
122
144
|
|
|
123
145
|
return {
|
|
124
146
|
...state,
|
|
125
147
|
selectedDay: action.day,
|
|
126
148
|
focusedDay: action.day,
|
|
127
|
-
focusedSlot: focusedSlot
|
|
149
|
+
focusedSlot: focusedSlot,
|
|
128
150
|
columnView: "slots",
|
|
129
151
|
daySlots,
|
|
130
152
|
populated: true,
|