@seamapi/react 0.19.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/ui/AccessCodeDetails/AccessCodeDetails.js +3 -1
- package/lib/ui/AccessCodeDetails/AccessCodeDetails.js.map +1 -1
- package/lib/ui/AccessCodeTable/CodeDetails.js +3 -1
- package/lib/ui/AccessCodeTable/CodeDetails.js.map +1 -1
- package/lib/use-interval.d.ts +1 -0
- package/lib/use-interval.js +15 -0
- package/lib/use-interval.js.map +1 -0
- package/lib/use-is-date-in-past.d.ts +1 -0
- package/lib/use-is-date-in-past.js +20 -0
- package/lib/use-is-date-in-past.js.map +1 -0
- package/package.json +1 -1
- package/src/lib/ui/AccessCodeDetails/AccessCodeDetails.tsx +6 -1
- package/src/lib/ui/AccessCodeTable/CodeDetails.tsx +6 -1
- package/src/lib/use-interval.ts +20 -0
- package/src/lib/use-is-date-in-past.ts +25 -0
|
@@ -4,6 +4,7 @@ import { useState } from 'react';
|
|
|
4
4
|
import { AccessCodeDevice } from '../../../lib/ui/AccessCodeDetails/AccessCodeDevice.js';
|
|
5
5
|
import { DeviceDetails } from '../../../lib/ui/DeviceDetails/DeviceDetails.js';
|
|
6
6
|
import { ContentHeader } from '../../../lib/ui/layout/ContentHeader.js';
|
|
7
|
+
import { useIsDateInPast } from '../../../lib/use-is-date-in-past.js';
|
|
7
8
|
export function AccessCodeDetails({ accessCode, onBack, }) {
|
|
8
9
|
const name = accessCode.name ?? t.fallbackName;
|
|
9
10
|
const [selectedDevice, selectDevice] = useState(null);
|
|
@@ -22,10 +23,11 @@ function ScheduleInfo({ accessCode }) {
|
|
|
22
23
|
}
|
|
23
24
|
function Duration(props) {
|
|
24
25
|
const { accessCode } = props;
|
|
26
|
+
const hasStarted = useIsDateInPast('starts_at' in accessCode ? accessCode?.starts_at : null) ??
|
|
27
|
+
false;
|
|
25
28
|
if (accessCode.type === 'ongoing') {
|
|
26
29
|
return (_jsxs("span", { children: [_jsx("span", { className: 'seam-label', children: "Active" }), " (ongoing)"] }));
|
|
27
30
|
}
|
|
28
|
-
const hasStarted = new Date(accessCode.starts_at).valueOf() < Date.now();
|
|
29
31
|
if (hasStarted) {
|
|
30
32
|
return (_jsxs("span", { children: [_jsx("span", { className: 'seam-label', children: "Active" }), " until", ' ', formatDurationDate(accessCode.ends_at), " at", ' ', formatTime(accessCode.ends_at)] }));
|
|
31
33
|
}
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"AccessCodeDetails.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeDetails/AccessCodeDetails.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { DateTime } from 'luxon';
|
|
3
3
|
import { DotDivider } from '../../../lib/ui/layout/DotDivider.js';
|
|
4
|
+
import { useIsDateInPast } from '../../../lib/use-is-date-in-past.js';
|
|
4
5
|
export function CodeDetails(props) {
|
|
5
6
|
const { accessCode } = props;
|
|
6
7
|
return (_jsxs("div", { className: 'seam-code-details', children: ["Unit 110", _jsx(DotDivider, {}), _jsx(Duration, { accessCode: accessCode }), _jsx(DotDivider, {}), t.code, ": ", accessCode.code] }));
|
|
7
8
|
}
|
|
8
9
|
function Duration(props) {
|
|
9
10
|
const { accessCode } = props;
|
|
11
|
+
const hasStarted = useIsDateInPast('starts_at' in accessCode ? accessCode?.starts_at : null) ??
|
|
12
|
+
false;
|
|
10
13
|
if (accessCode.type === 'ongoing') {
|
|
11
14
|
return (_jsxs("span", { children: [t.ends, ": ", t.never] }));
|
|
12
15
|
}
|
|
13
|
-
const hasStarted = new Date(accessCode.starts_at).valueOf() < Date.now();
|
|
14
16
|
if (hasStarted) {
|
|
15
17
|
return (_jsxs("span", { children: [t.ends, ": ", formatDate(accessCode.ends_at), ' '] }));
|
|
16
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeDetails.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeTable/CodeDetails.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAGhC,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"CodeDetails.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeTable/CodeDetails.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAGhC,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAE5D,MAAM,UAAU,WAAW,CAAC,KAAiC;IAC3D,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAA;IAE5B,OAAO,CACL,eAAK,SAAS,EAAC,mBAAmB,yBAEhC,KAAC,UAAU,KAAG,EACd,KAAC,QAAQ,IAAC,UAAU,EAAE,UAAU,GAAI,EACpC,KAAC,UAAU,KAAG,EACb,CAAC,CAAC,IAAI,QAAI,UAAU,CAAC,IAAI,IACtB,CACP,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAiC;IACjD,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAA;IAE5B,MAAM,UAAU,GACd,eAAe,CAAC,WAAW,IAAI,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;QACzE,KAAK,CAAA;IAEP,IAAI,UAAU,CAAC,IAAI,KAAK,SAAS,EAAE;QACjC,OAAO,CACL,2BACG,CAAC,CAAC,IAAI,QAAI,CAAC,CAAC,KAAK,IACb,CACR,CAAA;KACF;IAED,IAAI,UAAU,EAAE;QACd,OAAO,CACL,2BACG,CAAC,CAAC,IAAI,QAAI,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,IACzC,CACR,CAAA;KACF;IAED,OAAO,CACL,2BACG,CAAC,CAAC,MAAM,QAAI,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,IACxC,CACR,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC;QAC3C,KAAK,EAAE,MAAM;QACb,GAAG,EAAE,SAAS;KACf,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,GAAG;IACR,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;CACf,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useInterval(callback: () => void, delay?: number): void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Duration } from 'luxon';
|
|
2
|
+
import { useCallback, useEffect } from 'react';
|
|
3
|
+
const defaultDelay = Duration.fromObject({ minutes: 1 }).as('milliseconds');
|
|
4
|
+
export function useInterval(callback, delay = defaultDelay) {
|
|
5
|
+
const update = useCallback(() => {
|
|
6
|
+
callback();
|
|
7
|
+
}, [callback]);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const timer = globalThis.setInterval(update, delay);
|
|
10
|
+
return () => {
|
|
11
|
+
globalThis.clearInterval(timer);
|
|
12
|
+
};
|
|
13
|
+
}, [update, delay]);
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=use-interval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-interval.js","sourceRoot":"","sources":["../src/lib/use-interval.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAE9C,MAAM,YAAY,GAAG,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,CAAA;AAE3E,MAAM,UAAU,WAAW,CACzB,QAAoB,EACpB,QAAgB,YAAY;IAE5B,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE;QAC9B,QAAQ,EAAE,CAAA;IACZ,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,KAAK,GAAG,UAAU,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QACnD,OAAO,GAAG,EAAE;YACV,UAAU,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;QACjC,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAA;AACrB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useIsDateInPast(date: string | null | undefined): boolean | null;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DateTime } from 'luxon';
|
|
2
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
3
|
+
import { useInterval } from './use-interval.js';
|
|
4
|
+
export function useIsDateInPast(date) {
|
|
5
|
+
const [isDateInPast, setIsDateInPast] = useState(null);
|
|
6
|
+
const update = useCallback(() => {
|
|
7
|
+
if (date == null)
|
|
8
|
+
return;
|
|
9
|
+
setIsDateInPast(isInPast(DateTime.fromISO(date)));
|
|
10
|
+
}, [date]);
|
|
11
|
+
useEffect(update, [update]);
|
|
12
|
+
useInterval(update);
|
|
13
|
+
return isDateInPast;
|
|
14
|
+
}
|
|
15
|
+
const isInPast = (dt) => {
|
|
16
|
+
if (!dt.isValid)
|
|
17
|
+
return null;
|
|
18
|
+
return dt.diffNow().milliseconds < 0;
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=use-is-date-in-past.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-is-date-in-past.js","sourceRoot":"","sources":["../src/lib/use-is-date-in-past.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,MAAM,UAAU,eAAe,CAC7B,IAA+B;IAE/B,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAiB,IAAI,CAAC,CAAA;IAEtE,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE;QAC9B,IAAI,IAAI,IAAI,IAAI;YAAE,OAAM;QACxB,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnD,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;IAEV,SAAS,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAC3B,WAAW,CAAC,MAAM,CAAC,CAAA;IAEnB,OAAO,YAAY,CAAA;AACrB,CAAC;AAED,MAAM,QAAQ,GAAG,CAAC,EAAY,EAAkB,EAAE;IAChD,IAAI,CAAC,EAAE,CAAC,OAAO;QAAE,OAAO,IAAI,CAAA;IAC5B,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,YAAY,GAAG,CAAC,CAAA;AACtC,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -5,6 +5,7 @@ import type { AccessCode, CommonDeviceProperties, Device } from 'seamapi'
|
|
|
5
5
|
import { AccessCodeDevice } from 'lib/ui/AccessCodeDetails/AccessCodeDevice.js'
|
|
6
6
|
import { DeviceDetails } from 'lib/ui/DeviceDetails/DeviceDetails.js'
|
|
7
7
|
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
8
|
+
import { useIsDateInPast } from 'lib/use-is-date-in-past.js'
|
|
8
9
|
|
|
9
10
|
export interface AccessCodeDetailsProps {
|
|
10
11
|
accessCode: AccessCode
|
|
@@ -92,6 +93,11 @@ function ScheduleInfo({ accessCode }: { accessCode: AccessCode }): JSX.Element {
|
|
|
92
93
|
|
|
93
94
|
function Duration(props: { accessCode: AccessCode }): JSX.Element {
|
|
94
95
|
const { accessCode } = props
|
|
96
|
+
|
|
97
|
+
const hasStarted =
|
|
98
|
+
useIsDateInPast('starts_at' in accessCode ? accessCode?.starts_at : null) ??
|
|
99
|
+
false
|
|
100
|
+
|
|
95
101
|
if (accessCode.type === 'ongoing') {
|
|
96
102
|
return (
|
|
97
103
|
<span>
|
|
@@ -100,7 +106,6 @@ function Duration(props: { accessCode: AccessCode }): JSX.Element {
|
|
|
100
106
|
)
|
|
101
107
|
}
|
|
102
108
|
|
|
103
|
-
const hasStarted = new Date(accessCode.starts_at).valueOf() < Date.now()
|
|
104
109
|
if (hasStarted) {
|
|
105
110
|
return (
|
|
106
111
|
<span>
|
|
@@ -2,6 +2,7 @@ import { DateTime } from 'luxon'
|
|
|
2
2
|
import type { AccessCode } from 'seamapi'
|
|
3
3
|
|
|
4
4
|
import { DotDivider } from 'lib/ui/layout/DotDivider.js'
|
|
5
|
+
import { useIsDateInPast } from 'lib/use-is-date-in-past.js'
|
|
5
6
|
|
|
6
7
|
export function CodeDetails(props: { accessCode: AccessCode }): JSX.Element {
|
|
7
8
|
const { accessCode } = props
|
|
@@ -19,6 +20,11 @@ export function CodeDetails(props: { accessCode: AccessCode }): JSX.Element {
|
|
|
19
20
|
|
|
20
21
|
function Duration(props: { accessCode: AccessCode }): JSX.Element {
|
|
21
22
|
const { accessCode } = props
|
|
23
|
+
|
|
24
|
+
const hasStarted =
|
|
25
|
+
useIsDateInPast('starts_at' in accessCode ? accessCode?.starts_at : null) ??
|
|
26
|
+
false
|
|
27
|
+
|
|
22
28
|
if (accessCode.type === 'ongoing') {
|
|
23
29
|
return (
|
|
24
30
|
<span>
|
|
@@ -27,7 +33,6 @@ function Duration(props: { accessCode: AccessCode }): JSX.Element {
|
|
|
27
33
|
)
|
|
28
34
|
}
|
|
29
35
|
|
|
30
|
-
const hasStarted = new Date(accessCode.starts_at).valueOf() < Date.now()
|
|
31
36
|
if (hasStarted) {
|
|
32
37
|
return (
|
|
33
38
|
<span>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Duration } from 'luxon'
|
|
2
|
+
import { useCallback, useEffect } from 'react'
|
|
3
|
+
|
|
4
|
+
const defaultDelay = Duration.fromObject({ minutes: 1 }).as('milliseconds')
|
|
5
|
+
|
|
6
|
+
export function useInterval(
|
|
7
|
+
callback: () => void,
|
|
8
|
+
delay: number = defaultDelay
|
|
9
|
+
) {
|
|
10
|
+
const update = useCallback(() => {
|
|
11
|
+
callback()
|
|
12
|
+
}, [callback])
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const timer = globalThis.setInterval(update, delay)
|
|
16
|
+
return () => {
|
|
17
|
+
globalThis.clearInterval(timer)
|
|
18
|
+
}
|
|
19
|
+
}, [update, delay])
|
|
20
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { DateTime } from 'luxon'
|
|
2
|
+
import { useCallback, useEffect, useState } from 'react'
|
|
3
|
+
|
|
4
|
+
import { useInterval } from './use-interval.js'
|
|
5
|
+
|
|
6
|
+
export function useIsDateInPast(
|
|
7
|
+
date: string | null | undefined
|
|
8
|
+
): boolean | null {
|
|
9
|
+
const [isDateInPast, setIsDateInPast] = useState<boolean | null>(null)
|
|
10
|
+
|
|
11
|
+
const update = useCallback(() => {
|
|
12
|
+
if (date == null) return
|
|
13
|
+
setIsDateInPast(isInPast(DateTime.fromISO(date)))
|
|
14
|
+
}, [date])
|
|
15
|
+
|
|
16
|
+
useEffect(update, [update])
|
|
17
|
+
useInterval(update)
|
|
18
|
+
|
|
19
|
+
return isDateInPast
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const isInPast = (dt: DateTime): boolean | null => {
|
|
23
|
+
if (!dt.isValid) return null
|
|
24
|
+
return dt.diffNow().milliseconds < 0
|
|
25
|
+
}
|