cronofy-elements 1.44.1 → 1.45.0
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/build/CronofyElements.v1.45.0.js +2 -0
- package/build/{CronofyElements.v1.44.1.js.LICENSE.txt → CronofyElements.v1.45.0.js.LICENSE.txt} +0 -0
- package/build/npm/CronofyElements.js +2 -2
- package/demo/rules.ejs +7 -1
- package/package.json +1 -1
- package/src/js/components/AvailabilityRules/AvailabilityRules.js +15 -1
- package/src/js/components/AvailabilityRules/CalendarSelector.js +1 -1
- package/src/js/components/AvailabilityRules/Calendars.js +1 -1
- package/src/js/components/AvailabilityRules/TimeZoneDisplay.js +13 -2
- package/src/js/components/AvailabilityRules/Wrapper.js +41 -16
- package/src/js/components/AvailabilityRules/scss/_base.buttons.scss +58 -0
- package/src/js/components/AvailabilityRules/scss/_base.theme.scss +4 -0
- package/src/js/components/AvailabilityRules/scss/_components.timezoneselector.scss +74 -0
- package/src/js/components/AvailabilityRules/scss/_generic.reset.scss +13 -0
- package/src/js/components/AvailabilityRules/scss/_settings.colours.scss +12 -0
- package/src/js/components/AvailabilityRules/scss/availabilityrules.scss +5 -0
- package/src/js/components/AvailabilityRules/utils/tz-utils.js +44 -0
- package/src/js/components/DateTimePicker/Calendar.js +1 -1
- package/src/js/components/DateTimePicker/CalendarHeader.js +1 -1
- package/src/js/components/DateTimePicker/Confirm.js +1 -1
- package/src/js/components/DateTimePicker/DateTimePicker.js +1 -1
- package/src/js/components/DateTimePicker/DayButton.js +1 -1
- package/src/js/components/DateTimePicker/Details.js +5 -2
- package/src/js/components/DateTimePicker/SequencedSlotButton.js +1 -1
- package/src/js/components/DateTimePicker/SlotButton.js +1 -1
- package/src/js/components/DateTimePicker/Wrapper.js +1 -1
- package/src/js/components/DateTimePicker/utils/slots.js +1 -1
- package/src/js/components/{DateTimePicker → generic}/TimeZoneSelector.js +9 -16
- package/src/js/{components/DateTimePicker/contexts → contexts}/tz-context.js +0 -0
- package/src/js/{components/DateTimePicker/utils → helpers}/tz-list.js +0 -0
- package/tests/AvailabilityRules/__snapshots__/AvailabilityRules.test.js.snap +36 -6
- package/tests/DateTimePicker/SequencedSlotButton.test.js +1 -1
- package/tests/DateTimePicker/SlotButton.test.js +1 -1
- package/tests/components/TimezoneSelector.test.js +124 -0
- package/build/CronofyElements.v1.44.1.js +0 -2
package/demo/rules.ejs
CHANGED
|
@@ -77,7 +77,13 @@
|
|
|
77
77
|
// start_time: "09:00",
|
|
78
78
|
// end_time: "13:00"
|
|
79
79
|
// }],
|
|
80
|
-
// auto_create_rules: true
|
|
80
|
+
// auto_create_rules: true,
|
|
81
|
+
// tz_list: [
|
|
82
|
+
// "America/Sao_Paulo",
|
|
83
|
+
// "Etc/UTC",
|
|
84
|
+
// "Pacific/Fakaofo",
|
|
85
|
+
// "Europe/London",
|
|
86
|
+
// ],
|
|
81
87
|
},
|
|
82
88
|
callback: cb => console.log('rules callback',cb),
|
|
83
89
|
styles: {
|
package/package.json
CHANGED
|
@@ -2,9 +2,14 @@ import React from "react";
|
|
|
2
2
|
|
|
3
3
|
import { I18nProvider } from "../../contexts/i18n-context";
|
|
4
4
|
import { LogProvider } from "../../contexts/log-context";
|
|
5
|
+
import { TzProvider } from "../../contexts/tz-context";
|
|
6
|
+
|
|
7
|
+
import { parseTzList, getInitialSelectedTzid } from "./utils/tz-utils";
|
|
5
8
|
|
|
6
9
|
import Wrapper from "./Wrapper";
|
|
7
10
|
|
|
11
|
+
import "./scss/availabilityrules.scss";
|
|
12
|
+
|
|
8
13
|
const AvailabilityRules = ({ options }) => {
|
|
9
14
|
const logOptions = {
|
|
10
15
|
mode: options.config.logs,
|
|
@@ -19,10 +24,19 @@ const AvailabilityRules = ({ options }) => {
|
|
|
19
24
|
tzid: options.tzid,
|
|
20
25
|
};
|
|
21
26
|
|
|
27
|
+
const tzList = parseTzList(options.config.tz_list, options.tzid);
|
|
28
|
+
const selectedTzid = getInitialSelectedTzid(tzList, options.tzid);
|
|
29
|
+
const tzOptions = {
|
|
30
|
+
selectedTzid: selectedTzid,
|
|
31
|
+
list: tzList,
|
|
32
|
+
};
|
|
33
|
+
|
|
22
34
|
return (
|
|
23
35
|
<LogProvider options={logOptions}>
|
|
24
36
|
<I18nProvider options={i18nOptions}>
|
|
25
|
-
<
|
|
37
|
+
<TzProvider options={tzOptions}>
|
|
38
|
+
<Wrapper options={options} />
|
|
39
|
+
</TzProvider>
|
|
26
40
|
</I18nProvider>
|
|
27
41
|
</LogProvider>
|
|
28
42
|
);
|
|
@@ -2,27 +2,38 @@ import React, { useContext } from "react";
|
|
|
2
2
|
import { css } from "@emotion/core";
|
|
3
3
|
|
|
4
4
|
import { ExtrasContext, StatusContext, ThemeContext } from "./Wrapper";
|
|
5
|
+
import { useTz } from "../../contexts/tz-context";
|
|
5
6
|
import { useI18n } from "../../contexts/i18n-context";
|
|
6
|
-
import
|
|
7
|
+
import TimeZoneSelector from "../generic/TimeZoneSelector";
|
|
7
8
|
|
|
8
9
|
const TimeZoneDisplay = () => {
|
|
9
10
|
const [extras, setExtras] = useContext(ExtrasContext);
|
|
10
11
|
const [status, setStatus] = useContext(StatusContext);
|
|
11
12
|
const i18n = useI18n();
|
|
12
13
|
const [theme, setTheme] = useContext(ThemeContext);
|
|
14
|
+
const [tz, setTz] = useTz();
|
|
13
15
|
return (
|
|
14
16
|
<div
|
|
15
17
|
css={css`
|
|
16
18
|
flex-grow: 1;
|
|
17
19
|
display: flex;
|
|
18
20
|
width: 100%;
|
|
21
|
+
padding-right: 1em;
|
|
19
22
|
@media (max-width: ${theme.sizes.breakpoints.small}px) {
|
|
20
23
|
margin-bottom: 16px;
|
|
21
24
|
}
|
|
22
25
|
`}
|
|
23
26
|
className={`${theme.prefix}__timezone`}
|
|
24
27
|
>
|
|
25
|
-
|
|
28
|
+
<p
|
|
29
|
+
css={css`
|
|
30
|
+
padding: 0.3em 0.6em 0 0;
|
|
31
|
+
margin: 0;
|
|
32
|
+
`}
|
|
33
|
+
>
|
|
34
|
+
{i18n.t("time_zone")}
|
|
35
|
+
</p>
|
|
36
|
+
<TimeZoneSelector locale={status.locale} theme={theme} tz={tz} setTz={setTz} />
|
|
26
37
|
</div>
|
|
27
38
|
);
|
|
28
39
|
};
|
|
@@ -14,10 +14,12 @@ import {
|
|
|
14
14
|
parseAccountOptions,
|
|
15
15
|
buildRuleTemplate,
|
|
16
16
|
} from "../../helpers/utils.AvailabilityRules";
|
|
17
|
-
import {
|
|
17
|
+
import { getInitialSelectedTzid } from "./utils/tz-utils";
|
|
18
|
+
import { parseStyleOptions, classBuilder } from "../../helpers/theming";
|
|
18
19
|
import { globals } from "../../styles/utils";
|
|
19
20
|
import { useI18n } from "../../contexts/i18n-context";
|
|
20
21
|
import { useLog } from "../../contexts/log-context";
|
|
22
|
+
import { useTz } from "../../contexts/tz-context";
|
|
21
23
|
|
|
22
24
|
import Calendars from "./Calendars";
|
|
23
25
|
import Container from "../generic/Container";
|
|
@@ -37,6 +39,7 @@ export const ThemeContext = React.createContext();
|
|
|
37
39
|
const Wrapper = ({ options }) => {
|
|
38
40
|
const i18n = useI18n();
|
|
39
41
|
const log = useLog();
|
|
42
|
+
const [tz, setTz] = useTz();
|
|
40
43
|
|
|
41
44
|
const [account, setAccount] = useState(() => parseAccountOptions(options));
|
|
42
45
|
const [calendars, setCalendars] = useState(() => ({
|
|
@@ -52,7 +55,7 @@ const Wrapper = ({ options }) => {
|
|
|
52
55
|
saved: false,
|
|
53
56
|
savedSuccess: false,
|
|
54
57
|
locale: options.locale,
|
|
55
|
-
tzid:
|
|
58
|
+
tzid: tz.selectedTzid.tzid,
|
|
56
59
|
callback: options.callback ? options.callback : cb => {},
|
|
57
60
|
startDay: options.config.startDay,
|
|
58
61
|
defaultWeeklyPeriods: options.config.defaultWeeklyPeriods,
|
|
@@ -83,19 +86,23 @@ const Wrapper = ({ options }) => {
|
|
|
83
86
|
)
|
|
84
87
|
);
|
|
85
88
|
|
|
86
|
-
const [theme, setTheme] = useState(() =>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
const [theme, setTheme] = useState(() => {
|
|
90
|
+
const styles = parseStyleOptions(options.styles, "AvailabilityViewer");
|
|
91
|
+
return {
|
|
92
|
+
...styles,
|
|
93
|
+
classBuilder: classBuilder(styles.prefix, "AR"),
|
|
94
|
+
sizes: {
|
|
95
|
+
breakpoints: {
|
|
96
|
+
small: 650,
|
|
97
|
+
},
|
|
98
|
+
labelWidth: 60,
|
|
99
|
+
labelWidthSmall: 24,
|
|
100
|
+
columnWidth: 100,
|
|
101
|
+
wrapperWidth: false,
|
|
102
|
+
wrapperUnderflow: 0,
|
|
91
103
|
},
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
columnWidth: 100,
|
|
95
|
-
wrapperWidth: false,
|
|
96
|
-
wrapperUnderflow: 0,
|
|
97
|
-
},
|
|
98
|
-
}));
|
|
104
|
+
};
|
|
105
|
+
});
|
|
99
106
|
|
|
100
107
|
const handleRuleChange = (IDs, toggleStatus) => {
|
|
101
108
|
const availability = toggleStatus === "available";
|
|
@@ -173,7 +180,7 @@ const Wrapper = ({ options }) => {
|
|
|
173
180
|
.then(res => {
|
|
174
181
|
const isNewRule = res[0].type === 404;
|
|
175
182
|
const rulesResponse = isNewRule
|
|
176
|
-
? buildRuleTemplate(options.config.defaultWeeklyPeriods,
|
|
183
|
+
? buildRuleTemplate(options.config.defaultWeeklyPeriods, tz.selectedTzid.tzid)
|
|
177
184
|
: res[0];
|
|
178
185
|
|
|
179
186
|
if (isNewRule) {
|
|
@@ -198,6 +205,15 @@ const Wrapper = ({ options }) => {
|
|
|
198
205
|
tzid: rulesResponse.availability_rule.tzid,
|
|
199
206
|
}));
|
|
200
207
|
|
|
208
|
+
const selectedTzid = getInitialSelectedTzid(
|
|
209
|
+
tz.list,
|
|
210
|
+
rulesResponse.availability_rule.tzid
|
|
211
|
+
);
|
|
212
|
+
setTz({
|
|
213
|
+
list: tz.list,
|
|
214
|
+
selectedTzid: selectedTzid,
|
|
215
|
+
});
|
|
216
|
+
|
|
201
217
|
setSlots(slots => {
|
|
202
218
|
const hydratedSlots = checkSlotAvailability(
|
|
203
219
|
rulesResponse.availability_rule.weekly_periods,
|
|
@@ -269,6 +285,15 @@ const Wrapper = ({ options }) => {
|
|
|
269
285
|
}
|
|
270
286
|
}, [status]);
|
|
271
287
|
|
|
288
|
+
useEffect(() => {
|
|
289
|
+
if (tz.selectedTzid.tzid) {
|
|
290
|
+
setAccount(account => ({
|
|
291
|
+
...account,
|
|
292
|
+
tzid: tz.selectedTzid.tzid,
|
|
293
|
+
}));
|
|
294
|
+
}
|
|
295
|
+
}, [tz.selectedTzid.tzid]);
|
|
296
|
+
|
|
272
297
|
const generateRules = () => {
|
|
273
298
|
const newRules = buildNewRules(slots);
|
|
274
299
|
|
|
@@ -373,7 +398,7 @@ const Wrapper = ({ options }) => {
|
|
|
373
398
|
overflow: hidden;
|
|
374
399
|
}
|
|
375
400
|
`}
|
|
376
|
-
className={
|
|
401
|
+
className={theme.classBuilder()}
|
|
377
402
|
>
|
|
378
403
|
<ThemeContext.Provider value={[theme, setTheme]}>
|
|
379
404
|
<StatusContext.Provider value={[status, setStatus]}>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
.AR__button {
|
|
2
|
+
appearance: none;
|
|
3
|
+
background: none;
|
|
4
|
+
border: none;
|
|
5
|
+
border-radius: 0;
|
|
6
|
+
font-family: inherit;
|
|
7
|
+
position: relative;
|
|
8
|
+
display: block;
|
|
9
|
+
cursor: pointer;
|
|
10
|
+
font-size: 1em;
|
|
11
|
+
border: 0.1em solid var(--greyMid);
|
|
12
|
+
background-color: var(--white);
|
|
13
|
+
|
|
14
|
+
&:focus {
|
|
15
|
+
border-color: var(--availableActive);
|
|
16
|
+
box-shadow: inset var(--availableActive) 0 0 0 0.1em;
|
|
17
|
+
box-shadow: inset var(--availableActive) 0 0 0 0.1em;
|
|
18
|
+
outline: none;
|
|
19
|
+
}
|
|
20
|
+
&:hover {
|
|
21
|
+
border-color: var(--availableActive);
|
|
22
|
+
box-shadow: inset var(--availableActive) 0 0 0 0.1em;
|
|
23
|
+
background-color: var(--availableHover);
|
|
24
|
+
color: var(--black);
|
|
25
|
+
outline: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&:active {
|
|
29
|
+
background-color: var(--availableActive);
|
|
30
|
+
color: var(--black);
|
|
31
|
+
outline: none;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.AR__disabled-button {
|
|
36
|
+
pointer-events: none;
|
|
37
|
+
border: unset;
|
|
38
|
+
background-color: unset;
|
|
39
|
+
|
|
40
|
+
&:focus {
|
|
41
|
+
border-color: unset;
|
|
42
|
+
box-shadow: unset;
|
|
43
|
+
outline: none;
|
|
44
|
+
background-color: unset;
|
|
45
|
+
}
|
|
46
|
+
&:hover {
|
|
47
|
+
border-color: unset;
|
|
48
|
+
box-shadow: unset;
|
|
49
|
+
outline: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
&:active {
|
|
53
|
+
border-color: unset;
|
|
54
|
+
box-shadow: unset;
|
|
55
|
+
outline: none;
|
|
56
|
+
background-color: unset;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
.AR__timezone-selector {
|
|
2
|
+
position: relative;
|
|
3
|
+
flex-grow: 1;
|
|
4
|
+
max-width: 16rem;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.AR__timezone-selector--button {
|
|
8
|
+
@extend .AR__button;
|
|
9
|
+
display: inline-block;
|
|
10
|
+
border: 0.1em solid var(--greyMid);
|
|
11
|
+
background: var(--white);
|
|
12
|
+
padding: 0.3em 1em;
|
|
13
|
+
text-align: left;
|
|
14
|
+
width: 100%;
|
|
15
|
+
border-radius: 0.4em;
|
|
16
|
+
z-index: 4;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.AR__timezone-selector--icon {
|
|
20
|
+
width: 1em;
|
|
21
|
+
height: 1em;
|
|
22
|
+
margin-top: 0.2em;
|
|
23
|
+
fill: var(--grey);
|
|
24
|
+
float: right;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.AR__timezone-selector--icon-open {
|
|
28
|
+
transform: scaleY(-1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.AR__timezone-selector--listbox-wrapper {
|
|
32
|
+
@extend %unset;
|
|
33
|
+
position: absolute;
|
|
34
|
+
width: 100%;
|
|
35
|
+
border: 0.1em solid var(--greyMid);
|
|
36
|
+
background-color: var(--white);
|
|
37
|
+
border-top: 0;
|
|
38
|
+
padding-top: 1.15em;
|
|
39
|
+
top: 1em;
|
|
40
|
+
z-index: 3;
|
|
41
|
+
border-radius: 0 0 0.4em 0.4em;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.AR__timezone-selector--listbox {
|
|
45
|
+
@extend %unset;
|
|
46
|
+
width: 100%;
|
|
47
|
+
max-height: 15em;
|
|
48
|
+
overflow-y: auto;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.AR__timezone-selector--option {
|
|
52
|
+
@extend %unset;
|
|
53
|
+
display: block;
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
padding: 0.5em 1em;
|
|
56
|
+
position: relative;
|
|
57
|
+
line-height: 1.8em;
|
|
58
|
+
|
|
59
|
+
&:hover {
|
|
60
|
+
background-color: var(--availableHover);
|
|
61
|
+
color: var(--black);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.AR__timezone-selector--focused {
|
|
66
|
+
border-color: var(--availableActive);
|
|
67
|
+
box-shadow: inset var(--availableActive) 0 0 0 0.1em;
|
|
68
|
+
outline: none;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.AR__timezone-selector--selected {
|
|
72
|
+
background-color: var(--availableHover);
|
|
73
|
+
color: var(--black);
|
|
74
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//Unsetting styles to avoid clashes with styles outside the component
|
|
2
|
+
%unset {
|
|
3
|
+
padding: unset;
|
|
4
|
+
margin-top: unset;
|
|
5
|
+
margin-bottom: unset;
|
|
6
|
+
margin-left: unset;
|
|
7
|
+
margin-right: unset;
|
|
8
|
+
border: unset;
|
|
9
|
+
background: unset;
|
|
10
|
+
border-spacing: 0;
|
|
11
|
+
font-style: unset;
|
|
12
|
+
list-style: unset;
|
|
13
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import moment from "moment-timezone";
|
|
2
|
+
import { humanizeTzName } from "../../../helpers/utils";
|
|
3
|
+
import { defaultTimeZones } from "../../../helpers/tz-list";
|
|
4
|
+
|
|
5
|
+
export const createTzObject = tzid => {
|
|
6
|
+
const name = humanizeTzName(tzid);
|
|
7
|
+
|
|
8
|
+
const zone = moment.tz(tzid);
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
tzid: tzid,
|
|
12
|
+
offset: zone.format("Z"),
|
|
13
|
+
offsetMins: zone.utcOffset(),
|
|
14
|
+
name: name,
|
|
15
|
+
abbr: zone.zoneAbbr(),
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const parseTzList = (timezones, tzid) => {
|
|
20
|
+
const tzList = timezones ? timezones : moment.tz.names();
|
|
21
|
+
const filtered = timezones ? timezones : tzList.filter(item => defaultTimeZones.includes(item));
|
|
22
|
+
|
|
23
|
+
const result = [];
|
|
24
|
+
|
|
25
|
+
filtered.map(tz => {
|
|
26
|
+
const item = createTzObject(tz);
|
|
27
|
+
result.push(item);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const isInList = result.findIndex(item => tzid === item.tzid);
|
|
31
|
+
|
|
32
|
+
if (isInList <= -1) {
|
|
33
|
+
const item = createTzObject(tzid);
|
|
34
|
+
result.push(item);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
result.sort((tzA, tzB) => tzA.offsetMins - tzB.offsetMins);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const getInitialSelectedTzid = (tzList, tzid) => {
|
|
42
|
+
const result = tzList.find(tz => tzid === tz.tzid);
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
@@ -14,7 +14,7 @@ import DayHeadings from "./DayHeadings";
|
|
|
14
14
|
|
|
15
15
|
import { useStatus } from "./contexts/status-context";
|
|
16
16
|
import { useTheme } from "./contexts/theme-context";
|
|
17
|
-
import { useTz } from "
|
|
17
|
+
import { useTz } from "../../contexts/tz-context";
|
|
18
18
|
|
|
19
19
|
const Calendar = () => {
|
|
20
20
|
const [status, dispatchStatus] = useStatus();
|
|
@@ -4,7 +4,7 @@ import moment from "moment-timezone";
|
|
|
4
4
|
import { useI18n } from "../../contexts/i18n-context";
|
|
5
5
|
import { useStatus } from "./contexts/status-context";
|
|
6
6
|
import { useTheme } from "./contexts/theme-context";
|
|
7
|
-
import { useTz } from "
|
|
7
|
+
import { useTz } from "../../contexts/tz-context";
|
|
8
8
|
|
|
9
9
|
const CalendarHeader = () => {
|
|
10
10
|
const i18n = useI18n();
|
|
@@ -4,7 +4,7 @@ import moment from "moment-timezone";
|
|
|
4
4
|
import { useI18n } from "../../contexts/i18n-context";
|
|
5
5
|
import { useStatus } from "./contexts/status-context";
|
|
6
6
|
import { useTheme } from "./contexts/theme-context";
|
|
7
|
-
import { useTz } from "
|
|
7
|
+
import { useTz } from "../../contexts/tz-context";
|
|
8
8
|
|
|
9
9
|
const Confirm = ({ confirmButtonRef }) => {
|
|
10
10
|
const i18n = useI18n();
|
|
@@ -18,7 +18,7 @@ import { I18nProvider } from "../../contexts/i18n-context";
|
|
|
18
18
|
import { LogProvider } from "../../contexts/log-context";
|
|
19
19
|
import { ThemeProvider } from "./contexts/theme-context";
|
|
20
20
|
import { StatusProvider } from "./contexts/status-context";
|
|
21
|
-
import { TzProvider } from "
|
|
21
|
+
import { TzProvider } from "../../contexts/tz-context";
|
|
22
22
|
|
|
23
23
|
const DateTimePicker = ({ options }) => {
|
|
24
24
|
const statusOptions = useMemo(() => {
|
|
@@ -4,7 +4,7 @@ import moment from "moment-timezone";
|
|
|
4
4
|
import { useI18n } from "../../contexts/i18n-context";
|
|
5
5
|
import { useStatus } from "./contexts/status-context";
|
|
6
6
|
import { useTheme } from "./contexts/theme-context";
|
|
7
|
-
import { useTz } from "
|
|
7
|
+
import { useTz } from "../../contexts/tz-context";
|
|
8
8
|
|
|
9
9
|
const DayButton = ({ day, selected = false, focused = false }) => {
|
|
10
10
|
const i18n = useI18n();
|
|
@@ -2,11 +2,14 @@ import React, { memo } from "react";
|
|
|
2
2
|
|
|
3
3
|
import { useI18n } from "../../contexts/i18n-context";
|
|
4
4
|
import { useTheme } from "./contexts/theme-context";
|
|
5
|
-
import TimeZoneSelector from "
|
|
5
|
+
import TimeZoneSelector from "../generic/TimeZoneSelector";
|
|
6
|
+
|
|
7
|
+
import { useTz } from "../../contexts/tz-context";
|
|
6
8
|
|
|
7
9
|
const Details = ({ duration, locale }) => {
|
|
8
10
|
const i18n = useI18n();
|
|
9
11
|
const theme = useTheme();
|
|
12
|
+
const [tz, setTz] = useTz();
|
|
10
13
|
|
|
11
14
|
return (
|
|
12
15
|
<div className={theme.classBuilder("details")}>
|
|
@@ -14,7 +17,7 @@ const Details = ({ duration, locale }) => {
|
|
|
14
17
|
<p className={theme.classBuilder("details--tz-label")}>
|
|
15
18
|
<strong>{i18n.t("time_zone")}:</strong>
|
|
16
19
|
</p>
|
|
17
|
-
<TimeZoneSelector locale={locale} />
|
|
20
|
+
<TimeZoneSelector locale={locale} theme={theme} tz={tz} setTz={setTz} />
|
|
18
21
|
</div>
|
|
19
22
|
<div className={theme.classBuilder("details--duration")}>
|
|
20
23
|
{duration && (
|
|
@@ -4,7 +4,7 @@ import moment from "moment-timezone";
|
|
|
4
4
|
import { useI18n } from "../../contexts/i18n-context";
|
|
5
5
|
import { useStatus } from "./contexts/status-context";
|
|
6
6
|
import { useTheme } from "./contexts/theme-context";
|
|
7
|
-
import { useTz } from "
|
|
7
|
+
import { useTz } from "../../contexts/tz-context";
|
|
8
8
|
|
|
9
9
|
const SequencedSlotButton = ({ slot }) => {
|
|
10
10
|
const i18n = useI18n();
|
|
@@ -4,7 +4,7 @@ import moment from "moment-timezone";
|
|
|
4
4
|
import { useI18n } from "../../contexts/i18n-context";
|
|
5
5
|
import { useStatus } from "./contexts/status-context";
|
|
6
6
|
import { useTheme } from "./contexts/theme-context";
|
|
7
|
-
import { useTz } from "
|
|
7
|
+
import { useTz } from "../../contexts/tz-context";
|
|
8
8
|
|
|
9
9
|
const SlotButton = ({ slot }) => {
|
|
10
10
|
const i18n = useI18n();
|
|
@@ -14,7 +14,7 @@ import SlotsList from "./SlotsList";
|
|
|
14
14
|
|
|
15
15
|
import { useStatus } from "./contexts/status-context";
|
|
16
16
|
import { useTheme } from "./contexts/theme-context";
|
|
17
|
-
import { useTz } from "
|
|
17
|
+
import { useTz } from "../../contexts/tz-context";
|
|
18
18
|
|
|
19
19
|
const Wrapper = () => {
|
|
20
20
|
const [status, dispatchStatus] = useStatus();
|
|
@@ -4,7 +4,7 @@ import { getAvailability, getSequencedAvailability } from "../../../helpers/conn
|
|
|
4
4
|
import { uniqueItems, humanizeTzName } from "../../../helpers/utils";
|
|
5
5
|
import { errorMessages } from "../../../helpers/logging";
|
|
6
6
|
|
|
7
|
-
import { defaultTimeZones } from "
|
|
7
|
+
import { defaultTimeZones } from "../../../helpers/tz-list";
|
|
8
8
|
|
|
9
9
|
export const getMonthsCoveredByPeriod = (period, tzid) => {
|
|
10
10
|
const start = moment
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from "react";
|
|
2
2
|
|
|
3
|
-
import { useTheme } from "./contexts/theme-context";
|
|
4
|
-
|
|
5
3
|
import { tzi18n } from "../../helpers/i18n";
|
|
6
|
-
import { useTz } from "./contexts/tz-context";
|
|
7
|
-
|
|
8
|
-
const TimeZoneSelector = ({ locale }) => {
|
|
9
|
-
const theme = useTheme();
|
|
10
|
-
const [tz, setTz] = useTz();
|
|
11
4
|
|
|
5
|
+
const TimeZoneSelector = ({ locale, theme, tz, setTz }) => {
|
|
12
6
|
const [showList, setShowList] = useState(() => false);
|
|
13
7
|
const [focused, setFocused] = useState(() => false);
|
|
14
8
|
|
|
@@ -31,27 +25,26 @@ const TimeZoneSelector = ({ locale }) => {
|
|
|
31
25
|
};
|
|
32
26
|
|
|
33
27
|
const handleKeyDown = e => {
|
|
28
|
+
const list = tz.list;
|
|
34
29
|
switch (e.key) {
|
|
35
30
|
case "ArrowDown":
|
|
36
31
|
e.preventDefault();
|
|
37
|
-
const nextFocusedItemIndex =
|
|
38
|
-
const nextItem =
|
|
39
|
-
nextFocusedItemIndex > tz.list.length - 1 ? 0 : nextFocusedItemIndex;
|
|
32
|
+
const nextFocusedItemIndex = list.findIndex(item => focused === item.tzid) + 1;
|
|
33
|
+
const nextItem = nextFocusedItemIndex > list.length - 1 ? 0 : nextFocusedItemIndex;
|
|
40
34
|
|
|
41
|
-
setFocused(
|
|
35
|
+
setFocused(list[nextItem].tzid);
|
|
42
36
|
|
|
43
37
|
break;
|
|
44
38
|
case "ArrowUp":
|
|
45
39
|
e.preventDefault();
|
|
46
|
-
const prevFocusedItemIndex =
|
|
47
|
-
const prevItem =
|
|
48
|
-
prevFocusedItemIndex < 0 ? tz.list.length - 1 : prevFocusedItemIndex;
|
|
40
|
+
const prevFocusedItemIndex = list.findIndex(item => focused === item.tzid) - 1;
|
|
41
|
+
const prevItem = prevFocusedItemIndex < 0 ? list.length - 1 : prevFocusedItemIndex;
|
|
49
42
|
|
|
50
|
-
setFocused(
|
|
43
|
+
setFocused(list[prevItem].tzid);
|
|
51
44
|
|
|
52
45
|
break;
|
|
53
46
|
case "Enter":
|
|
54
|
-
const tz =
|
|
47
|
+
const tz = list.find(item => focused === item.tzid);
|
|
55
48
|
handleOptionSelect(tz);
|
|
56
49
|
break;
|
|
57
50
|
case "Escape":
|
|
File without changes
|
|
File without changes
|