@seamapi/react 3.1.1 → 4.0.0-beta.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.
Files changed (138) hide show
  1. package/README.md +2 -2
  2. package/dist/elements.js +9897 -10374
  3. package/dist/elements.js.map +1 -1
  4. package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.d.ts +1 -1
  5. package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.js +3 -3
  6. package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.js.map +1 -1
  7. package/lib/seam/components/AccessCodeTable/AccessCodeTable.d.ts +1 -1
  8. package/lib/seam/components/AccessCodeTable/AccessCodeTable.js +4 -4
  9. package/lib/seam/components/AccessCodeTable/AccessCodeTable.js.map +1 -1
  10. package/lib/seam/components/DeviceDetails/DeviceDetails.d.ts +1 -1
  11. package/lib/seam/components/DeviceDetails/DeviceDetails.js +1 -2
  12. package/lib/seam/components/DeviceDetails/DeviceDetails.js.map +1 -1
  13. package/lib/seam/components/DeviceDetails/LockDeviceDetails.d.ts +1 -1
  14. package/lib/seam/components/DeviceDetails/LockDeviceDetails.js +2 -2
  15. package/lib/seam/components/DeviceDetails/LockDeviceDetails.js.map +1 -1
  16. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.d.ts +1 -1
  17. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js +2 -40
  18. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js.map +1 -1
  19. package/lib/seam/components/DeviceTable/DeviceTable.d.ts +1 -1
  20. package/lib/seam/components/DeviceTable/DeviceTable.js +2 -2
  21. package/lib/seam/components/DeviceTable/DeviceTable.js.map +1 -1
  22. package/lib/seam/components/common-props.d.ts +0 -1
  23. package/lib/seam/components/common-props.js.map +1 -1
  24. package/lib/seam/components/index.d.ts +0 -2
  25. package/lib/seam/components/index.js +0 -2
  26. package/lib/seam/components/index.js.map +1 -1
  27. package/lib/seam/index.d.ts +0 -2
  28. package/lib/seam/index.js +0 -2
  29. package/lib/seam/index.js.map +1 -1
  30. package/lib/ui/AccessCodeForm/AccessCodeForm.js +3 -3
  31. package/lib/ui/AccessCodeForm/AccessCodeForm.js.map +1 -1
  32. package/lib/ui/thermostat/FanModeMenu.js +1 -0
  33. package/lib/ui/thermostat/FanModeMenu.js.map +1 -1
  34. package/lib/version.d.ts +1 -1
  35. package/lib/version.js +1 -1
  36. package/lib/version.js.map +1 -1
  37. package/package.json +3 -3
  38. package/src/lib/element.tsx +0 -1
  39. package/src/lib/seam/components/AccessCodeDetails/AccessCodeDetails.tsx +0 -3
  40. package/src/lib/seam/components/AccessCodeTable/AccessCodeTable.tsx +0 -4
  41. package/src/lib/seam/components/DeviceDetails/DeviceDetails.tsx +0 -2
  42. package/src/lib/seam/components/DeviceDetails/LockDeviceDetails.tsx +0 -2
  43. package/src/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.tsx +0 -137
  44. package/src/lib/seam/components/DeviceTable/DeviceTable.tsx +0 -2
  45. package/src/lib/seam/components/common-props.tsx +0 -1
  46. package/src/lib/seam/components/elements.ts +0 -2
  47. package/src/lib/seam/components/index.ts +0 -2
  48. package/src/lib/seam/index.ts +0 -2
  49. package/src/lib/ui/AccessCodeForm/AccessCodeForm.tsx +3 -4
  50. package/src/lib/ui/thermostat/FanModeMenu.tsx +1 -0
  51. package/src/lib/version.ts +1 -1
  52. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleCard.d.ts +0 -7
  53. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleCard.js +0 -43
  54. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleCard.js.map +0 -1
  55. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.d.ts +0 -7
  56. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.js +0 -55
  57. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.js.map +0 -1
  58. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDeviceBar.d.ts +0 -5
  59. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDeviceBar.js +0 -31
  60. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDeviceBar.js.map +0 -1
  61. package/lib/seam/components/ClimateSettingScheduleDetails/dates.d.ts +0 -1
  62. package/lib/seam/components/ClimateSettingScheduleDetails/dates.js +0 -9
  63. package/lib/seam/components/ClimateSettingScheduleDetails/dates.js.map +0 -1
  64. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleRow.d.ts +0 -8
  65. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleRow.js +0 -10
  66. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleRow.js.map +0 -1
  67. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleRowDetails.d.ts +0 -5
  68. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleRowDetails.js +0 -28
  69. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleRowDetails.js.map +0 -1
  70. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.d.ts +0 -14
  71. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.js +0 -80
  72. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.js.map +0 -1
  73. package/lib/seam/components/CreateClimateSettingScheduleForm/CreateClimateSettingScheduleForm.d.ts +0 -5
  74. package/lib/seam/components/CreateClimateSettingScheduleForm/CreateClimateSettingScheduleForm.js +0 -29
  75. package/lib/seam/components/CreateClimateSettingScheduleForm/CreateClimateSettingScheduleForm.js.map +0 -1
  76. package/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedule.d.ts +0 -6
  77. package/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedule.js +0 -16
  78. package/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedule.js.map +0 -1
  79. package/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.d.ts +0 -6
  80. package/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.js +0 -28
  81. package/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.js.map +0 -1
  82. package/lib/seam/thermostats/climate-setting-schedules/use-create-climate-setting-schedule.d.ts +0 -7
  83. package/lib/seam/thermostats/climate-setting-schedules/use-create-climate-setting-schedule.js +0 -25
  84. package/lib/seam/thermostats/climate-setting-schedules/use-create-climate-setting-schedule.js.map +0 -1
  85. package/lib/seam/thermostats/climate-setting-schedules/use-delete-climate-setting-schedule.d.ts +0 -6
  86. package/lib/seam/thermostats/climate-setting-schedules/use-delete-climate-setting-schedule.js +0 -27
  87. package/lib/seam/thermostats/climate-setting-schedules/use-delete-climate-setting-schedule.js.map +0 -1
  88. package/lib/seam/thermostats/climate-setting-schedules/use-update-climate-setting-schedule.d.ts +0 -6
  89. package/lib/seam/thermostats/climate-setting-schedules/use-update-climate-setting-schedule.js +0 -46
  90. package/lib/seam/thermostats/climate-setting-schedules/use-update-climate-setting-schedule.js.map +0 -1
  91. package/lib/seam/thermostats/use-update-thermostat.d.ts +0 -6
  92. package/lib/seam/thermostats/use-update-thermostat.js +0 -51
  93. package/lib/seam/thermostats/use-update-thermostat.js.map +0 -1
  94. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleForm.d.ts +0 -32
  95. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleForm.js +0 -85
  96. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleForm.js.map +0 -1
  97. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormClimateSetting.d.ts +0 -13
  98. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormClimateSetting.js +0 -44
  99. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormClimateSetting.js.map +0 -1
  100. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormDefaultClimateSetting.d.ts +0 -10
  101. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormDefaultClimateSetting.js +0 -24
  102. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormDefaultClimateSetting.js.map +0 -1
  103. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormDeviceSelect.d.ts +0 -10
  104. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormDeviceSelect.js +0 -10
  105. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormDeviceSelect.js.map +0 -1
  106. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormNameAndSchedule.d.ts +0 -15
  107. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormNameAndSchedule.js +0 -30
  108. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormNameAndSchedule.js.map +0 -1
  109. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormTimeZonePicker.d.ts +0 -9
  110. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormTimeZonePicker.js +0 -16
  111. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormTimeZonePicker.js.map +0 -1
  112. package/lib/ui/ClimateSettingForm/set-point-bounds.d.ts +0 -4
  113. package/lib/ui/ClimateSettingForm/set-point-bounds.js +0 -17
  114. package/lib/ui/ClimateSettingForm/set-point-bounds.js.map +0 -1
  115. package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleCard.tsx +0 -107
  116. package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.element.ts +0 -11
  117. package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.tsx +0 -175
  118. package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDeviceBar.tsx +0 -72
  119. package/src/lib/seam/components/ClimateSettingScheduleDetails/dates.ts +0 -10
  120. package/src/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleRow.tsx +0 -35
  121. package/src/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleRowDetails.tsx +0 -60
  122. package/src/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.element.ts +0 -17
  123. package/src/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.tsx +0 -220
  124. package/src/lib/seam/components/CreateClimateSettingScheduleForm/CreateClimateSettingScheduleForm.element.ts +0 -9
  125. package/src/lib/seam/components/CreateClimateSettingScheduleForm/CreateClimateSettingScheduleForm.tsx +0 -56
  126. package/src/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedule.ts +0 -34
  127. package/src/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.ts +0 -53
  128. package/src/lib/seam/thermostats/climate-setting-schedules/use-create-climate-setting-schedule.ts +0 -53
  129. package/src/lib/seam/thermostats/climate-setting-schedules/use-delete-climate-setting-schedule.ts +0 -51
  130. package/src/lib/seam/thermostats/climate-setting-schedules/use-update-climate-setting-schedule.ts +0 -83
  131. package/src/lib/seam/thermostats/use-update-thermostat.ts +0 -90
  132. package/src/lib/ui/ClimateSettingForm/ClimateSettingScheduleForm.tsx +0 -189
  133. package/src/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormClimateSetting.tsx +0 -118
  134. package/src/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormDefaultClimateSetting.tsx +0 -79
  135. package/src/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormDeviceSelect.tsx +0 -36
  136. package/src/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormNameAndSchedule.tsx +0 -120
  137. package/src/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormTimeZonePicker.tsx +0 -43
  138. package/src/lib/ui/ClimateSettingForm/set-point-bounds.ts +0 -31
