import classNames from 'classnames' import { useState } from 'react' import { ChevronRightIcon } from 'lib/icons/ChevronRight.js' import { useAccessCodes } from 'lib/seam/access-codes/use-access-codes.js' import { NestedAccessCodeTable } from 'lib/seam/components/AccessCodeTable/AccessCodeTable.js' import type { NestedSpecificDeviceDetailsProps } from 'lib/seam/components/DeviceDetails/DeviceDetails.js' import { DeviceInfo } from 'lib/seam/components/DeviceDetails/DeviceInfo.js' import { DeviceModel } from 'lib/seam/components/DeviceDetails/DeviceModel.js' import { LockDeviceLockButtons } from 'lib/seam/components/DeviceDetails/LockDeviceLockButtons.js' import { deviceErrorFilter, deviceWarningFilter } from 'lib/seam/filters.js' import type { LockDevice } from 'lib/seam/locks/lock-device.js' import { Alerts } from 'lib/ui/Alert/Alerts.js' import { BatteryStatusIndicator } from 'lib/ui/device/BatteryStatusIndicator.js' import { DeviceImage } from 'lib/ui/device/DeviceImage.js' import { EditableDeviceName } from 'lib/ui/device/EditableDeviceName.js' import { OnlineStatus } from 'lib/ui/device/OnlineStatus.js' import { ContentHeader } from 'lib/ui/layout/ContentHeader.js' import { Snackbar, type SnackbarVariant } from 'lib/ui/Snackbar/Snackbar.js' import { useToggle } from 'lib/ui/use-toggle.js' interface LockDeviceDetailsProps extends NestedSpecificDeviceDetailsProps { device: LockDevice onEditName?: (newName: string) => void | Promise } export function LockDeviceDetails({ device, errorFilter, warningFilter, disableLockUnlock, disableCreateAccessCode, disableEditAccessCode, disableDeleteAccessCode, disableResourceIds, disableConnectedAccountInformation, onBack, className, onEditName, }: LockDeviceDetailsProps): JSX.Element | null { const [accessCodesOpen, toggleAccessCodesOpen] = useToggle() const { accessCodes } = useAccessCodes({ device_id: device.device_id, }) const [snackbarVisible, setSnackbarVisible] = useState(false) const [snackbarVariant, setSnackbarVariant] = useState('success') const accessCodeCount = accessCodes?.length ?? 0 if (accessCodesOpen) { return ( ) } const alerts = [ ...device.errors .filter(deviceErrorFilter) .filter(errorFilter) .map((error) => ({ variant: 'error' as const, message: error.message, })), ...device.warnings .filter(deviceWarningFilter) .filter(warningFilter) .map((warning) => ({ variant: 'warning' as const, message: warning.message, })), ] return ( <> { setSnackbarVisible(false) }} message={ snackbarVariant === 'success' ? t.successfullyUpdated : t.failedToUpdate } autoDismiss />
{t.device}
{t.status}:{' '} {device.properties.online && ( <> {t.power}:{' '} )}
{accessCodes != null ? accessCodeCount : '–'} {t.accessCodes} {accessCodes != null && }
) } function AccessCodeLength(props: { supportedCodeLengths: number[] }): JSX.Element | null { const { supportedCodeLengths } = props if (supportedCodeLengths.length === 0) { return null } const min = Math.min(...supportedCodeLengths) const max = Math.max(...supportedCodeLengths) const range = min === max ? max : `${min}–${max}` return (
{t.codeLength} {range} {t.digits}
) } const t = { device: 'Device', accessCodes: 'access codes', codeLength: 'Code length', digits: 'digits', status: 'Status', power: 'Power', successfullyUpdated: 'Lock status has been successfully updated', failedToUpdate: 'Failed to update lock status', }