11import classNames from 'classnames'
2+ import { useState } from 'react'
23
34import { ChevronRightIcon } from 'lib/icons/ChevronRight.js'
45import { useAccessCodes } from 'lib/seam/access-codes/use-access-codes.js'
@@ -16,6 +17,7 @@ import { DeviceImage } from 'lib/ui/device/DeviceImage.js'
1617import { EditableDeviceName } from 'lib/ui/device/EditableDeviceName.js'
1718import { OnlineStatus } from 'lib/ui/device/OnlineStatus.js'
1819import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
20+ import { Snackbar , type SnackbarVariant } from 'lib/ui/Snackbar/Snackbar.js'
1921import { useToggle } from 'lib/ui/use-toggle.js'
2022
2123interface LockDeviceDetailsProps extends NestedSpecificDeviceDetailsProps {
@@ -38,11 +40,25 @@ export function LockDeviceDetails({
3840 onEditName,
3941} : LockDeviceDetailsProps ) : JSX . Element | null {
4042 const [ accessCodesOpen , toggleAccessCodesOpen ] = useToggle ( )
41- const toggleLock = useToggleLock ( )
4243 const { accessCodes } = useAccessCodes ( {
4344 device_id : device . device_id ,
4445 } )
4546
47+ const [ snackbarVisible , setSnackbarVisible ] = useState ( false )
48+ const [ snackbarVariant , setSnackbarVariant ] =
49+ useState < SnackbarVariant > ( 'success' )
50+
51+ const toggleLock = useToggleLock ( {
52+ onSuccess : ( ) => {
53+ setSnackbarVisible ( true )
54+ setSnackbarVariant ( 'success' )
55+ } ,
56+ onError : ( ) => {
57+ setSnackbarVisible ( true )
58+ setSnackbarVariant ( 'error' )
59+ } ,
60+ } )
61+
4662 const lockStatus = device . properties . locked ? t . locked : t . unlocked
4763 const toggleLockLabel = device . properties . locked ? t . unlock : t . lock
4864
@@ -88,87 +104,103 @@ export function LockDeviceDetails({
88104 ]
89105
90106 return (
91- < div className = { classNames ( 'seam-device-details' , className ) } >
92- < ContentHeader title = 'Device' onBack = { onBack } />
93- < div className = 'seam-body' >
94- < div className = 'seam-summary' >
95- < div className = 'seam-content' >
96- < div className = 'seam-image' >
97- < DeviceImage device = { device } />
98- </ div >
99- < div className = 'seam-info' >
100- < span className = 'seam-label' > { t . device } </ span >
101- < EditableDeviceName
102- tagName = 'h4'
103- value = { device . properties . name }
104- className = 'seam-device-name'
105- onEdit = { onEditName }
106- />
107- < div className = 'seam-properties' >
108- < span className = 'seam-label' > { t . status } :</ span > { ' ' }
109- < OnlineStatus device = { device } />
110- { device . properties . online && (
111- < >
112- < span className = 'seam-label' > { t . power } :</ span > { ' ' }
113- < BatteryStatusIndicator device = { device } />
114- </ >
115- ) }
116- < DeviceModel device = { device } />
107+ < >
108+ < Snackbar
109+ variant = { snackbarVariant }
110+ visible = { snackbarVisible }
111+ onClose = { ( ) => {
112+ setSnackbarVisible ( false )
113+ } }
114+ message = {
115+ snackbarVariant === 'success'
116+ ? t . successfullyUpdated
117+ : t . failedToUpdate
118+ }
119+ autoDismiss
120+ />
121+
122+ < div className = { classNames ( 'seam-device-details' , className ) } >
123+ < ContentHeader title = 'Device' onBack = { onBack } />
124+ < div className = 'seam-body' >
125+ < div className = 'seam-summary' >
126+ < div className = 'seam-content' >
127+ < div className = 'seam-image' >
128+ < DeviceImage device = { device } />
129+ </ div >
130+ < div className = 'seam-info' >
131+ < span className = 'seam-label' > { t . device } </ span >
132+ < EditableDeviceName
133+ tagName = 'h4'
134+ value = { device . properties . name }
135+ className = 'seam-device-name'
136+ onEdit = { onEditName }
137+ />
138+ < div className = 'seam-properties' >
139+ < span className = 'seam-label' > { t . status } :</ span > { ' ' }
140+ < OnlineStatus device = { device } />
141+ { device . properties . online && (
142+ < >
143+ < span className = 'seam-label' > { t . power } :</ span > { ' ' }
144+ < BatteryStatusIndicator device = { device } />
145+ </ >
146+ ) }
147+ < DeviceModel device = { device } />
148+ </ div >
117149 </ div >
118150 </ div >
151+ < Alerts alerts = { alerts } className = 'seam-alerts-space-top' />
119152 </ div >
120- < Alerts alerts = { alerts } className = 'seam-alerts-space-top' />
121- </ div >
122- < div className = 'seam-box' >
123- < div
124- className = 'seam-content seam-access-codes'
125- onClick = { toggleAccessCodesOpen }
126- >
127- < span className = 'seam-value' >
128- { accessCodeCount } { t . accessCodes }
129- </ span >
130- < ChevronRightIcon />
153+ < div className = 'seam-box' >
154+ < div
155+ className = 'seam-content seam-access-codes'
156+ onClick = { toggleAccessCodesOpen }
157+ >
158+ < span className = 'seam-value' >
159+ { accessCodeCount } { t . accessCodes }
160+ </ span >
161+ < ChevronRightIcon />
162+ </ div >
131163 </ div >
132- </ div >
133164
134- < div className = 'seam-box' >
135- { device . properties . locked && device . properties . online && (
136- < div className = 'seam-content seam-lock-status' >
137- < div >
138- < span className = 'seam-label' > { t . lockStatus } </ span >
139- < span className = 'seam-value' > { lockStatus } </ span >
140- </ div >
141- < div className = 'seam-right' >
142- { ! disableLockUnlock &&
143- device . capabilities_supported . includes ( 'lock' ) && (
144- < Button
145- size = 'small'
146- onClick = { ( ) => {
147- toggleLock . mutate ( device )
148- } }
149- >
150- { toggleLockLabel }
151- </ Button >
152- ) }
165+ < div className = 'seam-box' >
166+ { device . properties . locked && device . properties . online && (
167+ < div className = 'seam-content seam-lock-status' >
168+ < div >
169+ < span className = 'seam-label' > { t . lockStatus } </ span >
170+ < span className = 'seam-value' > { lockStatus } </ span >
171+ </ div >
172+ < div className = 'seam-right' >
173+ { ! disableLockUnlock &&
174+ device . capabilities_supported . includes ( 'lock' ) && (
175+ < Button
176+ size = 'small'
177+ onClick = { ( ) => {
178+ toggleLock . mutate ( device )
179+ } }
180+ >
181+ { toggleLockLabel }
182+ </ Button >
183+ ) }
184+ </ div >
153185 </ div >
154- </ div >
155- ) }
186+ ) }
156187
157- < AccessCodeLength
158- supportedCodeLengths = {
159- device . properties ?. supported_code_lengths ?? [ ]
188+ < AccessCodeLength
189+ supportedCodeLengths = {
190+ device . properties ?. supported_code_lengths ?? [ ]
191+ }
192+ />
193+ </ div >
194+ < DeviceInfo
195+ device = { device }
196+ disableConnectedAccountInformation = {
197+ disableConnectedAccountInformation
160198 }
199+ disableResourceIds = { disableResourceIds }
161200 />
162201 </ div >
163- < DeviceInfo
164- device = { device }
165- disableConnectedAccountInformation = {
166- disableConnectedAccountInformation
167- }
168- disableResourceIds = { disableResourceIds }
169- />
170202 </ div >
171- </ div >
203+ </ >
172204 )
173205}
174206
@@ -208,4 +240,6 @@ const t = {
208240 lockStatus : 'Lock status' ,
209241 status : 'Status' ,
210242 power : 'Power' ,
243+ successfullyUpdated : 'Lock status has been successfully updated' ,
244+ failedToUpdate : 'Failed to update lock status' ,
211245}
0 commit comments