@@ -1,175 +0,0 @@
1
- import classNames from 'classnames'
2
- import { useState } from 'react'
3
-
4
- import { ArrowRightIcon } from 'lib/icons/ArrowRight.js'
5
- import { ClimateSettingScheduleCard } from 'lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleCard.js'
6
- import {
7
- type CommonProps,
8
- withRequiredCommonProps,
9
- } from 'lib/seam/components/common-props.js'
10
- import { NestedDeviceDetails } from 'lib/seam/components/DeviceDetails/DeviceDetails.js'
11
- import { useClimateSettingSchedule } from 'lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedule.js'
12
- import { useUpdateClimateSettingSchedule } from 'lib/seam/thermostats/climate-setting-schedules/use-update-climate-setting-schedule.js'
13
- import { useComponentTelemetry } from 'lib/telemetry/index.js'
14
- import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
15
- import { DetailRow } from 'lib/ui/layout/DetailRow.js'
16
- import { DetailSection } from 'lib/ui/layout/DetailSection.js'
17
- import { DetailSectionGroup } from 'lib/ui/layout/DetailSectionGroup.js'
18
- import { Snackbar } from 'lib/ui/Snackbar/Snackbar.js'
19
- import { Switch } from 'lib/ui/Switch/Switch.js'
20
- import { ClimateSettingStatus } from 'lib/ui/thermostat/ClimateSettingStatus.js'
21
-
22
- import { formatDateTime } from './dates.js'
23
-
24
- export interface ClimateSettingScheduleDetailsProps extends CommonProps {
25
- climateSettingScheduleId: string
26
- }
27
-
28
- export const NestedClimateSettingScheduleDetails = withRequiredCommonProps(
29
- ClimateSettingScheduleDetails
30
- )
31
-
32
- export function ClimateSettingScheduleDetails({
33
- climateSettingScheduleId,
34
- disableLockUnlock = false,
35
- disableDeleteAccessCode = false,
36
- onBack,
37
- className,
38
- errorFilter = () => true,
39
- warningFilter = () => true,
40
- disableCreateAccessCode,
41
- disableEditAccessCode,
42
- disableResourceIds = false,
43
- disableConnectedAccountInformation = false,
44
- disableClimateSettingSchedules,
45
- }: ClimateSettingScheduleDetailsProps): JSX.Element | null {
46
- useComponentTelemetry('ClimateSettingScheduleDetails')
47
-
48
- const { climateSettingSchedule } = useClimateSettingSchedule({
49
- climate_setting_schedule_id: climateSettingScheduleId,
50
- })
51
-
52
- const { mutate, isSuccess, isError } = useUpdateClimateSettingSchedule()
53
-
54
- const [selectedDeviceId, selectDevice] = useState<string | null>(null)
55
-
56
- if (climateSettingSchedule == null) {
57
- return null
58
- }
59
-
60
- const isManualOverrideAllowed =
61
- climateSettingSchedule.manual_override_allowed ?? false
62
-
63
- if (selectedDeviceId != null) {
64
- return (
65
- <NestedDeviceDetails
66
- deviceId={selectedDeviceId}
67
- errorFilter={errorFilter}
68
- warningFilter={warningFilter}
69
- disableLockUnlock={disableLockUnlock}
70
- disableCreateAccessCode={disableCreateAccessCode}
71
- disableEditAccessCode={disableEditAccessCode}
72
- disableDeleteAccessCode={disableDeleteAccessCode}
73
- disableResourceIds={disableResourceIds}
74
- disableConnectedAccountInformation={disableConnectedAccountInformation}
75
- disableClimateSettingSchedules={disableClimateSettingSchedules}
76
- onBack={() => {
77
- selectDevice(null)
78
- }}
79
- className={className}
80
- />
81
- )
82
- }
83
-
84
- return (
85
- <>
86
- <div
87
- className={classNames(
88
- 'seam-climate-setting-schedule-details',
89
- className
90
- )}
91
- >
92
- <ContentHeader title={t.climateSettingSchedule} onBack={onBack} />
93
- <div className='seam-climate-setting-schedule-details-content'>
94
- <ClimateSettingScheduleCard
95
- climateSettingScheduleId={climateSettingScheduleId}
96
- onSelectDevice={selectDevice}
97
- />
98
- <div className='seam-default-setting-message-container'>
99
- <span className='seam-default-setting-message'>
100
- {t.defaultSettingMessagePart1}{' '}
101
- <span className='seam-default-setting-text'>
102
- {t.defaultSetting}
103
- </span>{' '}
104
- {t.defaultSettingMessagePart2}
105
- </span>
106
- </div>
107
- <DetailSectionGroup>
108
- <DetailSection>
109
- <DetailRow label={t.startEndTime}>
110
- <span className='seam-climate-setting-details-value seam-climate-setting-details-schedule-range'>
111
- {formatDateTime(climateSettingSchedule.schedule_starts_at)}
112
- <ArrowRightIcon />
113
- {formatDateTime(climateSettingSchedule.schedule_ends_at)}
114
- </span>
115
- </DetailRow>
116
- <DetailRow label={t.climateSetting}>
117
- <ClimateSettingStatus
118
- climateSetting={climateSettingSchedule}
119
- iconPlacement='right'
120
- />
121
- </DetailRow>
122
- <DetailRow label={t.allowManualOverride}>
123
- <span className='seam-climate-setting-details-value'>
124
- <Switch
125
- checked={isManualOverrideAllowed}
126
- onChange={(checked) => {
127
- mutate({
128
- climate_setting_schedule_id:
129
- climateSettingSchedule.climate_setting_schedule_id,
130
- manual_override_allowed: checked,
131
- })
132
- }}
133
- />
134
- </span>
135
- </DetailRow>
136
- </DetailSection>
137
- <DetailSection>
138
- <DetailRow label={t.creationDate}>
139
- <div className='seam-creation-date'>
140
- {formatDateTime(climateSettingSchedule.created_at)}
141
- </div>
142
- </DetailRow>
143
- </DetailSection>
144
- </DetailSectionGroup>
145
- </div>
146
- </div>
147
- <Snackbar
148
- message={t.manualOverrideSuccess}
149
- variant='success'
150
- visible={isSuccess}
151
- automaticVisibility
152
- />
153
-
154
- <Snackbar
155
- message={t.manualOverrideError}
156
- variant='error'
157
- visible={isError}
158
- automaticVisibility
159
- />
160
- </>
161
- )
162
- }
163
-
164
- const t = {
165
- climateSettingSchedule: 'Climate setting schedule',
166
- startEndTime: 'Start/End Time',
167
- climateSetting: 'Climate setting',
168
- allowManualOverride: 'Allow manual override',
169
- creationDate: 'Creation date',
170
- defaultSettingMessagePart1: 'Thermostat will return to its',
171
- defaultSetting: 'default setting',
172
- defaultSettingMessagePart2: 'at end time.',
173
- manualOverrideSuccess: 'Successfully updated manual override!',
174
- manualOverrideError: 'Error updating manual override. Please try again.',
175
- }
@@ -1,72 +0,0 @@
1
- import { ChevronWideIcon } from 'lib/icons/ChevronWide.js'
2
- import { useDevice } from 'lib/seam/devices/use-device.js'
3
- import {
4
- isThermostatDevice,
5
- type ThermostatDevice,
6
- } from 'lib/seam/thermostats/thermostat-device.js'
7
- import { DeviceImage } from 'lib/ui/device/DeviceImage.js'
8
- import { ClimateSettingStatus } from 'lib/ui/thermostat/ClimateSettingStatus.js'
9
-
10
- export function ClimateSettingScheduleDeviceBar({
11
- deviceId,
12
- onSelectDevice,
13
- }: {
14
- deviceId: string
15
- onSelectDevice: (deviceId: string) => void
16
- }): JSX.Element | null {
17
- const { isPending, device } = useDevice({
18
- device_id: deviceId,
19
- })
20
-
21
- if (isPending) {
22
- return null
23
- }
24
-
25
- if (device == null) {
26
- return null
27
- }
28
-
29
- if (!isThermostatDevice(device)) {
30
- return null
31
- }
32
-
33
- return <Content device={device} onSelectDevice={onSelectDevice} />
34
- }
35
-
36
- function Content(props: {
37
- device: ThermostatDevice
38
- onSelectDevice: (deviceId: string) => void
39
- }): JSX.Element {
40
- const { device, onSelectDevice } = props
41
-
42
- return (
43
- <div
44
- className='seam-climate-setting-schedule-device-bar'
45
- onClick={() => {
46
- onSelectDevice(device.device_id)
47
- }}
48
- >
49
- <div className='seam-climate-setting-schedule-device-content'>
50
- <div className='seam-device-image'>
51
- <DeviceImage device={device} />
52
- </div>
53
- <div className='seam-climate-setting-schedule-device-details'>
54
- <div className='seam-device-name'>{device.properties.name}</div>
55
- <div className='seam-device-current-climate-setting'>
56
- {t.currentClimate}:
57
- <ClimateSettingStatus
58
- climateSetting={device.properties.current_climate_setting}
59
- />
60
- </div>
61
- </div>
62
- </div>
63
- <div className='seam-climate-setting-schedule-device-chevron'>
64
- <ChevronWideIcon />
65
- </div>
66
- </div>
67
- )
68
- }
69
-
70
- const t = {
71
- currentClimate: 'Current climate',
72
- }
@@ -1,10 +0,0 @@
1
- import { DateTime } from 'luxon'
2
-
3
- export const formatDateTime = (date: string): string =>
4
- DateTime.fromISO(date).toLocaleString({
5
- month: 'short',
6
- day: 'numeric',
7
- hour: 'numeric',
8
- minute: '2-digit',
9
- timeZoneName: 'short',
10
- })
@@ -1,35 +0,0 @@
1
- import type { ClimateSettingSchedule } from '@seamapi/types/connect'
2
-
3
- import { ClimateSettingScheduleIcon } from 'lib/icons/ClimateSettingSchedule.js'
4
- import { ClimateSettingScheduleRowDetails } from 'lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleRowDetails.js'
5
- import { TableCell } from 'lib/ui/Table/TableCell.js'
6
- import { TableRow } from 'lib/ui/Table/TableRow.js'
7
- import { Title } from 'lib/ui/typography/Title.js'
8
-
9
- interface ClimateSettingScheduleRowProps {
10
- climateSettingSchedule: ClimateSettingSchedule
11
- onClick: () => void
12
- }
13
-
14
- export function ClimateSettingScheduleRow({
15
- climateSettingSchedule,
16
- onClick,
17
- }: ClimateSettingScheduleRowProps): JSX.Element {
18
- return (
19
- <TableRow onClick={onClick}>
20
- <TableCell className='seam-icon-cell'>
21
- <div>
22
- <ClimateSettingScheduleIcon />
23
- </div>
24
- </TableCell>
25
- <TableCell className='seam-name-cell'>
26
- <Title className='seam-truncated-text'>
27
- {climateSettingSchedule.name}
28
- </Title>
29
- <ClimateSettingScheduleRowDetails
30
- climateSettingSchedule={climateSettingSchedule}
31
- />
32
- </TableCell>
33
- </TableRow>
34
- )
35
- }
@@ -1,60 +0,0 @@
1
- import type { ClimateSettingSchedule } from '@seamapi/types/connect'
2
- import { DateTime } from 'luxon'
3
-
4
- import { useDevice } from 'lib/seam/devices/use-device.js'
5
- import { DotDivider } from 'lib/ui/layout/DotDivider.js'
6
- import { ClimateSettingStatus } from 'lib/ui/thermostat/ClimateSettingStatus.js'
7
- import { useIsDateInPast } from 'lib/ui/use-is-date-in-past.js'
8
-
9
- export function ClimateSettingScheduleRowDetails(props: {
10
- climateSettingSchedule: ClimateSettingSchedule
11
- }): JSX.Element {
12
- const { climateSettingSchedule } = props
13
- const { device } = useDevice({ device_id: climateSettingSchedule.device_id })
14
-
15
- return (
16
- <div className='seam-details'>
17
- <span className='seam-device-name seam-truncated-text'>
18
- {device?.properties.name}
19
- </span>
20
- <DotDivider />
21
- <Duration climateSettingSchedule={climateSettingSchedule} />
22
- <DotDivider />
23
- <ClimateSettingStatus climateSetting={climateSettingSchedule} />
24
- </div>
25
- )
26
- }
27
-
28
- function Duration(props: {
29
- climateSettingSchedule: ClimateSettingSchedule
30
- }): JSX.Element {
31
- const { climateSettingSchedule } = props
32
-
33
- const hasStarted =
34
- useIsDateInPast(climateSettingSchedule.schedule_starts_at) ?? false
35
-
36
- if (hasStarted) {
37
- return (
38
- <span>
39
- {t.ends} {formatDate(climateSettingSchedule.schedule_ends_at)}{' '}
40
- </span>
41
- )
42
- }
43
-
44
- return (
45
- <span>
46
- {t.starts} {formatDate(climateSettingSchedule.schedule_starts_at)}
47
- </span>
48
- )
49
- }
50
-
51
- const formatDate = (date: string): string =>
52
- DateTime.fromISO(date).toLocaleString({
53
- month: 'long',
54
- day: 'numeric',
55
- })
56
-
57
- const t = {
58
- starts: 'Starts',
59
- ends: 'Ends',
60
- }
@@ -1,17 +0,0 @@
1
- import type { ElementProps } from 'lib/element.js'
2
-
3
- import type { ClimateSettingScheduleTableProps } from './ClimateSettingScheduleTable.js'
4
-
5
- export const name = 'seam-climate-setting-schedule-table'
6
-
7
- export const props: ElementProps<ClimateSettingScheduleTableProps> = {
8
- deviceId: 'string',
9
- disableSearch: 'boolean',
10
- onClimateSettingScheduleClick: 'object',
11
- preventDefaultOnClimateSettingScheduleClick: 'boolean',
12
- climateSettingScheduleFilter: 'object',
13
- climateSettingScheduleComparator: 'object',
14
- heading: 'string',
15
- }
16
-
17
- export { ClimateSettingScheduleTable as Component } from './ClimateSettingScheduleTable.js'
@@ -1,220 +0,0 @@
1
- import type { ClimateSettingSchedule } from '@seamapi/types/connect'
2
- import classNames from 'classnames'
3
- import { useCallback, useMemo, useState } from 'react'
4
-
5
- import { compareByCreatedAtDesc } from 'lib/dates.js'
6
- import { NestedClimateSettingScheduleDetails } from 'lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.js'
7
- import { ClimateSettingScheduleRow } from 'lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleRow.js'
8
- import {
9
- type CommonProps,
10
- withRequiredCommonProps,
11
- } from 'lib/seam/components/common-props.js'
12
- import { useClimateSettingSchedules } from 'lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.js'
13
- import { useComponentTelemetry } from 'lib/telemetry/index.js'
14
- import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
15
- import { LoadingToast } from 'lib/ui/LoadingToast/LoadingToast.js'
16
- import { Snackbar } from 'lib/ui/Snackbar/Snackbar.js'
17
- import { EmptyPlaceholder } from 'lib/ui/Table/EmptyPlaceholder.js'
18
- import { TableBody } from 'lib/ui/Table/TableBody.js'
19
- import { TableHeader } from 'lib/ui/Table/TableHeader.js'
20
- import { TableTitle } from 'lib/ui/Table/TableTitle.js'
21
- import { SearchTextField } from 'lib/ui/TextField/SearchTextField.js'
22
- import { Caption } from 'lib/ui/typography/Caption.js'
23
-
24
- export const NestedClimateSettingScheduleTable = withRequiredCommonProps(
25
- ClimateSettingScheduleTable
26
- )
27
-
28
- export interface ClimateSettingScheduleTableProps extends CommonProps {
29
- deviceId: string
30
- disableSearch?: boolean
31
- onClimateSettingScheduleClick?: (climateSettingScheduleId: string) => void
32
- preventDefaultOnClimateSettingScheduleClick?: boolean
33
- climateSettingScheduleFilter?: (
34
- climateSettingSchedule: ClimateSettingSchedule,
35
- searchInputValue: string
36
- ) => boolean
37
- climateSettingScheduleComparator?: (
38
- climateSettingScheduleA: ClimateSettingSchedule,
39
- climateSettingScheduleB: ClimateSettingSchedule
40
- ) => number
41
- heading?: string | null
42
- }
43
-
44
- const defaultClimateSettingScheduleFilter = (
45
- climateSettingSchedule: ClimateSettingSchedule,
46
- searchInputValue: string
47
- ): boolean => {
48
- const value = searchInputValue.trim().toLowerCase()
49
- if (value === '') return true
50
- const name = climateSettingSchedule.name ?? ''
51
- return name.trim().toLowerCase().includes(value)
52
- }
53
-
54
- export function ClimateSettingScheduleTable({
55
- deviceId,
56
- disableSearch = false,
57
- onClimateSettingScheduleClick = () => {},
58
- preventDefaultOnClimateSettingScheduleClick = false,
59
- climateSettingScheduleFilter = defaultClimateSettingScheduleFilter,
60
- climateSettingScheduleComparator = compareByCreatedAtDesc,
61
- heading = t.climateSettingSchedules,
62
- disableLockUnlock = false,
63
- disableDeleteAccessCode = false,
64
- onBack,
65
- className,
66
- errorFilter = () => true,
67
- warningFilter = () => true,
68
- disableCreateAccessCode,
69
- disableEditAccessCode,
70
- disableResourceIds = false,
71
- disableConnectedAccountInformation = false,
72
- disableClimateSettingSchedules,
73
- }: ClimateSettingScheduleTableProps): JSX.Element {
74
- useComponentTelemetry('ClimateSettingScheduleTable')
75
-
76
- const { climateSettingSchedules, isInitialLoading, isError, refetch } =
77
- useClimateSettingSchedules({
78
- device_id: deviceId,
79
- })
80
-
81
- const [searchInputValue, setSearchInputValue] = useState('')
82
- const [
83
- selectedViewClimateSettingScheduleId,
84
- setSelectedViewClimateSettingScheduleId,
85
- ] = useState<string | null>(null)
86
-
87
- const filteredClimateSettingSchedules = useMemo(
88
- () =>
89
- climateSettingSchedules
90
- ?.filter((schedule) =>
91
- climateSettingScheduleFilter(schedule, searchInputValue)
92
- )
93
- ?.sort(climateSettingScheduleComparator) ?? [],
94
- [
95
- climateSettingSchedules,
96
- searchInputValue,
97
- climateSettingScheduleFilter,
98
- climateSettingScheduleComparator,
99
- ]
100
- )
101
-
102
- const handleClimateSettingScheduleClick = useCallback(
103
- (climateSettingScheduleId: string): void => {
104
- onClimateSettingScheduleClick(climateSettingScheduleId)
105
- if (preventDefaultOnClimateSettingScheduleClick) return
106
- setSelectedViewClimateSettingScheduleId(climateSettingScheduleId)
107
- },
108
- [
109
- onClimateSettingScheduleClick,
110
- preventDefaultOnClimateSettingScheduleClick,
111
- setSelectedViewClimateSettingScheduleId,
112
- ]
113
- )
114
-
115
- if (selectedViewClimateSettingScheduleId != null) {
116
- return (
117
- <NestedClimateSettingScheduleDetails
118
- climateSettingScheduleId={selectedViewClimateSettingScheduleId}
119
- errorFilter={errorFilter}
120
- warningFilter={warningFilter}
121
- disableLockUnlock={disableLockUnlock}
122
- disableCreateAccessCode={disableCreateAccessCode}
123
- disableEditAccessCode={disableEditAccessCode}
124
- disableDeleteAccessCode={disableDeleteAccessCode}
125
- disableResourceIds={disableResourceIds}
126
- disableConnectedAccountInformation={disableConnectedAccountInformation}
127
- disableClimateSettingSchedules={disableClimateSettingSchedules}
128
- onBack={() => {
129
- setSelectedViewClimateSettingScheduleId(null)
130
- }}
131
- className={className}
132
- />
133
- )
134
- }
135
-
136
- return (
137
- <div className={classNames('seam-table', className)}>
138
- <ContentHeader onBack={onBack} />
139
- <TableHeader>
140
- {heading != null ? (
141
- <TableTitle>
142
- {heading ?? t.climateSettingSchedules}{' '}
143
- <Caption>({filteredClimateSettingSchedules.length})</Caption>
144
- </TableTitle>
145
- ) : (
146
- <div className='seam-fragment' />
147
- )}
148
- <div className='seam-table-header-loading-wrap'>
149
- <LoadingToast
150
- isLoading={isInitialLoading}
151
- label={t.loading}
152
- top={-20}
153
- />
154
- </div>
155
- {!disableSearch && (
156
- <SearchTextField
157
- value={searchInputValue}
158
- onChange={setSearchInputValue}
159
- disabled={(climateSettingSchedules?.length ?? 0) === 0}
160
- />
161
- )}
162
- </TableHeader>
163
- <TableBody>
164
- <Content
165
- climateSettingSchedules={filteredClimateSettingSchedules}
166
- onClimateSettingScheduleClick={handleClimateSettingScheduleClick}
167
- />
168
- </TableBody>
169
-
170
- <Snackbar
171
- variant='error'
172
- visible={isError}
173
- message={t.fallbackErrorMessage}
174
- action={{
175
- label: t.tryAgain,
176
- onClick: () => {
177
- void refetch()
178
- },
179
- }}
180
- disableCloseButton
181
- />
182
- </div>
183
- )
184
- }
185
-
186
- function Content(props: {
187
- climateSettingSchedules: ClimateSettingSchedule[]
188
- onClimateSettingScheduleClick: (climateSettingScheduleId: string) => void
189
- }): JSX.Element {
190
- const { climateSettingSchedules, onClimateSettingScheduleClick } = props
191
-
192
- if (climateSettingSchedules.length === 0) {
193
- return (
194
- <EmptyPlaceholder>{t.noClimateSettingSchedulesMessage}</EmptyPlaceholder>
195
- )
196
- }
197
-
198
- return (
199
- <>
200
- {climateSettingSchedules.map((schedule) => (
201
- <ClimateSettingScheduleRow
202
- climateSettingSchedule={schedule}
203
- key={schedule.climate_setting_schedule_id}
204
- onClick={() => {
205
- onClimateSettingScheduleClick(schedule.climate_setting_schedule_id)
206
- }}
207
- />
208
- ))}
209
- </>
210
- )
211
- }
212
-
213
- const t = {
214
- climateSettingSchedules: 'Climate setting schedules',
215
- noClimateSettingSchedulesMessage:
216
- 'Sorry, no climate setting schedules were found',
217
- loading: 'Loading schedules',
218
- tryAgain: 'Try again',
219
- fallbackErrorMessage: 'Climate settings could not be loaded',
220
- }
@@ -1,9 +0,0 @@
1
- import type { ElementProps } from 'lib/element.js'
2
-
3
- import type { CreateClimateSettingScheduleFormProps } from './CreateClimateSettingScheduleForm.js'
4
-
5
- export const name = 'seam-create-climate-setting-schedule-form'
6
-
7
- export const props: ElementProps<CreateClimateSettingScheduleFormProps> = {}
8
-
9
- export { CreateClimateSettingScheduleForm as Component } from './CreateClimateSettingScheduleForm.js'
@@ -1,56 +0,0 @@
1
- import type { CommonProps } from 'lib/seam/components/common-props.js'
2
- import { useCreateClimateSettingSchedule } from 'lib/seam/thermostats/climate-setting-schedules/use-create-climate-setting-schedule.js'
3
- import { useComponentTelemetry } from 'lib/telemetry/index.js'
4
- import {
5
- ClimateSettingScheduleForm,
6
- type ClimateSettingScheduleFormSubmitData,
7
- } from 'lib/ui/ClimateSettingForm/ClimateSettingScheduleForm.js'
8
-
9
- export interface CreateClimateSettingScheduleFormProps extends CommonProps {}
10
-
11
- export function CreateClimateSettingScheduleForm({
12
- className,
13
- onBack,
14
- }: CreateClimateSettingScheduleFormProps): JSX.Element | null {
15
- useComponentTelemetry('CreateClimateSettingScheduleForm')
16
-
17
- const { submit, isSubmitting } = useSubmitCreateClimateSettingSchedule(onBack)
18
-
19
- return (
20
- <ClimateSettingScheduleForm
21
- className={className}
22
- onBack={onBack}
23
- onSubmit={submit}
24
- isSubmitting={isSubmitting}
25
- />
26
- )
27
- }
28
-
29
- function useSubmitCreateClimateSettingSchedule(onSuccess?: () => void): {
30
- submit: (data: ClimateSettingScheduleFormSubmitData) => void
31
- isSubmitting: boolean
32
- } {
33
- const { mutate, isPending: isSubmitting } = useCreateClimateSettingSchedule()
34
- const submit = (data: ClimateSettingScheduleFormSubmitData): void => {
35
- const { name, deviceId, startDate, endDate, climateSetting } = data
36
-
37
- if (isSubmitting) {
38
- return
39
- }
40
-
41
- mutate(
42
- {
43
- name,
44
- device_id: deviceId,
45
- schedule_starts_at: startDate,
46
- schedule_ends_at: endDate,
47
- ...climateSetting,
48
- },
49
- {
50
- onSuccess,
51
- }
52
- )
53
- }
54
-
55
- return { submit, isSubmitting }
56
- }