@seamapi/react 0.20.0 → 0.21.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/lib/seam/devices/use-device.d.ts +0 -4
- package/lib/seam/devices/use-device.js +0 -39
- package/lib/seam/devices/use-device.js.map +1 -1
- package/lib/seam/devices/use-devices.js +8 -1
- package/lib/seam/devices/use-devices.js.map +1 -1
- package/lib/seam/devices/use-toggle-lock.d.ts +5 -0
- package/lib/seam/devices/use-toggle-lock.js +57 -0
- package/lib/seam/devices/use-toggle-lock.js.map +1 -0
- package/lib/ui/AccessCodeDetails/AccessCodeDetails.js +3 -3
- package/lib/ui/AccessCodeDetails/AccessCodeDetails.js.map +1 -1
- package/lib/ui/AccessCodeDetails/AccessCodeDevice.d.ts +1 -2
- package/lib/ui/AccessCodeDetails/AccessCodeDevice.js +15 -5
- package/lib/ui/AccessCodeDetails/AccessCodeDevice.js.map +1 -1
- package/lib/ui/Button.d.ts +2 -1
- package/lib/ui/Button.js +2 -2
- package/lib/ui/Button.js.map +1 -1
- package/lib/ui/DeviceDetails/DeviceDetails.d.ts +1 -2
- package/lib/ui/DeviceDetails/DeviceDetails.js +26 -10
- package/lib/ui/DeviceDetails/DeviceDetails.js.map +1 -1
- package/lib/ui/DeviceTable/DeviceTable.js +4 -4
- package/lib/ui/DeviceTable/DeviceTable.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/seam/devices/use-device.ts +0 -46
- package/src/lib/seam/devices/use-devices.ts +12 -1
- package/src/lib/seam/devices/use-toggle-lock.ts +89 -0
- package/src/lib/ui/AccessCodeDetails/AccessCodeDetails.tsx +4 -5
- package/src/lib/ui/AccessCodeDetails/AccessCodeDevice.tsx +26 -7
- package/src/lib/ui/Button.tsx +3 -0
- package/src/lib/ui/DeviceDetails/DeviceDetails.tsx +43 -18
- package/src/lib/ui/DeviceTable/DeviceTable.tsx +4 -6
|
@@ -3,7 +3,3 @@ import type { UseSeamQueryResult } from '../../../lib/seam/use-seam-query-result
|
|
|
3
3
|
export type UseDeviceParams = DeviceGetRequest | string;
|
|
4
4
|
export type UseDeviceData = Device<CommonDeviceProperties> | null;
|
|
5
5
|
export declare function useDevice(params: DeviceGetRequest): UseSeamQueryResult<'device', UseDeviceData>;
|
|
6
|
-
export declare function useFakeDevice(_params: DeviceGetRequest): {
|
|
7
|
-
isLoading: boolean;
|
|
8
|
-
device: UseDeviceData;
|
|
9
|
-
};
|
|
@@ -14,43 +14,4 @@ export function useDevice(params) {
|
|
|
14
14
|
});
|
|
15
15
|
return { ...rest, device: data };
|
|
16
16
|
}
|
|
17
|
-
export function useFakeDevice(_params) {
|
|
18
|
-
const device = {
|
|
19
|
-
device_id: 'f9a9ab36-9e14-4390-a88c-b4c78304c6aa',
|
|
20
|
-
device_type: 'august_lock',
|
|
21
|
-
capabilities_supported: ['access_code', 'lock'],
|
|
22
|
-
properties: {
|
|
23
|
-
locked: true,
|
|
24
|
-
online: true,
|
|
25
|
-
door_open: false,
|
|
26
|
-
manufacturer: 'august',
|
|
27
|
-
battery_level: 0.9999532347993827,
|
|
28
|
-
serial_number: '00000004-992d-45a0-bea1-9128fdcd8d12',
|
|
29
|
-
august_metadata: {
|
|
30
|
-
lock_id: 'lock-1',
|
|
31
|
-
house_id: 'house-1',
|
|
32
|
-
lock_name: 'FRONT DOOR',
|
|
33
|
-
has_keypad: true,
|
|
34
|
-
house_name: 'My House',
|
|
35
|
-
},
|
|
36
|
-
supported_code_lengths: [6],
|
|
37
|
-
name: 'FRONT DOOR',
|
|
38
|
-
battery: {
|
|
39
|
-
level: 0.9999532347993827,
|
|
40
|
-
status: 'full',
|
|
41
|
-
},
|
|
42
|
-
image_url: 'https://connect.getseam.com/assets/images/devices/august_wifi-smart-lock-3rd-gen_silver_front.png',
|
|
43
|
-
},
|
|
44
|
-
location: {
|
|
45
|
-
timezone: 'America/Los_Angeles',
|
|
46
|
-
location_name: 'My House',
|
|
47
|
-
},
|
|
48
|
-
connected_account_id: '6fc0f854-cb5a-461a-af93-e543ce1f730f',
|
|
49
|
-
workspace_id: 'a9598de8-e627-4d01-b119-61ab7b9e07bd',
|
|
50
|
-
created_at: '2023-05-08T22:37:24.206Z',
|
|
51
|
-
errors: [],
|
|
52
|
-
warnings: [],
|
|
53
|
-
};
|
|
54
|
-
return { isLoading: false, device };
|
|
55
|
-
}
|
|
56
17
|
//# sourceMappingURL=use-device.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-device.js","sourceRoot":"","sources":["../../../src/lib/seam/devices/use-device.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"use-device.js","sourceRoot":"","sources":["../../../src/lib/seam/devices/use-device.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAShD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAM3D,MAAM,UAAU,SAAS,CACvB,MAAwB;IAExB,MAAM,gBAAgB,GACpB,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAA;IAE7D,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAGhC;QACA,OAAO,EAAE,MAAM,IAAI,IAAI;QACvB,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,gBAAgB,CAAC;QAC9C,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,IAAI,MAAM,IAAI,IAAI;gBAAE,OAAO,IAAI,CAAA;YAC/B,OAAO,MAAM,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;QACpD,CAAC;KACF,CAAC,CAAA;IAEF,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;AAClC,CAAC"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { useQuery } from '@tanstack/react-query';
|
|
1
|
+
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
|
2
2
|
import { useSeamClient } from '../../../lib/seam/use-seam-client.js';
|
|
3
3
|
import { byCreatedAt } from '../../../lib/sort-by.js';
|
|
4
4
|
export function useDevices(params) {
|
|
5
5
|
const { client } = useSeamClient();
|
|
6
|
+
const queryClient = useQueryClient();
|
|
6
7
|
const { data, ...rest } = useQuery({
|
|
7
8
|
enabled: client != null,
|
|
8
9
|
queryKey: ['devices', 'list', params],
|
|
@@ -12,6 +13,12 @@ export function useDevices(params) {
|
|
|
12
13
|
const devices = await client?.devices.list(params);
|
|
13
14
|
return devices.sort(byCreatedAt);
|
|
14
15
|
},
|
|
16
|
+
onSuccess(devices) {
|
|
17
|
+
// Prime cache for each device.
|
|
18
|
+
for (const device of devices) {
|
|
19
|
+
queryClient.setQueryData(['devices', 'get', { device_id: device.device_id }], device);
|
|
20
|
+
}
|
|
21
|
+
},
|
|
15
22
|
});
|
|
16
23
|
return { ...rest, devices: data };
|
|
17
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-devices.js","sourceRoot":"","sources":["../../../src/lib/seam/devices/use-devices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"use-devices.js","sourceRoot":"","sources":["../../../src/lib/seam/devices/use-devices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAShE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAE3D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAK5C,MAAM,UAAU,UAAU,CACxB,MAAyB;IAEzB,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAA;IAEpC,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAChC;QACE,OAAO,EAAE,MAAM,IAAI,IAAI;QACvB,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC;QACrC,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,IAAI,MAAM,IAAI,IAAI;gBAAE,OAAO,EAAE,CAAA;YAC7B,MAAM,OAAO,GAAG,MAAM,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YAClD,OAAO,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAClC,CAAC;QACD,SAAS,CAAC,OAAO;YACf,+BAA+B;YAC/B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;gBAC5B,WAAW,CAAC,YAAY,CACtB,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,EACnD,MAAM,CACP,CAAA;aACF;QACH,CAAC;KACF,CACF,CAAA;IAED,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AACnC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type UseMutationResult } from '@tanstack/react-query';
|
|
2
|
+
import type { ActionAttempt, LockDevice, SeamError } from 'seamapi';
|
|
3
|
+
export declare function useToggleLock({ device_id: deviceId, properties: { locked }, }: LockDevice): UseMutationResult<{
|
|
4
|
+
actionAttempt: ActionAttempt;
|
|
5
|
+
}, SeamError, void>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { useMutation, useQueryClient, } from '@tanstack/react-query';
|
|
2
|
+
import { useSeamClient } from '../../../lib/index.js';
|
|
3
|
+
import { isLockDevice } from '../../../lib/seam/devices/types.js';
|
|
4
|
+
export function useToggleLock({ device_id: deviceId, properties: { locked }, }) {
|
|
5
|
+
const { client } = useSeamClient();
|
|
6
|
+
const queryClient = useQueryClient();
|
|
7
|
+
return useMutation({
|
|
8
|
+
mutationFn: async () => {
|
|
9
|
+
if (client == null) {
|
|
10
|
+
throw new Error('Missing seam client');
|
|
11
|
+
}
|
|
12
|
+
const toggle = locked ? client.locks.unlockDoor : client.locks.lockDoor;
|
|
13
|
+
return await toggle(deviceId);
|
|
14
|
+
},
|
|
15
|
+
onMutate: () => {
|
|
16
|
+
queryClient.setQueryData(['devices', 'list', {}], (devices) => {
|
|
17
|
+
if (devices == null) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
return devices.map((device) => {
|
|
21
|
+
const isTarget = device.device_id === deviceId;
|
|
22
|
+
if (isTarget && isLockDevice(device)) {
|
|
23
|
+
return {
|
|
24
|
+
...device,
|
|
25
|
+
properties: {
|
|
26
|
+
...device.properties,
|
|
27
|
+
locked: !device.properties.locked,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return device;
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
queryClient.setQueryData(['devices', 'get', { device_id: deviceId }], (device) => {
|
|
35
|
+
if (device == null) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
...device,
|
|
40
|
+
properties: {
|
|
41
|
+
...device.properties,
|
|
42
|
+
locked: !device.properties.locked,
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
onSettled: async () => {
|
|
48
|
+
await queryClient.invalidateQueries({
|
|
49
|
+
queryKey: ['devices', 'list'],
|
|
50
|
+
});
|
|
51
|
+
await queryClient.invalidateQueries({
|
|
52
|
+
queryKey: ['devices', 'get', { device_id: deviceId }],
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=use-toggle-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-toggle-lock.js","sourceRoot":"","sources":["../../../src/lib/seam/devices/use-toggle-lock.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAEX,cAAc,GACf,MAAM,uBAAuB,CAAA;AAS9B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAExD,MAAM,UAAU,aAAa,CAAC,EAC5B,SAAS,EAAE,QAAQ,EACnB,UAAU,EAAE,EAAE,MAAM,EAAE,GACX;IAKX,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAA;IAEpC,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,KAAK,IAAI,EAAE;YACrB,IAAI,MAAM,IAAI,IAAI,EAAE;gBAClB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;aACvC;YAED,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAA;YACvE,OAAO,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAA;QAC/B,CAAC;QACD,QAAQ,EAAE,GAAG,EAAE;YACb,WAAW,CAAC,YAAY,CACtB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC,EACvB,CAAC,OAAO,EAAE,EAAE;gBACV,IAAI,OAAO,IAAI,IAAI,EAAE;oBACnB,OAAM;iBACP;gBAED,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;oBAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAA;oBAC9C,IAAI,QAAQ,IAAI,YAAY,CAAC,MAAM,CAAC,EAAE;wBACpC,OAAO;4BACL,GAAG,MAAM;4BACT,UAAU,EAAE;gCACV,GAAG,MAAM,CAAC,UAAU;gCACpB,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM;6BAClC;yBACF,CAAA;qBACF;oBAED,OAAO,MAAM,CAAA;gBACf,CAAC,CAAC,CAAA;YACJ,CAAC,CACF,CAAA;YAED,WAAW,CAAC,YAAY,CACtB,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAC3C,CAAC,MAAM,EAAE,EAAE;gBACT,IAAI,MAAM,IAAI,IAAI,EAAE;oBAClB,OAAM;iBACP;gBAED,OAAO;oBACL,GAAG,MAAM;oBACT,UAAU,EAAE;wBACV,GAAG,MAAM,CAAC,UAAU;wBACpB,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM;qBAClC;iBACF,CAAA;YACH,CAAC,CACF,CAAA;QACH,CAAC;QACD,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,WAAW,CAAC,iBAAiB,CAAC;gBAClC,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC;aAC9B,CAAC,CAAA;YACF,MAAM,WAAW,CAAC,iBAAiB,CAAC;gBAClC,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;aACtD,CAAC,CAAA;QACJ,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -7,9 +7,9 @@ import { ContentHeader } from '../../../lib/ui/layout/ContentHeader.js';
|
|
|
7
7
|
import { useIsDateInPast } from '../../../lib/use-is-date-in-past.js';
|
|
8
8
|
export function AccessCodeDetails({ accessCode, onBack, }) {
|
|
9
9
|
const name = accessCode.name ?? t.fallbackName;
|
|
10
|
-
const [
|
|
11
|
-
if (
|
|
12
|
-
return (_jsx(DeviceDetails, {
|
|
10
|
+
const [selectedDeviceId, selectDevice] = useState(null);
|
|
11
|
+
if (selectedDeviceId != null) {
|
|
12
|
+
return (_jsx(DeviceDetails, { deviceId: selectedDeviceId, onBack: () => {
|
|
13
13
|
selectDevice(null);
|
|
14
14
|
} }));
|
|
15
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessCodeDetails.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeDetails/AccessCodeDetails.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAGhC,OAAO,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAA;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAA;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAO5D,MAAM,UAAU,iBAAiB,CAAC,EAChC,UAAU,EACV,MAAM,GACiB;IACvB,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,IAAI,CAAC,CAAC,YAAY,CAAA;IAC9C,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"AccessCodeDetails.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeDetails/AccessCodeDetails.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { CommonDeviceProperties, Device } from 'seamapi';
|
|
2
1
|
export declare function AccessCodeDevice({ deviceId, onSelectDevice, }: {
|
|
3
2
|
deviceId: string;
|
|
4
|
-
onSelectDevice: (
|
|
3
|
+
onSelectDevice: (deviceId: string) => void;
|
|
5
4
|
}): JSX.Element | null;
|
|
@@ -1,22 +1,32 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { isLockDevice } from '../../../lib/seam/devices/types.js';
|
|
3
|
-
import {
|
|
3
|
+
import { useDevice } from '../../../lib/seam/devices/use-device.js';
|
|
4
|
+
import { useToggleLock } from '../../../lib/seam/devices/use-toggle-lock.js';
|
|
4
5
|
import { Button } from '../../../lib/ui/Button.js';
|
|
5
6
|
import { DeviceImage } from '../../../lib/ui/device/DeviceImage.js';
|
|
6
7
|
import { getDeviceModel } from '../../../lib/ui/DeviceDetails/DeviceModel.js';
|
|
7
8
|
import { TextButton } from '../../../lib/ui/TextButton.js';
|
|
8
9
|
export function AccessCodeDevice({ deviceId, onSelectDevice, }) {
|
|
9
|
-
|
|
10
|
-
const { isLoading, device } = useFakeDevice({ device_id: deviceId });
|
|
10
|
+
const { isLoading, device } = useDevice({ device_id: deviceId });
|
|
11
11
|
if (isLoading || device == null || !isLockDevice(device)) {
|
|
12
12
|
return null;
|
|
13
13
|
}
|
|
14
|
+
return _jsx(LockDeviceDetails, { device: device, onSelectDevice: onSelectDevice });
|
|
15
|
+
}
|
|
16
|
+
function LockDeviceDetails(props) {
|
|
17
|
+
const { device, onSelectDevice } = props;
|
|
18
|
+
const toggleLock = useToggleLock(device);
|
|
14
19
|
const model = getDeviceModel(device);
|
|
20
|
+
const toggleLockLabel = device.properties.locked ? t.unlock : t.lock;
|
|
15
21
|
return (_jsxs("div", { className: 'seam-access-code-device', children: [_jsx("div", { className: 'seam-device-image', children: _jsx(DeviceImage, { device: device }) }), _jsxs("div", { className: 'seam-body', children: [_jsx("div", { className: 'seam-model', children: model }), _jsx(TextButton, { onClick: () => {
|
|
16
|
-
onSelectDevice(device);
|
|
17
|
-
}, children: t.deviceDetails })] }), _jsx(Button, {
|
|
22
|
+
onSelectDevice(device.device_id);
|
|
23
|
+
}, children: t.deviceDetails })] }), _jsx(Button, { onClick: () => {
|
|
24
|
+
toggleLock.mutate();
|
|
25
|
+
}, children: toggleLockLabel })] }));
|
|
18
26
|
}
|
|
19
27
|
const t = {
|
|
20
28
|
deviceDetails: 'Device details',
|
|
29
|
+
unlock: 'Unlock',
|
|
30
|
+
lock: 'Lock',
|
|
21
31
|
};
|
|
22
32
|
//# sourceMappingURL=AccessCodeDevice.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessCodeDevice.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeDetails/AccessCodeDevice.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"AccessCodeDevice.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeDetails/AccessCodeDevice.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAA;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAA;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEjD,MAAM,UAAU,gBAAgB,CAAC,EAC/B,QAAQ,EACR,cAAc,GAIf;IACC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAA;IAEhE,IAAI,SAAS,IAAI,MAAM,IAAI,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE;QACxD,OAAO,IAAI,CAAA;KACZ;IAED,OAAO,KAAC,iBAAiB,IAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,GAAI,CAAA;AAC9E,CAAC;AAED,SAAS,iBAAiB,CAAC,KAG1B;IACC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,KAAK,CAAA;IACxC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;IACxC,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC,CAAA;IAEpC,MAAM,eAAe,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAEpE,OAAO,CACL,eAAK,SAAS,EAAC,yBAAyB,aACtC,cAAK,SAAS,EAAC,mBAAmB,YAChC,KAAC,WAAW,IAAC,MAAM,EAAE,MAAM,GAAI,GAC3B,EACN,eAAK,SAAS,EAAC,WAAW,aACxB,cAAK,SAAS,EAAC,YAAY,YAAE,KAAK,GAAO,EACzC,KAAC,UAAU,IACT,OAAO,EAAE,GAAG,EAAE;4BACZ,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;wBAClC,CAAC,YAEA,CAAC,CAAC,aAAa,GACL,IACT,EACN,KAAC,MAAM,IACL,OAAO,EAAE,GAAG,EAAE;oBACZ,UAAU,CAAC,MAAM,EAAE,CAAA;gBACrB,CAAC,YAEA,eAAe,GACT,IACL,CACP,CAAA;AACH,CAAC;AAED,MAAM,CAAC,GAAG;IACR,aAAa,EAAE,gBAAgB;IAC/B,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;CACb,CAAA"}
|
package/lib/ui/Button.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ interface ButtonProps {
|
|
|
3
3
|
variant?: 'solid' | 'outline' | 'neutral';
|
|
4
4
|
size?: 'small' | 'medium' | 'large';
|
|
5
5
|
disabled?: boolean;
|
|
6
|
+
onClick?: () => void;
|
|
6
7
|
}
|
|
7
|
-
export declare function Button({ variant, children, size, disabled, }: ButtonProps): JSX.Element;
|
|
8
|
+
export declare function Button({ variant, children, size, disabled, onClick, }: ButtonProps): JSX.Element;
|
|
8
9
|
export {};
|
package/lib/ui/Button.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import classNames from 'classnames';
|
|
3
|
-
export function Button({ variant = 'outline', children, size = 'medium', disabled, }) {
|
|
3
|
+
export function Button({ variant = 'outline', children, size = 'medium', disabled, onClick, }) {
|
|
4
4
|
return (_jsx("button", { className: classNames(`seam-btn seam-btn-${variant} seam-btn-${size}`, {
|
|
5
5
|
'seam-btn-disabled': disabled,
|
|
6
|
-
}), disabled: disabled, children: children }));
|
|
6
|
+
}), disabled: disabled, onClick: onClick, children: children }));
|
|
7
7
|
}
|
|
8
8
|
//# sourceMappingURL=Button.js.map
|
package/lib/ui/Button.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.js","sourceRoot":"","sources":["../../src/lib/ui/Button.tsx"],"names":[],"mappings":";AAAA,OAAO,UAAU,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"Button.js","sourceRoot":"","sources":["../../src/lib/ui/Button.tsx"],"names":[],"mappings":";AAAA,OAAO,UAAU,MAAM,YAAY,CAAA;AAUnC,MAAM,UAAU,MAAM,CAAC,EACrB,OAAO,GAAG,SAAS,EACnB,QAAQ,EACR,IAAI,GAAG,QAAQ,EACf,QAAQ,EACR,OAAO,GACK;IACZ,OAAO,CACL,iBACE,SAAS,EAAE,UAAU,CAAC,qBAAqB,OAAO,aAAa,IAAI,EAAE,EAAE;YACrE,mBAAmB,EAAE,QAAQ;SAC9B,CAAC,EACF,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,YAEf,QAAQ,GACF,CACV,CAAA;AACH,CAAC"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { type CommonDeviceProperties, type Device } from 'seamapi';
|
|
2
1
|
export interface DeviceDetailsProps {
|
|
3
|
-
|
|
2
|
+
deviceId: string;
|
|
4
3
|
onBack?: () => void;
|
|
5
4
|
}
|
|
6
5
|
export declare function DeviceDetails(props: DeviceDetailsProps): JSX.Element | null;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {} from '
|
|
2
|
+
import { useDevice } from '../../../lib/index.js';
|
|
3
3
|
import { ChevronRightIcon } from '../../../lib/icons/ChevronRight.js';
|
|
4
4
|
import { useAccessCodes } from '../../../lib/seam/access-codes/use-access-codes.js';
|
|
5
5
|
import { isLockDevice } from '../../../lib/seam/devices/types.js';
|
|
6
|
+
import { useToggleLock } from '../../../lib/seam/devices/use-toggle-lock.js';
|
|
6
7
|
import { AccessCodeTable } from '../../../lib/ui/AccessCodeTable/AccessCodeTable.js';
|
|
7
8
|
import { Button } from '../../../lib/ui/Button.js';
|
|
8
9
|
import { BatteryStatus } from '../../../lib/ui/device/BatteryStatus.js';
|
|
@@ -12,24 +13,38 @@ import { DeviceModel } from '../../../lib/ui/DeviceDetails/DeviceModel.js';
|
|
|
12
13
|
import { ContentHeader } from '../../../lib/ui/layout/ContentHeader.js';
|
|
13
14
|
import useToggle from '../../../lib/use-toggle.js';
|
|
14
15
|
export function DeviceDetails(props) {
|
|
15
|
-
const {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
device_id: device.device_id,
|
|
16
|
+
const { deviceId, onBack } = props;
|
|
17
|
+
const { device } = useDevice({
|
|
18
|
+
device_id: deviceId,
|
|
19
19
|
});
|
|
20
|
-
if (
|
|
20
|
+
if (device == null) {
|
|
21
21
|
return null;
|
|
22
22
|
}
|
|
23
|
-
if (accessCodesOpen) {
|
|
24
|
-
return (_jsx(AccessCodeTable, { deviceId: device.device_id, onBack: toggleAccessCodesOpen }));
|
|
25
|
-
}
|
|
26
23
|
if (!isLockDevice(device)) {
|
|
27
24
|
return null;
|
|
28
25
|
}
|
|
26
|
+
return _jsx(LockDeviceDetails, { device: device, onBack: onBack });
|
|
27
|
+
}
|
|
28
|
+
function LockDeviceDetails(props) {
|
|
29
|
+
const { device, onBack } = props;
|
|
30
|
+
const [accessCodesOpen, toggleAccessCodesOpen] = useToggle();
|
|
31
|
+
const toggleLock = useToggleLock(device);
|
|
32
|
+
const { accessCodes } = useAccessCodes({
|
|
33
|
+
device_id: device.device_id,
|
|
34
|
+
});
|
|
29
35
|
const lockStatus = device.properties.locked ? t.locked : t.unlocked;
|
|
36
|
+
const toggleLockLabel = device.properties.locked ? t.unlock : t.lock;
|
|
30
37
|
const accessCodeCount = accessCodes?.length;
|
|
31
38
|
const accessCodeLength = device.properties?.schlage_metadata?.access_code_length;
|
|
32
|
-
|
|
39
|
+
if (accessCodes == null) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
if (accessCodesOpen) {
|
|
43
|
+
return (_jsx(AccessCodeTable, { deviceId: device.device_id, onBack: toggleAccessCodesOpen }));
|
|
44
|
+
}
|
|
45
|
+
return (_jsxs("div", { className: 'seam-device-details', children: [_jsx(ContentHeader, { title: 'Device', onBack: onBack }), _jsxs("div", { className: 'seam-body', children: [_jsx("div", { className: 'seam-summary', children: _jsxs("div", { className: 'seam-content', children: [_jsx("div", { className: 'seam-image', children: _jsx(DeviceImage, { device: device }) }), _jsxs("div", { className: 'seam-info', children: [_jsx("span", { className: 'seam-label', children: t.device }), _jsx("h4", { className: 'seam-device-name', children: device.properties.name }), _jsxs("div", { className: 'seam-properties', children: [_jsxs("span", { className: 'seam-label', children: [t.status, ":"] }), ' ', _jsx(OnlineStatus, { device: device }), _jsxs("span", { className: 'seam-label', children: [t.power, ":"] }), ' ', _jsx(BatteryStatus, { device: device }), _jsx(DeviceModel, { device: device })] })] })] }) }), _jsx("div", { className: 'seam-box', children: _jsxs("div", { className: 'seam-content seam-access-codes', onClick: toggleAccessCodesOpen, children: [_jsxs("span", { className: 'seam-value', children: [accessCodeCount, " ", t.accessCodes] }), _jsx(ChevronRightIcon, {})] }) }), _jsxs("div", { className: 'seam-box', children: [_jsxs("div", { className: 'seam-content seam-lock-status', children: [_jsxs("div", { children: [_jsx("span", { className: 'seam-label', children: t.lockStatus }), _jsx("span", { className: 'seam-value', children: lockStatus })] }), _jsx("div", { className: 'seam-right', children: _jsx(Button, { size: 'small', onClick: () => {
|
|
46
|
+
toggleLock.mutate();
|
|
47
|
+
}, children: toggleLockLabel }) })] }), _jsx(AccessCodeLength, { accessCodeLength: accessCodeLength })] })] })] }));
|
|
33
48
|
}
|
|
34
49
|
function AccessCodeLength(props) {
|
|
35
50
|
const { accessCodeLength } = props;
|
|
@@ -41,6 +56,7 @@ function AccessCodeLength(props) {
|
|
|
41
56
|
const t = {
|
|
42
57
|
device: 'Device',
|
|
43
58
|
unlock: 'Unlock',
|
|
59
|
+
lock: 'Lock',
|
|
44
60
|
locked: 'Locked',
|
|
45
61
|
unlocked: 'Unlocked',
|
|
46
62
|
accessCodes: 'access codes',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeviceDetails.js","sourceRoot":"","sources":["../../../src/lib/ui/DeviceDetails/DeviceDetails.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"DeviceDetails.js","sourceRoot":"","sources":["../../../src/lib/ui/DeviceDetails/DeviceDetails.tsx"],"names":[],"mappings":"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"}
|
|
@@ -18,9 +18,9 @@ import { Caption } from '../../../lib/ui/typography/Caption.js';
|
|
|
18
18
|
import { Title } from '../../../lib/ui/typography/Title.js';
|
|
19
19
|
export function DeviceTable({ onBack, ...props }) {
|
|
20
20
|
const { devices, isLoading, isError, error } = useDevices(props);
|
|
21
|
-
const [
|
|
22
|
-
if (
|
|
23
|
-
return (_jsx(DeviceDetails, {
|
|
21
|
+
const [selectedDeviceId, selectDevice] = useState(null);
|
|
22
|
+
if (selectedDeviceId != null) {
|
|
23
|
+
return (_jsx(DeviceDetails, { deviceId: selectedDeviceId, onBack: () => {
|
|
24
24
|
selectDevice(null);
|
|
25
25
|
} }));
|
|
26
26
|
}
|
|
@@ -35,7 +35,7 @@ export function DeviceTable({ onBack, ...props }) {
|
|
|
35
35
|
}
|
|
36
36
|
const deviceCount = devices.length;
|
|
37
37
|
return (_jsxs("div", { className: 'seam-device-table', children: [_jsx(ContentHeader, { onBack: onBack }), _jsx(TableHeader, { children: _jsxs(TableTitle, { children: [t.devices, " ", _jsxs(Caption, { children: ["(", deviceCount, ")"] })] }) }), _jsx(TableBody, { children: devices.map((device) => (_jsx(DeviceRow, { device: device, onClick: () => {
|
|
38
|
-
selectDevice(device);
|
|
38
|
+
selectDevice(device.device_id);
|
|
39
39
|
} }, device.device_id))) })] }));
|
|
40
40
|
}
|
|
41
41
|
function DeviceRow(props) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeviceTable.js","sourceRoot":"","sources":["../../../src/lib/ui/DeviceTable/DeviceTable.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"DeviceTable.js","sourceRoot":"","sources":["../../../src/lib/ui/DeviceTable/DeviceTable.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -4,7 +4,6 @@ import type {
|
|
|
4
4
|
Device,
|
|
5
5
|
DeviceGetRequest,
|
|
6
6
|
DeviceGetResponse,
|
|
7
|
-
LockDevice,
|
|
8
7
|
SeamError,
|
|
9
8
|
} from 'seamapi'
|
|
10
9
|
|
|
@@ -35,48 +34,3 @@ export function useDevice(
|
|
|
35
34
|
|
|
36
35
|
return { ...rest, device: data }
|
|
37
36
|
}
|
|
38
|
-
|
|
39
|
-
export function useFakeDevice(_params: DeviceGetRequest): {
|
|
40
|
-
isLoading: boolean
|
|
41
|
-
device: UseDeviceData
|
|
42
|
-
} {
|
|
43
|
-
const device: LockDevice = {
|
|
44
|
-
device_id: 'f9a9ab36-9e14-4390-a88c-b4c78304c6aa',
|
|
45
|
-
device_type: 'august_lock',
|
|
46
|
-
capabilities_supported: ['access_code', 'lock'],
|
|
47
|
-
properties: {
|
|
48
|
-
locked: true,
|
|
49
|
-
online: true,
|
|
50
|
-
door_open: false,
|
|
51
|
-
manufacturer: 'august',
|
|
52
|
-
battery_level: 0.9999532347993827,
|
|
53
|
-
serial_number: '00000004-992d-45a0-bea1-9128fdcd8d12',
|
|
54
|
-
august_metadata: {
|
|
55
|
-
lock_id: 'lock-1',
|
|
56
|
-
house_id: 'house-1',
|
|
57
|
-
lock_name: 'FRONT DOOR',
|
|
58
|
-
has_keypad: true,
|
|
59
|
-
house_name: 'My House',
|
|
60
|
-
},
|
|
61
|
-
supported_code_lengths: [6],
|
|
62
|
-
name: 'FRONT DOOR',
|
|
63
|
-
battery: {
|
|
64
|
-
level: 0.9999532347993827,
|
|
65
|
-
status: 'full',
|
|
66
|
-
},
|
|
67
|
-
image_url:
|
|
68
|
-
'https://connect.getseam.com/assets/images/devices/august_wifi-smart-lock-3rd-gen_silver_front.png',
|
|
69
|
-
},
|
|
70
|
-
location: {
|
|
71
|
-
timezone: 'America/Los_Angeles',
|
|
72
|
-
location_name: 'My House',
|
|
73
|
-
},
|
|
74
|
-
connected_account_id: '6fc0f854-cb5a-461a-af93-e543ce1f730f',
|
|
75
|
-
workspace_id: 'a9598de8-e627-4d01-b119-61ab7b9e07bd',
|
|
76
|
-
created_at: '2023-05-08T22:37:24.206Z',
|
|
77
|
-
errors: [],
|
|
78
|
-
warnings: [],
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return { isLoading: false, device }
|
|
82
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useQuery } from '@tanstack/react-query'
|
|
1
|
+
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
|
2
2
|
import type {
|
|
3
3
|
CommonDeviceProperties,
|
|
4
4
|
Device,
|
|
@@ -18,6 +18,8 @@ export function useDevices(
|
|
|
18
18
|
params?: UseDevicesParams
|
|
19
19
|
): UseSeamQueryResult<'devices', UseDevicesData> {
|
|
20
20
|
const { client } = useSeamClient()
|
|
21
|
+
const queryClient = useQueryClient()
|
|
22
|
+
|
|
21
23
|
const { data, ...rest } = useQuery<DevicesListResponse['devices'], SeamError>(
|
|
22
24
|
{
|
|
23
25
|
enabled: client != null,
|
|
@@ -27,6 +29,15 @@ export function useDevices(
|
|
|
27
29
|
const devices = await client?.devices.list(params)
|
|
28
30
|
return devices.sort(byCreatedAt)
|
|
29
31
|
},
|
|
32
|
+
onSuccess(devices) {
|
|
33
|
+
// Prime cache for each device.
|
|
34
|
+
for (const device of devices) {
|
|
35
|
+
queryClient.setQueryData(
|
|
36
|
+
['devices', 'get', { device_id: device.device_id }],
|
|
37
|
+
device
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
},
|
|
30
41
|
}
|
|
31
42
|
)
|
|
32
43
|
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useMutation,
|
|
3
|
+
type UseMutationResult,
|
|
4
|
+
useQueryClient,
|
|
5
|
+
} from '@tanstack/react-query'
|
|
6
|
+
import type {
|
|
7
|
+
ActionAttempt,
|
|
8
|
+
CommonDeviceProperties,
|
|
9
|
+
Device,
|
|
10
|
+
LockDevice,
|
|
11
|
+
SeamError,
|
|
12
|
+
} from 'seamapi'
|
|
13
|
+
|
|
14
|
+
import { useSeamClient } from 'lib/index.js'
|
|
15
|
+
|
|
16
|
+
import { isLockDevice } from 'lib/seam/devices/types.js'
|
|
17
|
+
|
|
18
|
+
export function useToggleLock({
|
|
19
|
+
device_id: deviceId,
|
|
20
|
+
properties: { locked },
|
|
21
|
+
}: LockDevice): UseMutationResult<
|
|
22
|
+
{ actionAttempt: ActionAttempt },
|
|
23
|
+
SeamError,
|
|
24
|
+
void
|
|
25
|
+
> {
|
|
26
|
+
const { client } = useSeamClient()
|
|
27
|
+
const queryClient = useQueryClient()
|
|
28
|
+
|
|
29
|
+
return useMutation({
|
|
30
|
+
mutationFn: async () => {
|
|
31
|
+
if (client == null) {
|
|
32
|
+
throw new Error('Missing seam client')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const toggle = locked ? client.locks.unlockDoor : client.locks.lockDoor
|
|
36
|
+
return await toggle(deviceId)
|
|
37
|
+
},
|
|
38
|
+
onMutate: () => {
|
|
39
|
+
queryClient.setQueryData<Array<Device<CommonDeviceProperties>>>(
|
|
40
|
+
['devices', 'list', {}],
|
|
41
|
+
(devices) => {
|
|
42
|
+
if (devices == null) {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return devices.map((device) => {
|
|
47
|
+
const isTarget = device.device_id === deviceId
|
|
48
|
+
if (isTarget && isLockDevice(device)) {
|
|
49
|
+
return {
|
|
50
|
+
...device,
|
|
51
|
+
properties: {
|
|
52
|
+
...device.properties,
|
|
53
|
+
locked: !device.properties.locked,
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return device
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
queryClient.setQueryData<LockDevice>(
|
|
64
|
+
['devices', 'get', { device_id: deviceId }],
|
|
65
|
+
(device) => {
|
|
66
|
+
if (device == null) {
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
...device,
|
|
72
|
+
properties: {
|
|
73
|
+
...device.properties,
|
|
74
|
+
locked: !device.properties.locked,
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
},
|
|
80
|
+
onSettled: async () => {
|
|
81
|
+
await queryClient.invalidateQueries({
|
|
82
|
+
queryKey: ['devices', 'list'],
|
|
83
|
+
})
|
|
84
|
+
await queryClient.invalidateQueries({
|
|
85
|
+
queryKey: ['devices', 'get', { device_id: deviceId }],
|
|
86
|
+
})
|
|
87
|
+
},
|
|
88
|
+
})
|
|
89
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DateTime } from 'luxon'
|
|
2
2
|
import { useState } from 'react'
|
|
3
|
-
import type { AccessCode
|
|
3
|
+
import type { AccessCode } from 'seamapi'
|
|
4
4
|
|
|
5
5
|
import { AccessCodeDevice } from 'lib/ui/AccessCodeDetails/AccessCodeDevice.js'
|
|
6
6
|
import { DeviceDetails } from 'lib/ui/DeviceDetails/DeviceDetails.js'
|
|
@@ -17,13 +17,12 @@ export function AccessCodeDetails({
|
|
|
17
17
|
onBack,
|
|
18
18
|
}: AccessCodeDetailsProps): JSX.Element {
|
|
19
19
|
const name = accessCode.name ?? t.fallbackName
|
|
20
|
-
const [
|
|
21
|
-
useState<Device<CommonDeviceProperties> | null>(null)
|
|
20
|
+
const [selectedDeviceId, selectDevice] = useState<string | null>(null)
|
|
22
21
|
|
|
23
|
-
if (
|
|
22
|
+
if (selectedDeviceId != null) {
|
|
24
23
|
return (
|
|
25
24
|
<DeviceDetails
|
|
26
|
-
|
|
25
|
+
deviceId={selectedDeviceId}
|
|
27
26
|
onBack={() => {
|
|
28
27
|
selectDevice(null)
|
|
29
28
|
}}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { LockDevice } from 'seamapi'
|
|
2
2
|
|
|
3
3
|
import { isLockDevice } from 'lib/seam/devices/types.js'
|
|
4
|
-
import {
|
|
4
|
+
import { useDevice } from 'lib/seam/devices/use-device.js'
|
|
5
|
+
import { useToggleLock } from 'lib/seam/devices/use-toggle-lock.js'
|
|
5
6
|
import { Button } from 'lib/ui/Button.js'
|
|
6
7
|
import { DeviceImage } from 'lib/ui/device/DeviceImage.js'
|
|
7
8
|
import { getDeviceModel } from 'lib/ui/DeviceDetails/DeviceModel.js'
|
|
@@ -12,17 +13,27 @@ export function AccessCodeDevice({
|
|
|
12
13
|
onSelectDevice,
|
|
13
14
|
}: {
|
|
14
15
|
deviceId: string
|
|
15
|
-
onSelectDevice: (
|
|
16
|
+
onSelectDevice: (deviceId: string) => void
|
|
16
17
|
}): JSX.Element | null {
|
|
17
|
-
|
|
18
|
-
const { isLoading, device } = useFakeDevice({ device_id: deviceId })
|
|
18
|
+
const { isLoading, device } = useDevice({ device_id: deviceId })
|
|
19
19
|
|
|
20
20
|
if (isLoading || device == null || !isLockDevice(device)) {
|
|
21
21
|
return null
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
return <LockDeviceDetails device={device} onSelectDevice={onSelectDevice} />
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function LockDeviceDetails(props: {
|
|
28
|
+
device: LockDevice
|
|
29
|
+
onSelectDevice: (deviceId: string) => void
|
|
30
|
+
}) {
|
|
31
|
+
const { device, onSelectDevice } = props
|
|
32
|
+
const toggleLock = useToggleLock(device)
|
|
24
33
|
const model = getDeviceModel(device)
|
|
25
34
|
|
|
35
|
+
const toggleLockLabel = device.properties.locked ? t.unlock : t.lock
|
|
36
|
+
|
|
26
37
|
return (
|
|
27
38
|
<div className='seam-access-code-device'>
|
|
28
39
|
<div className='seam-device-image'>
|
|
@@ -32,17 +43,25 @@ export function AccessCodeDevice({
|
|
|
32
43
|
<div className='seam-model'>{model}</div>
|
|
33
44
|
<TextButton
|
|
34
45
|
onClick={() => {
|
|
35
|
-
onSelectDevice(device)
|
|
46
|
+
onSelectDevice(device.device_id)
|
|
36
47
|
}}
|
|
37
48
|
>
|
|
38
49
|
{t.deviceDetails}
|
|
39
50
|
</TextButton>
|
|
40
51
|
</div>
|
|
41
|
-
<Button
|
|
52
|
+
<Button
|
|
53
|
+
onClick={() => {
|
|
54
|
+
toggleLock.mutate()
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
{toggleLockLabel}
|
|
58
|
+
</Button>
|
|
42
59
|
</div>
|
|
43
60
|
)
|
|
44
61
|
}
|
|
45
62
|
|
|
46
63
|
const t = {
|
|
47
64
|
deviceDetails: 'Device details',
|
|
65
|
+
unlock: 'Unlock',
|
|
66
|
+
lock: 'Lock',
|
|
48
67
|
}
|
package/src/lib/ui/Button.tsx
CHANGED
|
@@ -5,6 +5,7 @@ interface ButtonProps {
|
|
|
5
5
|
variant?: 'solid' | 'outline' | 'neutral'
|
|
6
6
|
size?: 'small' | 'medium' | 'large'
|
|
7
7
|
disabled?: boolean
|
|
8
|
+
onClick?: () => void
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
export function Button({
|
|
@@ -12,6 +13,7 @@ export function Button({
|
|
|
12
13
|
children,
|
|
13
14
|
size = 'medium',
|
|
14
15
|
disabled,
|
|
16
|
+
onClick,
|
|
15
17
|
}: ButtonProps): JSX.Element {
|
|
16
18
|
return (
|
|
17
19
|
<button
|
|
@@ -19,6 +21,7 @@ export function Button({
|
|
|
19
21
|
'seam-btn-disabled': disabled,
|
|
20
22
|
})}
|
|
21
23
|
disabled={disabled}
|
|
24
|
+
onClick={onClick}
|
|
22
25
|
>
|
|
23
26
|
{children}
|
|
24
27
|
</button>
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { LockDevice } from 'seamapi'
|
|
2
|
+
|
|
3
|
+
import { useDevice } from 'lib/index.js'
|
|
2
4
|
|
|
3
5
|
import { ChevronRightIcon } from 'lib/icons/ChevronRight.js'
|
|
4
6
|
import { useAccessCodes } from 'lib/seam/access-codes/use-access-codes.js'
|
|
5
7
|
import { isLockDevice } from 'lib/seam/devices/types.js'
|
|
8
|
+
import { useToggleLock } from 'lib/seam/devices/use-toggle-lock.js'
|
|
6
9
|
import { AccessCodeTable } from 'lib/ui/AccessCodeTable/AccessCodeTable.js'
|
|
7
10
|
import { Button } from 'lib/ui/Button.js'
|
|
8
11
|
import { BatteryStatus } from 'lib/ui/device/BatteryStatus.js'
|
|
@@ -13,43 +16,57 @@ import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
|
13
16
|
import useToggle from 'lib/use-toggle.js'
|
|
14
17
|
|
|
15
18
|
export interface DeviceDetailsProps {
|
|
16
|
-
|
|
19
|
+
deviceId: string
|
|
17
20
|
onBack?: () => void
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
export function DeviceDetails(props: DeviceDetailsProps): JSX.Element | null {
|
|
21
|
-
const {
|
|
24
|
+
const { deviceId, onBack } = props
|
|
22
25
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
const { isLoading, accessCodes } = useAccessCodes({
|
|
26
|
-
device_id: device.device_id,
|
|
26
|
+
const { device } = useDevice({
|
|
27
|
+
device_id: deviceId,
|
|
27
28
|
})
|
|
28
29
|
|
|
29
|
-
if (
|
|
30
|
+
if (device == null) {
|
|
30
31
|
return null
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
if (accessCodesOpen) {
|
|
34
|
-
return (
|
|
35
|
-
<AccessCodeTable
|
|
36
|
-
deviceId={device.device_id}
|
|
37
|
-
onBack={toggleAccessCodesOpen}
|
|
38
|
-
/>
|
|
39
|
-
)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
34
|
if (!isLockDevice(device)) {
|
|
43
35
|
return null
|
|
44
36
|
}
|
|
45
37
|
|
|
38
|
+
return <LockDeviceDetails device={device} onBack={onBack} />
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function LockDeviceDetails(props: { device: LockDevice; onBack?: () => void }) {
|
|
42
|
+
const { device, onBack } = props
|
|
43
|
+
const [accessCodesOpen, toggleAccessCodesOpen] = useToggle()
|
|
44
|
+
const toggleLock = useToggleLock(device)
|
|
45
|
+
const { accessCodes } = useAccessCodes({
|
|
46
|
+
device_id: device.device_id,
|
|
47
|
+
})
|
|
48
|
+
|
|
46
49
|
const lockStatus = device.properties.locked ? t.locked : t.unlocked
|
|
50
|
+
const toggleLockLabel = device.properties.locked ? t.unlock : t.lock
|
|
47
51
|
|
|
48
52
|
const accessCodeCount = accessCodes?.length
|
|
49
53
|
|
|
50
54
|
const accessCodeLength =
|
|
51
55
|
device.properties?.schlage_metadata?.access_code_length
|
|
52
56
|
|
|
57
|
+
if (accessCodes == null) {
|
|
58
|
+
return null
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (accessCodesOpen) {
|
|
62
|
+
return (
|
|
63
|
+
<AccessCodeTable
|
|
64
|
+
deviceId={device.device_id}
|
|
65
|
+
onBack={toggleAccessCodesOpen}
|
|
66
|
+
/>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
53
70
|
return (
|
|
54
71
|
<div className='seam-device-details'>
|
|
55
72
|
<ContentHeader title='Device' onBack={onBack} />
|
|
@@ -91,7 +108,14 @@ export function DeviceDetails(props: DeviceDetailsProps): JSX.Element | null {
|
|
|
91
108
|
<span className='seam-value'>{lockStatus}</span>
|
|
92
109
|
</div>
|
|
93
110
|
<div className='seam-right'>
|
|
94
|
-
<Button
|
|
111
|
+
<Button
|
|
112
|
+
size='small'
|
|
113
|
+
onClick={() => {
|
|
114
|
+
toggleLock.mutate()
|
|
115
|
+
}}
|
|
116
|
+
>
|
|
117
|
+
{toggleLockLabel}
|
|
118
|
+
</Button>
|
|
95
119
|
</div>
|
|
96
120
|
</div>
|
|
97
121
|
<AccessCodeLength accessCodeLength={accessCodeLength} />
|
|
@@ -122,6 +146,7 @@ function AccessCodeLength(props: {
|
|
|
122
146
|
const t = {
|
|
123
147
|
device: 'Device',
|
|
124
148
|
unlock: 'Unlock',
|
|
149
|
+
lock: 'Lock',
|
|
125
150
|
locked: 'Locked',
|
|
126
151
|
unlocked: 'Unlocked',
|
|
127
152
|
accessCodes: 'access codes',
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { useState } from 'react'
|
|
2
|
-
import type { CommonDeviceProperties, Device } from 'seamapi'
|
|
3
2
|
|
|
4
3
|
import { isLockDevice } from 'lib/seam/devices/types.js'
|
|
5
4
|
import {
|
|
@@ -34,13 +33,12 @@ export function DeviceTable({
|
|
|
34
33
|
}: DeviceTableProps): JSX.Element | null {
|
|
35
34
|
const { devices, isLoading, isError, error } = useDevices(props)
|
|
36
35
|
|
|
37
|
-
const [
|
|
38
|
-
useState<Device<CommonDeviceProperties> | null>(null)
|
|
36
|
+
const [selectedDeviceId, selectDevice] = useState<string | null>(null)
|
|
39
37
|
|
|
40
|
-
if (
|
|
38
|
+
if (selectedDeviceId != null) {
|
|
41
39
|
return (
|
|
42
40
|
<DeviceDetails
|
|
43
|
-
|
|
41
|
+
deviceId={selectedDeviceId}
|
|
44
42
|
onBack={() => {
|
|
45
43
|
selectDevice(null)
|
|
46
44
|
}}
|
|
@@ -76,7 +74,7 @@ export function DeviceTable({
|
|
|
76
74
|
device={device}
|
|
77
75
|
key={device.device_id}
|
|
78
76
|
onClick={() => {
|
|
79
|
-
selectDevice(device)
|
|
77
|
+
selectDevice(device.device_id)
|
|
80
78
|
}}
|
|
81
79
|
/>
|
|
82
80
|
))}
|