@seamapi/react 4.13.0 → 4.13.2

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.
@@ -0,0 +1,101 @@
1
+ import type {
2
+ SeamActionAttemptFailedError,
3
+ SeamActionAttemptTimeoutError,
4
+ SeamHttpApiError,
5
+ } from '@seamapi/http/connect'
6
+ import { NullSeamClientError, useSeamClient } from '@seamapi/react-query'
7
+ import type { ActionAttempt, Device } from '@seamapi/types/connect'
8
+ import {
9
+ useMutation,
10
+ type UseMutationResult,
11
+ useQueryClient,
12
+ } from '@tanstack/react-query'
13
+
14
+ export type UseLockData = undefined
15
+
16
+ export type UseLockMutationVariables = Pick<Device, 'device_id'> & {
17
+ properties: Required<Pick<Device['properties'], 'locked'>>
18
+ }
19
+
20
+ type LockActionAttempt = Extract<ActionAttempt, { action_type: 'LOCK_DOOR' }>
21
+
22
+ type MutationError =
23
+ | SeamHttpApiError
24
+ | SeamActionAttemptFailedError<LockActionAttempt>
25
+ | SeamActionAttemptTimeoutError<LockActionAttempt>
26
+
27
+ interface UseLockParams {
28
+ onError?: () => void
29
+ onSuccess?: () => void
30
+ }
31
+
32
+ export function useLock(
33
+ params: UseLockParams = {}
34
+ ): UseMutationResult<UseLockData, MutationError, UseLockMutationVariables> {
35
+ const { client } = useSeamClient()
36
+ const queryClient = useQueryClient()
37
+
38
+ return useMutation<UseLockData, MutationError, UseLockMutationVariables>({
39
+ mutationFn: async (variables) => {
40
+ const {
41
+ device_id: deviceId,
42
+ properties: { locked },
43
+ } = variables
44
+ if (client === null) throw new NullSeamClientError()
45
+ if (locked == null) return
46
+ await client.locks.lockDoor({ device_id: deviceId })
47
+ },
48
+ onMutate: (variables) => {
49
+ queryClient.setQueryData<Device[]>(['devices', 'list', {}], (devices) => {
50
+ if (devices == null) {
51
+ return devices
52
+ }
53
+
54
+ return devices.map((device) => {
55
+ if (
56
+ device.device_id !== variables.device_id ||
57
+ device.properties.locked == null
58
+ ) {
59
+ return device
60
+ }
61
+
62
+ return {
63
+ ...device,
64
+ properties: {
65
+ ...device.properties,
66
+ locked: !variables.properties.locked,
67
+ },
68
+ }
69
+ })
70
+ })
71
+
72
+ queryClient.setQueryData<Device>(
73
+ ['devices', 'get', { device_id: variables.device_id }],
74
+ (device) => {
75
+ if (device?.properties.locked == null) return device
76
+
77
+ return {
78
+ ...device,
79
+ properties: {
80
+ ...device.properties,
81
+ locked: !variables.properties.locked,
82
+ },
83
+ }
84
+ }
85
+ )
86
+ },
87
+ onError: async (_error, variables) => {
88
+ params.onError?.()
89
+
90
+ await queryClient.invalidateQueries({
91
+ queryKey: ['devices', 'list'],
92
+ })
93
+ await queryClient.invalidateQueries({
94
+ queryKey: ['devices', 'get', { device_id: variables.device_id }],
95
+ })
96
+ },
97
+ onSuccess() {
98
+ params.onSuccess?.()
99
+ },
100
+ })
101
+ }
@@ -0,0 +1,104 @@
1
+ import type {
2
+ SeamActionAttemptFailedError,
3
+ SeamActionAttemptTimeoutError,
4
+ SeamHttpApiError,
5
+ } from '@seamapi/http/connect'
6
+ import { NullSeamClientError, useSeamClient } from '@seamapi/react-query'
7
+ import type { ActionAttempt, Device } from '@seamapi/types/connect'
8
+ import {
9
+ useMutation,
10
+ type UseMutationResult,
11
+ useQueryClient,
12
+ } from '@tanstack/react-query'
13
+
14
+ export type UseUnlockData = undefined
15
+
16
+ export type UseUnlockMutationVariables = Pick<Device, 'device_id'> & {
17
+ properties: Required<Pick<Device['properties'], 'locked'>>
18
+ }
19
+
20
+ type UnlockActionAttempt = Extract<
21
+ ActionAttempt,
22
+ { action_type: 'UNLOCK_DOOR' }
23
+ >
24
+
25
+ type MutationError =
26
+ | SeamHttpApiError
27
+ | SeamActionAttemptFailedError<UnlockActionAttempt>
28
+ | SeamActionAttemptTimeoutError<UnlockActionAttempt>
29
+
30
+ interface UseUnlockParams {
31
+ onError?: () => void
32
+ onSuccess?: () => void
33
+ }
34
+
35
+ export function useUnlock(
36
+ params: UseUnlockParams = {}
37
+ ): UseMutationResult<UseUnlockData, MutationError, UseUnlockMutationVariables> {
38
+ const { client } = useSeamClient()
39
+ const queryClient = useQueryClient()
40
+
41
+ return useMutation<UseUnlockData, MutationError, UseUnlockMutationVariables>({
42
+ mutationFn: async (variables) => {
43
+ const {
44
+ device_id: deviceId,
45
+ properties: { locked },
46
+ } = variables
47
+ if (client === null) throw new NullSeamClientError()
48
+ if (locked == null) return
49
+ await client.locks.unlockDoor({ device_id: deviceId })
50
+ },
51
+ onMutate: (variables) => {
52
+ queryClient.setQueryData<Device[]>(['devices', 'list', {}], (devices) => {
53
+ if (devices == null) {
54
+ return devices
55
+ }
56
+
57
+ return devices.map((device) => {
58
+ if (
59
+ device.device_id !== variables.device_id ||
60
+ device.properties.locked == null
61
+ ) {
62
+ return device
63
+ }
64
+
65
+ return {
66
+ ...device,
67
+ properties: {
68
+ ...device.properties,
69
+ locked: !variables.properties.locked,
70
+ },
71
+ }
72
+ })
73
+ })
74
+
75
+ queryClient.setQueryData<Device>(
76
+ ['devices', 'get', { device_id: variables.device_id }],
77
+ (device) => {
78
+ if (device?.properties.locked == null) return device
79
+
80
+ return {
81
+ ...device,
82
+ properties: {
83
+ ...device.properties,
84
+ locked: !variables.properties.locked,
85
+ },
86
+ }
87
+ }
88
+ )
89
+ },
90
+ onError: async (_error, variables) => {
91
+ params.onError?.()
92
+
93
+ await queryClient.invalidateQueries({
94
+ queryKey: ['devices', 'list'],
95
+ })
96
+ await queryClient.invalidateQueries({
97
+ queryKey: ['devices', 'get', { device_id: variables.device_id }],
98
+ })
99
+ },
100
+ onSuccess() {
101
+ params.onSuccess?.()
102
+ },
103
+ })
104
+ }
@@ -1,3 +1,3 @@
1
- const seamapiReactVersion = '4.13.0'
1
+ const seamapiReactVersion = '4.13.2'
2
2
 
3
3
  export default seamapiReactVersion
@@ -27,6 +27,11 @@
27
27
  justify-content: space-between;
28
28
  cursor: pointer;
29
29
 
30
+ &.disabled {
31
+ opacity: 0.6;
32
+ cursor: not-allowed;
33
+ }
34
+
30
35
  &:hover {
31
36
  background: colors.$item-hover-bg;
32
37
  }
@@ -43,6 +48,7 @@
43
48
  > .seam-right {
44
49
  display: flex;
45
50
  align-items: center;
51
+ gap: 8px;
46
52
  }
47
53
  }
48
54