@seamapi/react 0.17.0 → 0.18.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/README.md +23 -0
- package/lib/seam/access-codes/use-access-code.d.ts +0 -4
- package/lib/seam/access-codes/use-access-code.js +0 -16
- package/lib/seam/access-codes/use-access-code.js.map +1 -1
- package/lib/ui/AccessCodeDetails/AccessCodeDetails.d.ts +4 -2
- package/lib/ui/AccessCodeDetails/AccessCodeDetails.js +11 -10
- package/lib/ui/AccessCodeDetails/AccessCodeDetails.js.map +1 -1
- package/lib/ui/AccessCodeDetails/AccessCodeDevice.d.ts +3 -1
- package/lib/ui/AccessCodeDetails/AccessCodeDevice.js +2 -4
- package/lib/ui/AccessCodeDetails/AccessCodeDevice.js.map +1 -1
- package/lib/ui/AccessCodeTable/AccessCodeTable.d.ts +1 -0
- package/lib/ui/AccessCodeTable/AccessCodeTable.js +12 -8
- package/lib/ui/AccessCodeTable/AccessCodeTable.js.map +1 -1
- package/lib/ui/AccessCodeTable/AccessCodeTableContent.d.ts +1 -0
- package/lib/ui/AccessCodeTable/AccessCodeTableContent.js +2 -2
- package/lib/ui/AccessCodeTable/AccessCodeTableContent.js.map +1 -1
- package/lib/ui/DeviceDetails/DeviceDetails.d.ts +3 -1
- package/lib/ui/DeviceDetails/DeviceDetails.js +12 -14
- package/lib/ui/DeviceDetails/DeviceDetails.js.map +1 -1
- package/lib/ui/DeviceTable/DeviceTable.js +10 -4
- package/lib/ui/DeviceTable/DeviceTable.js.map +1 -1
- package/lib/ui/layout/ContentHeader.d.ts +1 -0
- package/lib/ui/layout/ContentHeader.js +3 -5
- package/lib/ui/layout/ContentHeader.js.map +1 -1
- package/package.json +1 -3
- package/src/lib/seam/access-codes/use-access-code.ts +0 -21
- package/src/lib/ui/AccessCodeDetails/AccessCodeDetails.tsx +26 -16
- package/src/lib/ui/AccessCodeDetails/AccessCodeDevice.tsx +10 -4
- package/src/lib/ui/AccessCodeTable/AccessCodeTable.tsx +25 -8
- package/src/lib/ui/AccessCodeTable/AccessCodeTableContent.tsx +3 -2
- package/src/lib/ui/DeviceDetails/DeviceDetails.tsx +19 -18
- package/src/lib/ui/DeviceTable/DeviceTable.tsx +20 -4
- package/src/lib/ui/layout/ContentHeader.tsx +7 -7
- package/lib/NavigationProvider.d.ts +0 -27
- package/lib/NavigationProvider.js +0 -36
- package/lib/NavigationProvider.js.map +0 -1
- package/lib/NavigationView.d.ts +0 -5
- package/lib/NavigationView.js +0 -25
- package/lib/NavigationView.js.map +0 -1
- package/src/lib/NavigationProvider.tsx +0 -86
- package/src/lib/NavigationView.tsx +0 -32
package/README.md
CHANGED
|
@@ -66,6 +66,29 @@ Load the font from Google Fonts by placing the following in the `<head>` tag:
|
|
|
66
66
|
|
|
67
67
|
[Source Sans Pro]: https://fonts.google.com/specimen/Source+Sans+Pro
|
|
68
68
|
|
|
69
|
+
### Content Security Policy (CSP)
|
|
70
|
+
|
|
71
|
+
By self hosting the recommended fonts (or choosing not to use them),
|
|
72
|
+
and proxying the Seam API endpoint, the components are compatible with this strict CSP:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
default-src 'self'; img-src 'self' https://connect.getseam.com
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The `img-src` is required as some components display device images from the Seam API.
|
|
79
|
+
|
|
80
|
+
When using the default endpoint, include `connect-src` with
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
connect-src 'self' https://connect.getseam.com
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
When serving the fonts from Google Fonts, include `font-src` and `style-src` with
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
font-src 'self' https://fonts.gstatic.com; style-src 'self' https://fonts.googleapis.com
|
|
90
|
+
```
|
|
91
|
+
|
|
69
92
|
## Development and Testing
|
|
70
93
|
|
|
71
94
|
### Quickstart
|
|
@@ -2,7 +2,3 @@ import type { AccessCode, AccessCodeGetRequest } from 'seamapi';
|
|
|
2
2
|
export type UseAccessCodeParams = AccessCodeGetRequest | string;
|
|
3
3
|
export type UseAccessCodeData = AccessCode;
|
|
4
4
|
export declare function useAccessCode(params: UseAccessCodeParams): import("@tanstack/react-query").UseQueryResult<AccessCode | null, unknown>;
|
|
5
|
-
export declare function useFakeAccessCode(_params: UseAccessCodeParams): {
|
|
6
|
-
isLoading: boolean;
|
|
7
|
-
data: AccessCode;
|
|
8
|
-
};
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { useQuery } from '@tanstack/react-query';
|
|
2
|
-
import { DateTime } from 'luxon';
|
|
3
|
-
import { v4 as uuid } from 'uuid';
|
|
4
2
|
import { useSeamClient } from '../../../lib/seam/use-seam-client.js';
|
|
5
3
|
export function useAccessCode(params) {
|
|
6
4
|
const { client } = useSeamClient();
|
|
@@ -15,18 +13,4 @@ export function useAccessCode(params) {
|
|
|
15
13
|
},
|
|
16
14
|
});
|
|
17
15
|
}
|
|
18
|
-
export function useFakeAccessCode(_params) {
|
|
19
|
-
const accessCode = {
|
|
20
|
-
access_code_id: uuid(),
|
|
21
|
-
type: 'time_bound',
|
|
22
|
-
starts_at: DateTime.now().minus({ days: 2 }).toISO() ?? '',
|
|
23
|
-
ends_at: DateTime.now().plus({ days: 1 }).toISO() ?? '',
|
|
24
|
-
code: '1234',
|
|
25
|
-
created_at: DateTime.now().toISO() ?? '',
|
|
26
|
-
device_id: 'some_device_id',
|
|
27
|
-
status: 'set',
|
|
28
|
-
name: 'Guest - Kranz',
|
|
29
|
-
};
|
|
30
|
-
return { isLoading: false, data: accessCode };
|
|
31
|
-
}
|
|
32
16
|
//# sourceMappingURL=use-access-code.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-access-code.js","sourceRoot":"","sources":["../../../src/lib/seam/access-codes/use-access-code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"use-access-code.js","sourceRoot":"","sources":["../../../src/lib/seam/access-codes/use-access-code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAGhD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAK3D,MAAM,UAAU,aAAa,CAAC,MAA2B;IACvD,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAAA;IAElC,MAAM,gBAAgB,GACpB,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAA;IAElE,OAAO,QAAQ,CAAC;QACd,OAAO,EAAE,MAAM,IAAI,IAAI;QACvB,QAAQ,EAAE,CAAC,aAAa,EAAE,KAAK,EAAE,gBAAgB,CAAC;QAClD,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,IAAI,MAAM,IAAI,IAAI;gBAAE,OAAO,IAAI,CAAA;YAE/B,OAAO,MAAM,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;QACxD,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { AccessCode } from 'seamapi';
|
|
1
2
|
export interface AccessCodeDetailsProps {
|
|
2
|
-
|
|
3
|
+
accessCode: AccessCode;
|
|
4
|
+
onBack?: () => void;
|
|
3
5
|
}
|
|
4
|
-
export
|
|
6
|
+
export declare function AccessCodeDetails({ accessCode, onBack, }: AccessCodeDetailsProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { DateTime } from 'luxon';
|
|
3
|
-
import {
|
|
4
|
-
import AccessCodeDevice from '../../../lib/ui/AccessCodeDetails/AccessCodeDevice.js';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { AccessCodeDevice } from '../../../lib/ui/AccessCodeDetails/AccessCodeDevice.js';
|
|
5
|
+
import { DeviceDetails } from '../../../lib/ui/DeviceDetails/DeviceDetails.js';
|
|
5
6
|
import { ContentHeader } from '../../../lib/ui/layout/ContentHeader.js';
|
|
6
|
-
export
|
|
7
|
-
const { isLoading, data: accessCode } = useFakeAccessCode({
|
|
8
|
-
access_code_id: accessCodeId,
|
|
9
|
-
});
|
|
10
|
-
if (isLoading || !accessCode) {
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
7
|
+
export function AccessCodeDetails({ accessCode, onBack, }) {
|
|
13
8
|
const name = accessCode.name ?? t.fallbackName;
|
|
14
|
-
|
|
9
|
+
const [selectedDevice, selectDevice] = useState(null);
|
|
10
|
+
if (selectedDevice) {
|
|
11
|
+
return (_jsx(DeviceDetails, { device: selectedDevice, onBack: () => {
|
|
12
|
+
selectDevice(null);
|
|
13
|
+
} }));
|
|
14
|
+
}
|
|
15
|
+
return (_jsxs("div", { className: 'seam-access-code-details', children: [_jsx(ContentHeader, { title: 'Access code', onBack: onBack }), _jsxs("div", { className: 'seam-summary', children: [_jsxs("div", { className: 'seam-top', children: [_jsx("span", { className: 'seam-label', children: t.accessCode }), _jsx("h5", { className: 'seam-access-code-name', children: name }), _jsx("div", { className: 'seam-code', children: accessCode.code }), _jsx("div", { className: 'seam-duration', children: _jsx(Duration, { accessCode: accessCode }) })] }), _jsx(AccessCodeDevice, { deviceId: accessCode.device_id, onSelectDevice: selectDevice })] }), _jsxs("div", { className: 'seam-details', children: [_jsxs("div", { className: 'seam-row', children: [_jsxs("div", { className: 'seam-heading', children: [t.id, ":"] }), _jsx("div", { className: 'seam-content', children: accessCode.access_code_id })] }), _jsxs("div", { className: 'seam-row', children: [_jsxs("div", { className: 'seam-heading', children: [t.created, ":"] }), _jsx("div", { className: 'seam-content', children: formatDate(accessCode.created_at) })] }), _jsxs("div", { className: 'seam-row seam-schedule', children: [_jsxs("div", { className: 'seam-heading', children: [t.timing, ":"] }), _jsx("div", { className: 'seam-content', children: _jsx(ScheduleInfo, { accessCode: accessCode }) })] })] })] }));
|
|
15
16
|
}
|
|
16
17
|
function ScheduleInfo({ accessCode }) {
|
|
17
18
|
if (accessCode.type === 'ongoing') {
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"AccessCodeDetails.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeDetails/AccessCodeDetails.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import type { CommonDeviceProperties, Device } from 'seamapi';
|
|
2
|
+
export declare function AccessCodeDevice({ deviceId, onSelectDevice, }: {
|
|
2
3
|
deviceId: string;
|
|
4
|
+
onSelectDevice: (device: Device<CommonDeviceProperties>) => void;
|
|
3
5
|
}): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useNavigation } from '../../../lib/NavigationProvider.js';
|
|
3
2
|
import { isLockDevice } from '../../../lib/seam/devices/types.js';
|
|
4
3
|
import { useFakeDevice } from '../../../lib/seam/devices/use-device.js';
|
|
5
4
|
import { Button } from '../../../lib/ui/Button.js';
|
|
6
5
|
import { DeviceImage } from '../../../lib/ui/device/DeviceImage.js';
|
|
7
6
|
import { getDeviceModel } from '../../../lib/ui/DeviceDetails/DeviceModel.js';
|
|
8
7
|
import { TextButton } from '../../../lib/ui/TextButton.js';
|
|
9
|
-
export
|
|
8
|
+
export function AccessCodeDevice({ deviceId, onSelectDevice, }) {
|
|
10
9
|
// TODO: Replace with `useDevice()` once ready
|
|
11
10
|
const { isLoading, device } = useFakeDevice({ device_id: deviceId });
|
|
12
|
-
const { show } = useNavigation();
|
|
13
11
|
// TODO: Do we want to return a skeleton loader here instead?
|
|
14
12
|
if (isLoading || !device || !isLockDevice(device)) {
|
|
15
13
|
return null;
|
|
16
14
|
}
|
|
17
15
|
const model = getDeviceModel(device);
|
|
18
16
|
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: () => {
|
|
19
|
-
|
|
17
|
+
onSelectDevice(device);
|
|
20
18
|
}, children: t.deviceDetails })] }), _jsx(Button, { children: "Unlock" })] }));
|
|
21
19
|
}
|
|
22
20
|
const t = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessCodeDevice.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeDetails/AccessCodeDevice.tsx"],"names":[],"mappings":";
|
|
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,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAC9D,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,+CAA+C;IAC/C,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAA;IAEpE,6DAA6D;IAC7D,IAAI,SAAS,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE;QACjD,OAAO,IAAI,CAAA;KACZ;IAED,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC,CAAA;IAEpC,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,CAAA;wBACxB,CAAC,YAEA,CAAC,CAAC,aAAa,GACL,IACT,EACN,KAAC,MAAM,yBAAgB,IACnB,CACP,CAAA;AACH,CAAC;AAED,MAAM,CAAC,GAAG;IACR,aAAa,EAAE,gBAAgB;CAChC,CAAA"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
2
3
|
import { AccessCodeKeyIcon } from '../../../lib/icons/AccessCodeKey.js';
|
|
3
|
-
import { useNavigation } from '../../../lib/NavigationProvider.js';
|
|
4
4
|
import { useAccessCodes } from '../../../lib/seam/access-codes/use-access-codes.js';
|
|
5
|
+
import { AccessCodeDetails } from '../../../lib/ui/AccessCodeDetails/AccessCodeDetails.js';
|
|
5
6
|
import { CodeDetails } from '../../../lib/ui/AccessCodeTable/CodeDetails.js';
|
|
6
7
|
import { ContentHeader } from '../../../lib/ui/layout/ContentHeader.js';
|
|
7
8
|
import { TableBody } from '../../../lib/ui/Table/TableBody.js';
|
|
@@ -15,14 +16,17 @@ export function AccessCodeTable(props) {
|
|
|
15
16
|
const { accessCodes } = useAccessCodes({
|
|
16
17
|
device_id: props.deviceId,
|
|
17
18
|
});
|
|
18
|
-
const {
|
|
19
|
+
const { onBack } = props;
|
|
20
|
+
const [selectedAccessCode, selectAccessCode] = useState(null);
|
|
21
|
+
if (selectedAccessCode) {
|
|
22
|
+
return (_jsx(AccessCodeDetails, { accessCode: selectedAccessCode, onBack: () => {
|
|
23
|
+
selectAccessCode(null);
|
|
24
|
+
} }));
|
|
25
|
+
}
|
|
19
26
|
if (!accessCodes)
|
|
20
27
|
return _jsx(_Fragment, { children: null });
|
|
21
|
-
return (_jsxs("div", { className: 'seam-access-code-table', children: [_jsx(ContentHeader, {}), _jsx(TableHeader, { children: _jsxs(TableTitle, { children: [t.accessCodes, " ", _jsxs(Caption, { children: ["(", accessCodes.length, ")"] })] }) }), _jsx(TableBody, { children: accessCodes.map((code) => (_jsxs(TableRow, { onClick: () => {
|
|
22
|
-
|
|
23
|
-
name: 'access_code_detail',
|
|
24
|
-
accessCodeId: code.access_code_id,
|
|
25
|
-
});
|
|
28
|
+
return (_jsxs("div", { className: 'seam-access-code-table', children: [_jsx(ContentHeader, { onBack: onBack }), _jsx(TableHeader, { children: _jsxs(TableTitle, { children: [t.accessCodes, " ", _jsxs(Caption, { children: ["(", accessCodes.length, ")"] })] }) }), _jsx(TableBody, { children: accessCodes.map((code) => (_jsxs(TableRow, { onClick: () => {
|
|
29
|
+
selectAccessCode(code);
|
|
26
30
|
}, children: [_jsx(TableCell, { className: 'seam-icon-cell', children: _jsx("div", { children: _jsx(AccessCodeKeyIcon, {}) }) }), _jsxs(TableCell, { className: 'seam-name-cell', children: [_jsx(Title, { children: code.name }), _jsx(CodeDetails, { accessCode: code })] }), _jsx(TableCell, { className: 'seam-action-cell' })] }, code.access_code_id))) })] }));
|
|
27
31
|
}
|
|
28
32
|
const t = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessCodeTable.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeTable/AccessCodeTable.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"AccessCodeTable.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeTable/AccessCodeTable.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAGhC,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAA;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAA;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAA;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAElD,MAAM,UAAU,eAAe,CAAC,KAG/B;IACC,MAAM,EAAE,WAAW,EAAE,GAAG,cAAc,CAAC;QACrC,SAAS,EAAE,KAAK,CAAC,QAAQ;KAC1B,CAAC,CAAA;IACF,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;IAExB,MAAM,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CACrD,IAAI,CACL,CAAA;IAED,IAAI,kBAAkB,EAAE;QACtB,OAAO,CACL,KAAC,iBAAiB,IAChB,UAAU,EAAE,kBAAkB,EAC9B,MAAM,EAAE,GAAG,EAAE;gBACX,gBAAgB,CAAC,IAAI,CAAC,CAAA;YACxB,CAAC,GACD,CACH,CAAA;KACF;IAED,IAAI,CAAC,WAAW;QAAE,OAAO,4BAAG,IAAI,GAAI,CAAA;IAEpC,OAAO,CACL,eAAK,SAAS,EAAC,wBAAwB,aACrC,KAAC,aAAa,IAAC,MAAM,EAAE,MAAM,GAAI,EACjC,KAAC,WAAW,cACV,MAAC,UAAU,eACR,CAAC,CAAC,WAAW,OAAE,MAAC,OAAO,oBAAG,WAAW,CAAC,MAAM,SAAY,IAC9C,GACD,EACd,KAAC,SAAS,cACP,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACzB,MAAC,QAAQ,IAEP,OAAO,EAAE,GAAG,EAAE;wBACZ,gBAAgB,CAAC,IAAI,CAAC,CAAA;oBACxB,CAAC,aAED,KAAC,SAAS,IAAC,SAAS,EAAC,gBAAgB,YACnC,wBACE,KAAC,iBAAiB,KAAG,GACjB,GACI,EACZ,MAAC,SAAS,IAAC,SAAS,EAAC,gBAAgB,aACnC,KAAC,KAAK,cAAE,IAAI,CAAC,IAAI,GAAS,EAC1B,KAAC,WAAW,IAAC,UAAU,EAAE,IAAI,GAAI,IACvB,EACZ,KAAC,SAAS,IAAC,SAAS,EAAC,kBAAkB,GAI3B,KAlBP,IAAI,CAAC,cAAc,CAmBf,CACZ,CAAC,GACQ,IACR,CACP,CAAA;AACH,CAAC;AAED,MAAM,CAAC,GAAG;IACR,WAAW,EAAE,cAAc;CAC5B,CAAA"}
|
|
@@ -10,8 +10,8 @@ import { TableTitle } from '../../../lib/ui/Table/TableTitle.js';
|
|
|
10
10
|
import { Caption } from '../../../lib/ui/typography/Caption.js';
|
|
11
11
|
import { Title } from '../../../lib/ui/typography/Title.js';
|
|
12
12
|
export function AccessCodeTableContent(props) {
|
|
13
|
-
const { accessCodes } = props;
|
|
14
|
-
return (_jsxs("div", { className: 'seam-access-code-table', children: [_jsx(ContentHeader, {}), _jsx(TableHeader, { children: _jsxs(TableTitle, { children: [t.accessCodes, " ", _jsxs(Caption, { children: ["(", accessCodes.length, ")"] })] }) }), _jsx(TableBody, { children: accessCodes.map((code) => (_jsxs(TableRow, { children: [_jsx(TableCell, { className: 'seam-icon-cell', children: _jsx("div", { children: _jsx(AccessCodeKeyIcon, {}) }) }), _jsxs(TableCell, { className: 'seam-name-cell', children: [_jsx(Title, { children: code.name }), _jsx(CodeDetails, { accessCode: code })] }), _jsx(TableCell, { className: 'seam-action-cell' })] }, code.access_code_id))) })] }));
|
|
13
|
+
const { accessCodes, onBack } = props;
|
|
14
|
+
return (_jsxs("div", { className: 'seam-access-code-table', children: [_jsx(ContentHeader, { onBack: onBack }), _jsx(TableHeader, { children: _jsxs(TableTitle, { children: [t.accessCodes, " ", _jsxs(Caption, { children: ["(", accessCodes.length, ")"] })] }) }), _jsx(TableBody, { children: accessCodes.map((code) => (_jsxs(TableRow, { children: [_jsx(TableCell, { className: 'seam-icon-cell', children: _jsx("div", { children: _jsx(AccessCodeKeyIcon, {}) }) }), _jsxs(TableCell, { className: 'seam-name-cell', children: [_jsx(Title, { children: code.name }), _jsx(CodeDetails, { accessCode: code })] }), _jsx(TableCell, { className: 'seam-action-cell' })] }, code.access_code_id))) })] }));
|
|
15
15
|
}
|
|
16
16
|
const t = {
|
|
17
17
|
accessCodes: 'Access Codes',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessCodeTableContent.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeTable/AccessCodeTableContent.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAA;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"AccessCodeTableContent.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeTable/AccessCodeTableContent.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAA;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAOlD,MAAM,UAAU,sBAAsB,CACpC,KAAkC;IAElC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;IAErC,OAAO,CACL,eAAK,SAAS,EAAC,wBAAwB,aACrC,KAAC,aAAa,IAAC,MAAM,EAAE,MAAM,GAAI,EACjC,KAAC,WAAW,cACV,MAAC,UAAU,eACR,CAAC,CAAC,WAAW,OAAE,MAAC,OAAO,oBAAG,WAAW,CAAC,MAAM,SAAY,IAC9C,GACD,EACd,KAAC,SAAS,cACP,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACzB,MAAC,QAAQ,eACP,KAAC,SAAS,IAAC,SAAS,EAAC,gBAAgB,YACnC,wBACE,KAAC,iBAAiB,KAAG,GACjB,GACI,EACZ,MAAC,SAAS,IAAC,SAAS,EAAC,gBAAgB,aACnC,KAAC,KAAK,cAAE,IAAI,CAAC,IAAI,GAAS,EAC1B,KAAC,WAAW,IAAC,UAAU,EAAE,IAAI,GAAI,IACvB,EACZ,KAAC,SAAS,IAAC,SAAS,EAAC,kBAAkB,GAI3B,KAdC,IAAI,CAAC,cAAc,CAevB,CACZ,CAAC,GACQ,IACR,CACP,CAAA;AACH,CAAC;AAED,MAAM,CAAC,GAAG;IACR,WAAW,EAAE,cAAc;CAC5B,CAAA"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { type CommonDeviceProperties, type Device } from 'seamapi';
|
|
1
2
|
export interface DeviceDetailsProps {
|
|
2
|
-
|
|
3
|
+
device: Device<CommonDeviceProperties>;
|
|
4
|
+
onBack?: () => void;
|
|
3
5
|
}
|
|
4
6
|
export declare function DeviceDetails(props: DeviceDetailsProps): JSX.Element | null;
|
|
@@ -1,37 +1,35 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import {} from 'seamapi';
|
|
2
3
|
import { ChevronRightIcon } from '../../../lib/icons/ChevronRight.js';
|
|
3
|
-
import { useNavigation } from '../../../lib/NavigationProvider.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 {
|
|
6
|
+
import { AccessCodeTable } from '../../../lib/ui/AccessCodeTable/AccessCodeTable.js';
|
|
7
7
|
import { Button } from '../../../lib/ui/Button.js';
|
|
8
8
|
import { BatteryStatus } from '../../../lib/ui/device/BatteryStatus.js';
|
|
9
9
|
import { DeviceImage } from '../../../lib/ui/device/DeviceImage.js';
|
|
10
10
|
import { OnlineStatus } from '../../../lib/ui/device/OnlineStatus.js';
|
|
11
11
|
import { DeviceModel } from '../../../lib/ui/DeviceDetails/DeviceModel.js';
|
|
12
12
|
import { ContentHeader } from '../../../lib/ui/layout/ContentHeader.js';
|
|
13
|
+
import useToggle from '../../../lib/use-toggle.js';
|
|
13
14
|
export function DeviceDetails(props) {
|
|
14
|
-
const {
|
|
15
|
-
const
|
|
16
|
-
|
|
15
|
+
const { device, onBack } = props;
|
|
16
|
+
const [showingAccessCodes, toggleAccessCodes] = useToggle();
|
|
17
|
+
const { isLoading, accessCodes } = useAccessCodes({
|
|
18
|
+
device_id: device.device_id,
|
|
17
19
|
});
|
|
18
|
-
|
|
19
|
-
device_id: deviceId,
|
|
20
|
-
});
|
|
21
|
-
const isLoading = isLoadingDevice || isLoadingAccessCodes;
|
|
22
|
-
const { show } = useNavigation();
|
|
23
|
-
if (isLoading || !device) {
|
|
20
|
+
if (isLoading) {
|
|
24
21
|
return null;
|
|
25
22
|
}
|
|
23
|
+
if (showingAccessCodes) {
|
|
24
|
+
return (_jsx(AccessCodeTable, { deviceId: device.device_id, onBack: toggleAccessCodes }));
|
|
25
|
+
}
|
|
26
26
|
if (!isLockDevice(device)) {
|
|
27
27
|
return null;
|
|
28
28
|
}
|
|
29
29
|
const lockStatus = device.properties.locked ? t.locked : t.unlocked;
|
|
30
30
|
const accessCodeCount = accessCodes?.length;
|
|
31
31
|
const accessCodeLength = device.properties?.schlage_metadata?.access_code_length;
|
|
32
|
-
return (_jsxs("div", { className: 'seam-device-details', children: [_jsx(ContentHeader, { title: 'Device' }), _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: ()
|
|
33
|
-
show({ name: 'access_code_table', deviceId: device.device_id });
|
|
34
|
-
}, 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', children: t.unlock }) })] }), _jsx(AccessCodeLength, { accessCodeLength: accessCodeLength })] })] })] }));
|
|
32
|
+
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: toggleAccessCodes, 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', children: t.unlock }) })] }), _jsx(AccessCodeLength, { accessCodeLength: accessCodeLength })] })] })] }));
|
|
35
33
|
}
|
|
36
34
|
function AccessCodeLength(props) {
|
|
37
35
|
const { accessCodeLength } = props;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeviceDetails.js","sourceRoot":"","sources":["../../../src/lib/ui/DeviceDetails/DeviceDetails.tsx"],"names":[],"mappings":";AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"DeviceDetails.js","sourceRoot":"","sources":["../../../src/lib/ui/DeviceDetails/DeviceDetails.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useState } from 'react';
|
|
3
3
|
import { isLockDevice } from '../../../lib/seam/devices/types.js';
|
|
4
4
|
import { useDevices, } from '../../../lib/seam/devices/use-devices.js';
|
|
5
5
|
import { BatteryStatus } from '../../../lib/ui/device/BatteryStatus.js';
|
|
6
6
|
import { DeviceImage } from '../../../lib/ui/device/DeviceImage.js';
|
|
7
7
|
import { LockStatus } from '../../../lib/ui/device/LockStatus.js';
|
|
8
8
|
import { OnlineStatus } from '../../../lib/ui/device/OnlineStatus.js';
|
|
9
|
+
import { DeviceDetails } from '../../../lib/ui/DeviceDetails/DeviceDetails.js';
|
|
9
10
|
import { getDeviceModel } from '../../../lib/ui/DeviceDetails/DeviceModel.js';
|
|
10
11
|
import { ContentHeader } from '../../../lib/ui/layout/ContentHeader.js';
|
|
11
12
|
import { TableBody } from '../../../lib/ui/Table/TableBody.js';
|
|
@@ -17,7 +18,12 @@ import { Caption } from '../../../lib/ui/typography/Caption.js';
|
|
|
17
18
|
import { Title } from '../../../lib/ui/typography/Title.js';
|
|
18
19
|
export function DeviceTable({ onBack, ...props }) {
|
|
19
20
|
const { devices, isLoading, isError, error } = useDevices(props);
|
|
20
|
-
const
|
|
21
|
+
const [selectedDevice, selectDevice] = useState(null);
|
|
22
|
+
if (selectedDevice) {
|
|
23
|
+
return (_jsx(DeviceDetails, { device: selectedDevice, onBack: () => {
|
|
24
|
+
selectDevice(null);
|
|
25
|
+
} }));
|
|
26
|
+
}
|
|
21
27
|
if (isLoading)
|
|
22
28
|
return _jsx("p", { children: "..." });
|
|
23
29
|
if (isError)
|
|
@@ -25,8 +31,8 @@ export function DeviceTable({ onBack, ...props }) {
|
|
|
25
31
|
if (devices == null)
|
|
26
32
|
return null;
|
|
27
33
|
const deviceCount = devices.length;
|
|
28
|
-
return (_jsxs("div", { className: 'seam-device-table', children: [_jsx(ContentHeader, {}), _jsx(TableHeader, { children: _jsxs(TableTitle, { children: [t.devices, " ", _jsxs(Caption, { children: ["(", deviceCount, ")"] })] }) }), _jsx(TableBody, { children: devices.map((device) => (_jsx(DeviceRow, { device: device, onClick: () => {
|
|
29
|
-
|
|
34
|
+
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: () => {
|
|
35
|
+
selectDevice(device);
|
|
30
36
|
} }, device.device_id))) })] }));
|
|
31
37
|
}
|
|
32
38
|
function DeviceRow(props) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeviceTable.js","sourceRoot":"","sources":["../../../src/lib/ui/DeviceTable/DeviceTable.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"DeviceTable.js","sourceRoot":"","sources":["../../../src/lib/ui/DeviceTable/DeviceTable.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ArrowBackIcon } from '../../../lib/icons/ArrowBack.js';
|
|
3
|
-
import { useNavigation } from '../../../lib/NavigationProvider.js';
|
|
4
3
|
export function ContentHeader(props) {
|
|
5
|
-
const { title } = props;
|
|
6
|
-
|
|
7
|
-
if (!title && !goBack) {
|
|
4
|
+
const { title, onBack } = props;
|
|
5
|
+
if (!title && !onBack) {
|
|
8
6
|
return null;
|
|
9
7
|
}
|
|
10
|
-
return (_jsxs("div", { className: 'seam-content-header', children: [
|
|
8
|
+
return (_jsxs("div", { className: 'seam-content-header', children: [_jsx(BackIcon, { onClick: onBack }), _jsx("span", { className: 'seam-title', children: title })] }));
|
|
11
9
|
}
|
|
12
10
|
function BackIcon(props) {
|
|
13
11
|
if (props.onClick == null) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContentHeader.js","sourceRoot":"","sources":["../../../src/lib/ui/layout/ContentHeader.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"ContentHeader.js","sourceRoot":"","sources":["../../../src/lib/ui/layout/ContentHeader.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAEtD,MAAM,UAAU,aAAa,CAAC,KAG7B;IACC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;IAC/B,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE;QACrB,OAAO,IAAI,CAAA;KACZ;IAED,OAAO,CACL,eAAK,SAAS,EAAC,qBAAqB,aAClC,KAAC,QAAQ,IAAC,OAAO,EAAE,MAAM,GAAI,EAC7B,eAAM,SAAS,EAAC,YAAY,YAAE,KAAK,GAAQ,IACvC,CACP,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAA+B;IAC/C,IAAI,KAAK,CAAC,OAAO,IAAI,IAAI,EAAE;QACzB,OAAO,IAAI,CAAA;KACZ;IAED,OAAO,KAAC,aAAa,IAAC,SAAS,EAAC,gBAAgB,EAAC,OAAO,EAAE,KAAK,CAAC,OAAO,GAAI,CAAA;AAC7E,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seamapi/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Seam React component library.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -58,7 +58,6 @@
|
|
|
58
58
|
"docs:build": "storybook build --docs --output-dir docs",
|
|
59
59
|
"predocs:build": "npm run examples:build",
|
|
60
60
|
"typecheck": "tsc",
|
|
61
|
-
"dependencies": "dpdm --exit-code circular:1 src/index.ts",
|
|
62
61
|
"test": "jest --collect-coverage",
|
|
63
62
|
"test:update": "jest --updateSnapshot",
|
|
64
63
|
"test:watch": "jest --watch",
|
|
@@ -126,7 +125,6 @@
|
|
|
126
125
|
"concurrently": "^8.0.1",
|
|
127
126
|
"copy-webpack-plugin": "^11.0.0",
|
|
128
127
|
"del-cli": "^5.0.0",
|
|
129
|
-
"dpdm": "^3.13.0",
|
|
130
128
|
"eslint": "^8.9.0",
|
|
131
129
|
"eslint-config-prettier": "^8.4.0",
|
|
132
130
|
"eslint-config-standard-jsx": "^11.0.0",
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { useQuery } from '@tanstack/react-query'
|
|
2
|
-
import { DateTime } from 'luxon'
|
|
3
2
|
import type { AccessCode, AccessCodeGetRequest } from 'seamapi'
|
|
4
|
-
import { v4 as uuid } from 'uuid'
|
|
5
3
|
|
|
6
4
|
import { useSeamClient } from 'lib/seam/use-seam-client.js'
|
|
7
5
|
|
|
@@ -24,22 +22,3 @@ export function useAccessCode(params: UseAccessCodeParams) {
|
|
|
24
22
|
},
|
|
25
23
|
})
|
|
26
24
|
}
|
|
27
|
-
|
|
28
|
-
export function useFakeAccessCode(_params: UseAccessCodeParams): {
|
|
29
|
-
isLoading: boolean
|
|
30
|
-
data: AccessCode
|
|
31
|
-
} {
|
|
32
|
-
const accessCode: AccessCode = {
|
|
33
|
-
access_code_id: uuid(),
|
|
34
|
-
type: 'time_bound',
|
|
35
|
-
starts_at: DateTime.now().minus({ days: 2 }).toISO() ?? '',
|
|
36
|
-
ends_at: DateTime.now().plus({ days: 1 }).toISO() ?? '',
|
|
37
|
-
code: '1234',
|
|
38
|
-
created_at: DateTime.now().toISO() ?? '',
|
|
39
|
-
device_id: 'some_device_id',
|
|
40
|
-
status: 'set',
|
|
41
|
-
name: 'Guest - Kranz',
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return { isLoading: false, data: accessCode }
|
|
45
|
-
}
|
|
@@ -1,31 +1,38 @@
|
|
|
1
1
|
import { DateTime } from 'luxon'
|
|
2
|
-
import
|
|
2
|
+
import { useState } from 'react'
|
|
3
|
+
import type { AccessCode, CommonDeviceProperties, Device } from 'seamapi'
|
|
3
4
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import AccessCodeDevice from 'lib/ui/AccessCodeDetails/AccessCodeDevice.js'
|
|
5
|
+
import { AccessCodeDevice } from 'lib/ui/AccessCodeDetails/AccessCodeDevice.js'
|
|
6
|
+
import { DeviceDetails } from 'lib/ui/DeviceDetails/DeviceDetails.js'
|
|
7
7
|
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
8
8
|
|
|
9
9
|
export interface AccessCodeDetailsProps {
|
|
10
|
-
|
|
10
|
+
accessCode: AccessCode
|
|
11
|
+
onBack?: () => void
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
export
|
|
14
|
-
|
|
14
|
+
export function AccessCodeDetails({
|
|
15
|
+
accessCode,
|
|
16
|
+
onBack,
|
|
15
17
|
}: AccessCodeDetailsProps) {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
const name = accessCode.name ?? t.fallbackName
|
|
19
|
+
const [selectedDevice, selectDevice] =
|
|
20
|
+
useState<Device<CommonDeviceProperties> | null>(null)
|
|
19
21
|
|
|
20
|
-
if (
|
|
21
|
-
return
|
|
22
|
+
if (selectedDevice) {
|
|
23
|
+
return (
|
|
24
|
+
<DeviceDetails
|
|
25
|
+
device={selectedDevice}
|
|
26
|
+
onBack={() => {
|
|
27
|
+
selectDevice(null)
|
|
28
|
+
}}
|
|
29
|
+
/>
|
|
30
|
+
)
|
|
22
31
|
}
|
|
23
32
|
|
|
24
|
-
const name = accessCode.name ?? t.fallbackName
|
|
25
|
-
|
|
26
33
|
return (
|
|
27
34
|
<div className='seam-access-code-details'>
|
|
28
|
-
<ContentHeader title='Access code' />
|
|
35
|
+
<ContentHeader title='Access code' onBack={onBack} />
|
|
29
36
|
<div className='seam-summary'>
|
|
30
37
|
<div className='seam-top'>
|
|
31
38
|
<span className='seam-label'>{t.accessCode}</span>
|
|
@@ -35,7 +42,10 @@ export default function AccessCodeDetails({
|
|
|
35
42
|
<Duration accessCode={accessCode} />
|
|
36
43
|
</div>
|
|
37
44
|
</div>
|
|
38
|
-
<AccessCodeDevice
|
|
45
|
+
<AccessCodeDevice
|
|
46
|
+
deviceId={accessCode.device_id}
|
|
47
|
+
onSelectDevice={selectDevice}
|
|
48
|
+
/>
|
|
39
49
|
</div>
|
|
40
50
|
<div className='seam-details'>
|
|
41
51
|
<div className='seam-row'>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { CommonDeviceProperties, Device } from 'seamapi'
|
|
2
|
+
|
|
2
3
|
import { isLockDevice } from 'lib/seam/devices/types.js'
|
|
3
4
|
import { useFakeDevice } from 'lib/seam/devices/use-device.js'
|
|
4
5
|
import { Button } from 'lib/ui/Button.js'
|
|
@@ -6,10 +7,15 @@ 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
|
|
|
9
|
-
export
|
|
10
|
+
export function AccessCodeDevice({
|
|
11
|
+
deviceId,
|
|
12
|
+
onSelectDevice,
|
|
13
|
+
}: {
|
|
14
|
+
deviceId: string
|
|
15
|
+
onSelectDevice: (device: Device<CommonDeviceProperties>) => void
|
|
16
|
+
}) {
|
|
10
17
|
// TODO: Replace with `useDevice()` once ready
|
|
11
18
|
const { isLoading, device } = useFakeDevice({ device_id: deviceId })
|
|
12
|
-
const { show } = useNavigation()
|
|
13
19
|
|
|
14
20
|
// TODO: Do we want to return a skeleton loader here instead?
|
|
15
21
|
if (isLoading || !device || !isLockDevice(device)) {
|
|
@@ -27,7 +33,7 @@ export default function AccessCodeDevice({ deviceId }: { deviceId: string }) {
|
|
|
27
33
|
<div className='seam-model'>{model}</div>
|
|
28
34
|
<TextButton
|
|
29
35
|
onClick={() => {
|
|
30
|
-
|
|
36
|
+
onSelectDevice(device)
|
|
31
37
|
}}
|
|
32
38
|
>
|
|
33
39
|
{t.deviceDetails}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import type { AccessCode } from 'seamapi'
|
|
3
|
+
|
|
1
4
|
import { AccessCodeKeyIcon } from 'lib/icons/AccessCodeKey.js'
|
|
2
|
-
import { useNavigation } from 'lib/NavigationProvider.js'
|
|
3
5
|
import { useAccessCodes } from 'lib/seam/access-codes/use-access-codes.js'
|
|
6
|
+
import { AccessCodeDetails } from 'lib/ui/AccessCodeDetails/AccessCodeDetails.js'
|
|
4
7
|
import { CodeDetails } from 'lib/ui/AccessCodeTable/CodeDetails.js'
|
|
5
8
|
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
6
9
|
import { TableBody } from 'lib/ui/Table/TableBody.js'
|
|
@@ -11,18 +14,35 @@ import { TableTitle } from 'lib/ui/Table/TableTitle.js'
|
|
|
11
14
|
import { Caption } from 'lib/ui/typography/Caption.js'
|
|
12
15
|
import { Title } from 'lib/ui/typography/Title.js'
|
|
13
16
|
|
|
14
|
-
export function AccessCodeTable(props: {
|
|
17
|
+
export function AccessCodeTable(props: {
|
|
18
|
+
deviceId: string
|
|
19
|
+
onBack?: () => void
|
|
20
|
+
}): JSX.Element {
|
|
15
21
|
const { accessCodes } = useAccessCodes({
|
|
16
22
|
device_id: props.deviceId,
|
|
17
23
|
})
|
|
24
|
+
const { onBack } = props
|
|
25
|
+
|
|
26
|
+
const [selectedAccessCode, selectAccessCode] = useState<AccessCode | null>(
|
|
27
|
+
null
|
|
28
|
+
)
|
|
18
29
|
|
|
19
|
-
|
|
30
|
+
if (selectedAccessCode) {
|
|
31
|
+
return (
|
|
32
|
+
<AccessCodeDetails
|
|
33
|
+
accessCode={selectedAccessCode}
|
|
34
|
+
onBack={() => {
|
|
35
|
+
selectAccessCode(null)
|
|
36
|
+
}}
|
|
37
|
+
/>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
20
40
|
|
|
21
41
|
if (!accessCodes) return <>{null}</>
|
|
22
42
|
|
|
23
43
|
return (
|
|
24
44
|
<div className='seam-access-code-table'>
|
|
25
|
-
<ContentHeader />
|
|
45
|
+
<ContentHeader onBack={onBack} />
|
|
26
46
|
<TableHeader>
|
|
27
47
|
<TableTitle>
|
|
28
48
|
{t.accessCodes} <Caption>({accessCodes.length})</Caption>
|
|
@@ -33,10 +53,7 @@ export function AccessCodeTable(props: { deviceId: string }): JSX.Element {
|
|
|
33
53
|
<TableRow
|
|
34
54
|
key={code.access_code_id}
|
|
35
55
|
onClick={() => {
|
|
36
|
-
|
|
37
|
-
name: 'access_code_detail',
|
|
38
|
-
accessCodeId: code.access_code_id,
|
|
39
|
-
})
|
|
56
|
+
selectAccessCode(code)
|
|
40
57
|
}}
|
|
41
58
|
>
|
|
42
59
|
<TableCell className='seam-icon-cell'>
|
|
@@ -13,16 +13,17 @@ import { Title } from 'lib/ui/typography/Title.js'
|
|
|
13
13
|
|
|
14
14
|
export interface AccessCodeTableContentProps {
|
|
15
15
|
accessCodes: AccessCode[]
|
|
16
|
+
onBack?: () => void
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export function AccessCodeTableContent(
|
|
19
20
|
props: AccessCodeTableContentProps
|
|
20
21
|
): JSX.Element {
|
|
21
|
-
const { accessCodes } = props
|
|
22
|
+
const { accessCodes, onBack } = props
|
|
22
23
|
|
|
23
24
|
return (
|
|
24
25
|
<div className='seam-access-code-table'>
|
|
25
|
-
<ContentHeader />
|
|
26
|
+
<ContentHeader onBack={onBack} />
|
|
26
27
|
<TableHeader>
|
|
27
28
|
<TableTitle>
|
|
28
29
|
{t.accessCodes} <Caption>({accessCodes.length})</Caption>
|
|
@@ -1,38 +1,41 @@
|
|
|
1
|
+
import { type CommonDeviceProperties, type Device } from 'seamapi'
|
|
2
|
+
|
|
1
3
|
import { ChevronRightIcon } from 'lib/icons/ChevronRight.js'
|
|
2
|
-
import { useNavigation } from 'lib/NavigationProvider.js'
|
|
3
4
|
import { useAccessCodes } from 'lib/seam/access-codes/use-access-codes.js'
|
|
4
5
|
import { isLockDevice } from 'lib/seam/devices/types.js'
|
|
5
|
-
import {
|
|
6
|
+
import { AccessCodeTable } from 'lib/ui/AccessCodeTable/AccessCodeTable.js'
|
|
6
7
|
import { Button } from 'lib/ui/Button.js'
|
|
7
8
|
import { BatteryStatus } from 'lib/ui/device/BatteryStatus.js'
|
|
8
9
|
import { DeviceImage } from 'lib/ui/device/DeviceImage.js'
|
|
9
10
|
import { OnlineStatus } from 'lib/ui/device/OnlineStatus.js'
|
|
10
11
|
import { DeviceModel } from 'lib/ui/DeviceDetails/DeviceModel.js'
|
|
11
12
|
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
13
|
+
import useToggle from 'lib/use-toggle.js'
|
|
12
14
|
|
|
13
15
|
export interface DeviceDetailsProps {
|
|
14
|
-
|
|
16
|
+
device: Device<CommonDeviceProperties>
|
|
17
|
+
onBack?: () => void
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
export function DeviceDetails(props: DeviceDetailsProps): JSX.Element | null {
|
|
18
|
-
const {
|
|
21
|
+
const { device, onBack } = props
|
|
19
22
|
|
|
20
|
-
const
|
|
21
|
-
device_id: deviceId,
|
|
22
|
-
})
|
|
23
|
+
const [showingAccessCodes, toggleAccessCodes] = useToggle()
|
|
23
24
|
|
|
24
|
-
const { isLoading
|
|
25
|
-
device_id:
|
|
25
|
+
const { isLoading, accessCodes } = useAccessCodes({
|
|
26
|
+
device_id: device.device_id,
|
|
26
27
|
})
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const { show } = useNavigation()
|
|
31
|
-
|
|
32
|
-
if (isLoading || !device) {
|
|
29
|
+
if (isLoading) {
|
|
33
30
|
return null
|
|
34
31
|
}
|
|
35
32
|
|
|
33
|
+
if (showingAccessCodes) {
|
|
34
|
+
return (
|
|
35
|
+
<AccessCodeTable deviceId={device.device_id} onBack={toggleAccessCodes} />
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
36
39
|
if (!isLockDevice(device)) {
|
|
37
40
|
return null
|
|
38
41
|
}
|
|
@@ -46,7 +49,7 @@ export function DeviceDetails(props: DeviceDetailsProps): JSX.Element | null {
|
|
|
46
49
|
|
|
47
50
|
return (
|
|
48
51
|
<div className='seam-device-details'>
|
|
49
|
-
<ContentHeader title='Device' />
|
|
52
|
+
<ContentHeader title='Device' onBack={onBack} />
|
|
50
53
|
<div className='seam-body'>
|
|
51
54
|
<div className='seam-summary'>
|
|
52
55
|
<div className='seam-content'>
|
|
@@ -69,9 +72,7 @@ export function DeviceDetails(props: DeviceDetailsProps): JSX.Element | null {
|
|
|
69
72
|
<div className='seam-box'>
|
|
70
73
|
<div
|
|
71
74
|
className='seam-content seam-access-codes'
|
|
72
|
-
onClick={
|
|
73
|
-
show({ name: 'access_code_table', deviceId: device.device_id })
|
|
74
|
-
}}
|
|
75
|
+
onClick={toggleAccessCodes}
|
|
75
76
|
>
|
|
76
77
|
<span className='seam-value'>
|
|
77
78
|
{accessCodeCount} {t.accessCodes}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import type { CommonDeviceProperties, Device } from 'seamapi'
|
|
3
|
+
|
|
2
4
|
import { isLockDevice } from 'lib/seam/devices/types.js'
|
|
3
5
|
import {
|
|
4
6
|
useDevices,
|
|
@@ -9,6 +11,7 @@ import { BatteryStatus } from 'lib/ui/device/BatteryStatus.js'
|
|
|
9
11
|
import { DeviceImage } from 'lib/ui/device/DeviceImage.js'
|
|
10
12
|
import { LockStatus } from 'lib/ui/device/LockStatus.js'
|
|
11
13
|
import { OnlineStatus } from 'lib/ui/device/OnlineStatus.js'
|
|
14
|
+
import { DeviceDetails } from 'lib/ui/DeviceDetails/DeviceDetails.js'
|
|
12
15
|
import { getDeviceModel } from 'lib/ui/DeviceDetails/DeviceModel.js'
|
|
13
16
|
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
14
17
|
import { TableBody } from 'lib/ui/Table/TableBody.js'
|
|
@@ -27,7 +30,20 @@ interface Props {
|
|
|
27
30
|
|
|
28
31
|
export function DeviceTable({ onBack, ...props }: DeviceTableProps) {
|
|
29
32
|
const { devices, isLoading, isError, error } = useDevices(props)
|
|
30
|
-
|
|
33
|
+
|
|
34
|
+
const [selectedDevice, selectDevice] =
|
|
35
|
+
useState<Device<CommonDeviceProperties> | null>(null)
|
|
36
|
+
|
|
37
|
+
if (selectedDevice) {
|
|
38
|
+
return (
|
|
39
|
+
<DeviceDetails
|
|
40
|
+
device={selectedDevice}
|
|
41
|
+
onBack={() => {
|
|
42
|
+
selectDevice(null)
|
|
43
|
+
}}
|
|
44
|
+
/>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
31
47
|
|
|
32
48
|
if (isLoading) return <p>...</p>
|
|
33
49
|
if (isError) return <p>{error?.message}</p>
|
|
@@ -37,7 +53,7 @@ export function DeviceTable({ onBack, ...props }: DeviceTableProps) {
|
|
|
37
53
|
|
|
38
54
|
return (
|
|
39
55
|
<div className='seam-device-table'>
|
|
40
|
-
<ContentHeader />
|
|
56
|
+
<ContentHeader onBack={onBack} />
|
|
41
57
|
<TableHeader>
|
|
42
58
|
<TableTitle>
|
|
43
59
|
{t.devices} <Caption>({deviceCount})</Caption>
|
|
@@ -49,7 +65,7 @@ export function DeviceTable({ onBack, ...props }: DeviceTableProps) {
|
|
|
49
65
|
device={device}
|
|
50
66
|
key={device.device_id}
|
|
51
67
|
onClick={() => {
|
|
52
|
-
|
|
68
|
+
selectDevice(device)
|
|
53
69
|
}}
|
|
54
70
|
/>
|
|
55
71
|
))}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { ArrowBackIcon } from 'lib/icons/ArrowBack.js'
|
|
2
|
-
import { useNavigation } from 'lib/NavigationProvider.js'
|
|
3
2
|
|
|
4
|
-
export function ContentHeader(props: {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
export function ContentHeader(props: {
|
|
4
|
+
title?: string
|
|
5
|
+
onBack?: () => void
|
|
6
|
+
}): JSX.Element | null {
|
|
7
|
+
const { title, onBack } = props
|
|
8
|
+
if (!title && !onBack) {
|
|
9
9
|
return null
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
return (
|
|
13
13
|
<div className='seam-content-header'>
|
|
14
|
-
|
|
14
|
+
<BackIcon onClick={onBack} />
|
|
15
15
|
<span className='seam-title'>{title}</span>
|
|
16
16
|
</div>
|
|
17
17
|
)
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
interface DeviceTableView {
|
|
2
|
-
name: 'device_table';
|
|
3
|
-
}
|
|
4
|
-
interface DeviceDetailView {
|
|
5
|
-
name: 'device_detail';
|
|
6
|
-
deviceId: string;
|
|
7
|
-
}
|
|
8
|
-
interface AccessCodeTableView {
|
|
9
|
-
name: 'access_code_table';
|
|
10
|
-
deviceId: string;
|
|
11
|
-
}
|
|
12
|
-
interface AccessCodeDetailView {
|
|
13
|
-
name: 'access_code_detail';
|
|
14
|
-
accessCodeId: string;
|
|
15
|
-
}
|
|
16
|
-
export type View = DeviceTableView | DeviceDetailView | AccessCodeTableView | AccessCodeDetailView;
|
|
17
|
-
export interface NavigationStackProps {
|
|
18
|
-
children: JSX.Element;
|
|
19
|
-
}
|
|
20
|
-
interface NavigationContextProps {
|
|
21
|
-
views: View[];
|
|
22
|
-
show: (view: View) => void;
|
|
23
|
-
goBack?: () => void;
|
|
24
|
-
}
|
|
25
|
-
export default function NavigationProvider({ children }: NavigationStackProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
-
export declare function useNavigation(): NavigationContextProps;
|
|
27
|
-
export {};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import React, { useState } from 'react';
|
|
3
|
-
const NavigationContext = React.createContext(undefined);
|
|
4
|
-
export default function NavigationProvider({ children }) {
|
|
5
|
-
const [views, setViews] = useState([]);
|
|
6
|
-
const pushView = (view) => {
|
|
7
|
-
setViews((current) => [view, ...current]);
|
|
8
|
-
};
|
|
9
|
-
const popView = () => {
|
|
10
|
-
setViews((current) => {
|
|
11
|
-
if (current.length === 0) {
|
|
12
|
-
return current;
|
|
13
|
-
}
|
|
14
|
-
const [_showing, ...others] = current;
|
|
15
|
-
return others;
|
|
16
|
-
});
|
|
17
|
-
};
|
|
18
|
-
const hasViews = views.length > 0;
|
|
19
|
-
return (_jsx(NavigationContext.Provider, { value: {
|
|
20
|
-
views,
|
|
21
|
-
show: pushView,
|
|
22
|
-
goBack: hasViews ? popView : undefined,
|
|
23
|
-
}, children: children }));
|
|
24
|
-
}
|
|
25
|
-
export function useNavigation() {
|
|
26
|
-
const context = React.useContext(NavigationContext);
|
|
27
|
-
if (context === undefined) {
|
|
28
|
-
return {
|
|
29
|
-
show: () => { },
|
|
30
|
-
goBack: undefined,
|
|
31
|
-
views: [],
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
return context;
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=NavigationProvider.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NavigationProvider.js","sourceRoot":"","sources":["../src/lib/NavigationProvider.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAqCvC,MAAM,iBAAiB,GAAG,KAAK,CAAC,aAAa,CAE3C,SAAS,CAAC,CAAA;AAEZ,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EAAE,QAAQ,EAAwB;IAC3E,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAS,EAAE,CAAC,CAAA;IAE9C,MAAM,QAAQ,GAAG,CAAC,IAAU,EAAE,EAAE;QAC9B,QAAQ,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,OAAO,CAAC,CAAC,CAAA;IAC3C,CAAC,CAAA;IAED,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,QAAQ,CAAC,CAAC,OAAO,EAAE,EAAE;YACnB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;gBACxB,OAAO,OAAO,CAAA;aACf;YAED,MAAM,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,GAAG,OAAO,CAAA;YACrC,OAAO,MAAM,CAAA;QACf,CAAC,CAAC,CAAA;IACJ,CAAC,CAAA;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;IAEjC,OAAO,CACL,KAAC,iBAAiB,CAAC,QAAQ,IACzB,KAAK,EAAE;YACL,KAAK;YACL,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;SACvC,YAEA,QAAQ,GACkB,CAC9B,CAAA;AACH,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAA;IACnD,IAAI,OAAO,KAAK,SAAS,EAAE;QACzB,OAAO;YACL,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;YACd,MAAM,EAAE,SAAS;YACjB,KAAK,EAAE,EAAE;SACV,CAAA;KACF;IAED,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
package/lib/NavigationView.d.ts
DELETED
package/lib/NavigationView.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { AccessCodeTable, DeviceDetails, DeviceTable } from '../lib/index.js';
|
|
3
|
-
import { useNavigation } from '../lib/NavigationProvider.js';
|
|
4
|
-
import AccessCodeDetails from '../lib/ui/AccessCodeDetails/AccessCodeDetails.js';
|
|
5
|
-
export function NavigationView({ children: rootView }) {
|
|
6
|
-
const { views } = useNavigation();
|
|
7
|
-
const firstView = views[0];
|
|
8
|
-
if (firstView != null) {
|
|
9
|
-
return _jsx(Subview, { view: firstView });
|
|
10
|
-
}
|
|
11
|
-
return rootView;
|
|
12
|
-
}
|
|
13
|
-
function Subview({ view }) {
|
|
14
|
-
switch (view.name) {
|
|
15
|
-
case 'device_detail':
|
|
16
|
-
return _jsx(DeviceDetails, { deviceId: view.deviceId });
|
|
17
|
-
case 'access_code_detail':
|
|
18
|
-
return _jsx(AccessCodeDetails, { accessCodeId: view.accessCodeId });
|
|
19
|
-
case 'device_table':
|
|
20
|
-
return _jsx(DeviceTable, {});
|
|
21
|
-
case 'access_code_table':
|
|
22
|
-
return _jsx(AccessCodeTable, { deviceId: view.deviceId });
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
//# sourceMappingURL=NavigationView.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NavigationView.js","sourceRoot":"","sources":["../src/lib/NavigationView.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE1E,OAAO,EAAE,aAAa,EAAa,MAAM,2BAA2B,CAAA;AACpE,OAAO,iBAAiB,MAAM,+CAA+C,CAAA;AAM7E,MAAM,UAAU,cAAc,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAuB;IACxE,MAAM,EAAE,KAAK,EAAE,GAAG,aAAa,EAAE,CAAA;IAEjC,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IAC1B,IAAI,SAAS,IAAI,IAAI,EAAE;QACrB,OAAO,KAAC,OAAO,IAAC,IAAI,EAAE,SAAS,GAAI,CAAA;KACpC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,SAAS,OAAO,CAAC,EAAE,IAAI,EAAkB;IACvC,QAAQ,IAAI,CAAC,IAAI,EAAE;QACjB,KAAK,eAAe;YAClB,OAAO,KAAC,aAAa,IAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,GAAI,CAAA;QACnD,KAAK,oBAAoB;YACvB,OAAO,KAAC,iBAAiB,IAAC,YAAY,EAAE,IAAI,CAAC,YAAY,GAAI,CAAA;QAC/D,KAAK,cAAc;YACjB,OAAO,KAAC,WAAW,KAAG,CAAA;QACxB,KAAK,mBAAmB;YACtB,OAAO,KAAC,eAAe,IAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,GAAI,CAAA;KACtD;AACH,CAAC"}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react'
|
|
2
|
-
|
|
3
|
-
interface DeviceTableView {
|
|
4
|
-
name: 'device_table'
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
interface DeviceDetailView {
|
|
8
|
-
name: 'device_detail'
|
|
9
|
-
deviceId: string
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
interface AccessCodeTableView {
|
|
13
|
-
name: 'access_code_table'
|
|
14
|
-
deviceId: string
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface AccessCodeDetailView {
|
|
18
|
-
name: 'access_code_detail'
|
|
19
|
-
accessCodeId: string
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type View =
|
|
23
|
-
| DeviceTableView
|
|
24
|
-
| DeviceDetailView
|
|
25
|
-
| AccessCodeTableView
|
|
26
|
-
| AccessCodeDetailView
|
|
27
|
-
|
|
28
|
-
export interface NavigationStackProps {
|
|
29
|
-
children: JSX.Element
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
interface NavigationContextProps {
|
|
33
|
-
views: View[]
|
|
34
|
-
show: (view: View) => void
|
|
35
|
-
goBack?: () => void
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const NavigationContext = React.createContext<
|
|
39
|
-
NavigationContextProps | undefined
|
|
40
|
-
>(undefined)
|
|
41
|
-
|
|
42
|
-
export default function NavigationProvider({ children }: NavigationStackProps) {
|
|
43
|
-
const [views, setViews] = useState<View[]>([])
|
|
44
|
-
|
|
45
|
-
const pushView = (view: View) => {
|
|
46
|
-
setViews((current) => [view, ...current])
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const popView = () => {
|
|
50
|
-
setViews((current) => {
|
|
51
|
-
if (current.length === 0) {
|
|
52
|
-
return current
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const [_showing, ...others] = current
|
|
56
|
-
return others
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const hasViews = views.length > 0
|
|
61
|
-
|
|
62
|
-
return (
|
|
63
|
-
<NavigationContext.Provider
|
|
64
|
-
value={{
|
|
65
|
-
views,
|
|
66
|
-
show: pushView,
|
|
67
|
-
goBack: hasViews ? popView : undefined,
|
|
68
|
-
}}
|
|
69
|
-
>
|
|
70
|
-
{children}
|
|
71
|
-
</NavigationContext.Provider>
|
|
72
|
-
)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function useNavigation(): NavigationContextProps {
|
|
76
|
-
const context = React.useContext(NavigationContext)
|
|
77
|
-
if (context === undefined) {
|
|
78
|
-
return {
|
|
79
|
-
show: () => {},
|
|
80
|
-
goBack: undefined,
|
|
81
|
-
views: [],
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return context
|
|
86
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { AccessCodeTable, DeviceDetails, DeviceTable } from 'lib/index.js'
|
|
2
|
-
|
|
3
|
-
import { useNavigation, type View } from 'lib/NavigationProvider.js'
|
|
4
|
-
import AccessCodeDetails from 'lib/ui/AccessCodeDetails/AccessCodeDetails.js'
|
|
5
|
-
|
|
6
|
-
interface NavigationViewProps {
|
|
7
|
-
children: JSX.Element
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function NavigationView({ children: rootView }: NavigationViewProps) {
|
|
11
|
-
const { views } = useNavigation()
|
|
12
|
-
|
|
13
|
-
const firstView = views[0]
|
|
14
|
-
if (firstView != null) {
|
|
15
|
-
return <Subview view={firstView} />
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return rootView
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function Subview({ view }: { view: View }) {
|
|
22
|
-
switch (view.name) {
|
|
23
|
-
case 'device_detail':
|
|
24
|
-
return <DeviceDetails deviceId={view.deviceId} />
|
|
25
|
-
case 'access_code_detail':
|
|
26
|
-
return <AccessCodeDetails accessCodeId={view.accessCodeId} />
|
|
27
|
-
case 'device_table':
|
|
28
|
-
return <DeviceTable />
|
|
29
|
-
case 'access_code_table':
|
|
30
|
-
return <AccessCodeTable deviceId={view.deviceId} />
|
|
31
|
-
}
|
|
32
|
-
}
|