Skip to content

Commit ee89a0c

Browse files
authored
TimezonePicker UI Component (#467)
1 parent af2c3ac commit ee89a0c

File tree

6 files changed

+131
-55
lines changed

6 files changed

+131
-55
lines changed

src/lib/ui/AccessCodeForm/AccessCodeFormTimezonePicker.tsx

+8-40
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
11
import { useState } from 'react'
22

3-
import {
4-
getBrowserTimezone,
5-
getTimezoneLabel,
6-
getTimezoneOffset,
7-
getTimezones,
8-
} from 'lib/dates.js'
9-
import { Checkbox } from 'lib/ui/Checkbox.js'
103
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
11-
import { handleString } from 'lib/ui/TextField/TextField.js'
4+
import { TimezonePicker } from 'lib/ui/TimezonePicker/TimezonePicker.js'
125

136
interface AccessCodeFormTimezonePickerProps {
147
value: string
@@ -21,44 +14,19 @@ export function AccessCodeFormTimezonePicker({
2114
value,
2215
onClose,
2316
}: AccessCodeFormTimezonePickerProps): JSX.Element {
24-
const [manualTimezoneEnabled, setManualTimezoneEnabled] = useState(false)
25-
26-
const isBrowserTimezone = value === getBrowserTimezone()
27-
const isManualTimezone = !isBrowserTimezone || manualTimezoneEnabled
28-
29-
const handleChangeManualTimezone = (enabled: boolean): void => {
30-
setManualTimezoneEnabled(enabled)
31-
if (!enabled) {
32-
onChange(getBrowserTimezone())
33-
}
34-
}
35-
36-
const title = isManualTimezone ? t.titleManual : t.titleAuto
17+
const [title, setTitle] = useState(t.titleAuto)
3718

3819
return (
39-
<div className='seam-timezone-picker'>
20+
<div className='seam-access-code-timezone-picker'>
4021
<ContentHeader title={title} onBack={onClose} />
4122
<div className='seam-content'>
42-
<Checkbox
43-
label={t.setTimezoneManuallyLabel}
44-
checked={!isManualTimezone}
45-
onChange={(manual) => {
46-
handleChangeManualTimezone(!manual)
23+
<TimezonePicker
24+
value={value}
25+
onChange={onChange}
26+
onManualTimezoneSelected={(manualTimezoneSelected) => {
27+
setTitle(manualTimezoneSelected ? t.titleManual : t.titleAuto)
4728
}}
48-
className='seam-manual-timezone-checkbox'
4929
/>
50-
51-
<select
52-
value={value}
53-
onChange={handleString(onChange)}
54-
className='seam-timezone-select'
55-
>
56-
{getTimezones().map((timezone) => (
57-
<option value={timezone} key={timezone}>
58-
{t.utc} {getTimezoneOffset(timezone)} {getTimezoneLabel(timezone)}
59-
</option>
60-
))}
61-
</select>
6230
</div>
6331
</div>
6432
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { useArgs } from '@storybook/preview-api'
2+
import type { Meta, StoryObj } from '@storybook/react'
3+
4+
import { getBrowserTimezone } from 'lib/dates.js'
5+
import { TimezonePicker } from 'lib/ui/TimezonePicker/TimezonePicker.js'
6+
7+
const meta: Meta<typeof TimezonePicker> = {
8+
title: 'Library/TimezonePicker',
9+
tags: ['autodocs'],
10+
component: TimezonePicker,
11+
}
12+
13+
type Story = StoryObj<typeof TimezonePicker>
14+
15+
export const Content: Story = {
16+
render: (props) => {
17+
const [, setArgs] = useArgs()
18+
19+
const onChange = (timezone: string): void => {
20+
setArgs({ value: timezone })
21+
}
22+
23+
return <TimezonePicker value={props.value} onChange={onChange} />
24+
},
25+
}
26+
27+
Content.args = {
28+
value: getBrowserTimezone(),
29+
}
30+
31+
export default meta
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { useEffect, useState } from 'react'
2+
3+
import {
4+
getBrowserTimezone,
5+
getTimezoneLabel,
6+
getTimezoneOffset,
7+
getTimezones,
8+
} from 'lib/dates.js'
9+
import { Checkbox } from 'lib/ui/Checkbox.js'
10+
import { handleString } from 'lib/ui/TextField/TextField.js'
11+
12+
interface TimezonePickerProps {
13+
value: string
14+
onChange: (timezone: string) => void
15+
onManualTimezoneSelected?: (manualTimezoneSelected: boolean) => void
16+
}
17+
18+
export function TimezonePicker({
19+
onChange,
20+
value,
21+
onManualTimezoneSelected,
22+
}: TimezonePickerProps): JSX.Element {
23+
const [manualTimezoneEnabled, setManualTimezoneEnabled] = useState(false)
24+
25+
const isBrowserTimezoneSelected = value === getBrowserTimezone()
26+
const isManualTimezoneSelected =
27+
!isBrowserTimezoneSelected || manualTimezoneEnabled
28+
29+
useEffect(() => {
30+
if (onManualTimezoneSelected != null)
31+
onManualTimezoneSelected(isManualTimezoneSelected)
32+
}, [isManualTimezoneSelected, onManualTimezoneSelected])
33+
34+
const handleChangeManualTimezone = (enabled: boolean): void => {
35+
setManualTimezoneEnabled(enabled)
36+
if (!enabled) {
37+
onChange(getBrowserTimezone())
38+
}
39+
}
40+
41+
return (
42+
<div className='seam-timezone-picker'>
43+
<Checkbox
44+
label={t.setTimezoneManuallyLabel}
45+
checked={!isManualTimezoneSelected}
46+
onChange={(manual) => {
47+
handleChangeManualTimezone(!manual)
48+
}}
49+
className='seam-manual-timezone-checkbox'
50+
/>
51+
52+
<select
53+
value={value}
54+
onChange={handleString(onChange)}
55+
className='seam-timezone-select'
56+
>
57+
{getTimezones().map((timezone) => (
58+
<option value={timezone} key={timezone}>
59+
{t.utc} {getTimezoneOffset(timezone)} {getTimezoneLabel(timezone)}
60+
</option>
61+
))}
62+
</select>
63+
</div>
64+
)
65+
}
66+
67+
const t = {
68+
utc: 'UTC',
69+
setTimezoneManuallyLabel: 'Use local time zone',
70+
}

src/styles/_access-code-form.scss

+1-15
Original file line numberDiff line numberDiff line change
@@ -117,23 +117,9 @@
117117
}
118118

119119
@mixin timezone-picker {
120-
.seam-timezone-picker {
120+
.seam-access-code-timezone-picker {
121121
.seam-content {
122122
padding: 0 24px;
123-
124-
.seam-manual-timezone-checkbox {
125-
margin-bottom: 8px;
126-
}
127-
128-
> .seam-timezone-select {
129-
background: colors.$white;
130-
padding: 0 12px;
131-
width: 100%;
132-
border: 1px solid colors.$text-gray-3;
133-
border-radius: 8px;
134-
height: 48px;
135-
font-size: 16px;
136-
}
137123
}
138124
}
139125
}

src/styles/_main.scss

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
@use './switch';
2424
@use './climate-setting-schedule-form';
2525
@use './climate-setting-schedule-details';
26+
@use './timezone-picker';
2627

2728
.seam-components {
2829
// Reset
@@ -42,6 +43,7 @@
4243
@include radio-field.all;
4344
@include tooltip.all;
4445
@include switch.all;
46+
@include timezone-picker.all;
4547

4648
// Components
4749
@include device-details.all;

src/styles/_timezone-picker.scss

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
@use './colors';
2+
3+
@mixin all {
4+
.seam-timezone-picker {
5+
.seam-manual-timezone-checkbox {
6+
margin-bottom: 8px;
7+
}
8+
9+
> .seam-timezone-select {
10+
background: colors.$white;
11+
padding: 0 12px;
12+
width: 100%;
13+
border: 1px solid colors.$text-gray-3;
14+
border-radius: 8px;
15+
height: 48px;
16+
font-size: 16px;
17+
}
18+
}
19+
}

0 commit comments

Comments
 (0)