"use client"; import { useCallback } from "react"; import { Badge, Center, Group, Stack, Text, Tooltip, UnstyledButton } from "@mantine/core"; import { IconBinaryTree } from "@tabler/icons-react"; import { clientApi } from "@homarr/api/client"; import { useIntegrationsWithInteractAccess } from "@homarr/auth/client"; import { useRegisterSpotlightContextActions } from "@homarr/spotlight"; import { useCurrentLocale, useI18n } from "@homarr/translation/client"; import type { WidgetComponentProps } from "../../definition"; export default function SmartHomeEntityStateWidget({ options, integrationIds, isEditMode, width, height, displayMode, }: WidgetComponentProps<"smartHome-entityState">) { const t = useI18n(); const locale = useCurrentLocale(); // It will always have at least one integration as otherwise the NoIntegrationSelectedError would be thrown in item-content.tsx // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const integrationId = integrationIds[0]!; const input = { entityId: options.entityId, integrationId, }; const { data: entity } = clientApi.widget.smartHome.entityDetails.useQuery(input); const canInteract = useIntegrationsWithInteractAccess().some(({ id }) => id === integrationId); const utils = clientApi.useUtils(); const { mutate, isPending, error } = clientApi.widget.smartHome.switchEntity.useMutation({ onSettled: () => void utils.widget.smartHome.entityDetails.invalidate(input), }); const apiUnit = entity?.attributes.unit_of_measurement; const unit = options.entityUnit || (typeof apiUnit === "string" ? apiUnit : ""); const attribute = unit.length > 0 ? ` ${unit}` : ""; const isActionable = options.clickable && canInteract && !isPending; const handleClick = useCallback(() => { if (isEditMode) { return; } if (!isActionable) { return; } mutate({ entityId: options.entityId, integrationId, }); }, [integrationId, isActionable, isEditMode, mutate, options.entityId]); useRegisterSpotlightContextActions( `smartHome-entityState-${options.entityId}`, [ { id: options.entityId, name: options.displayName, icon: IconBinaryTree, interaction() { return { type: "javaScript", onSelect() { handleClick(); }, }; }, disabled: !isActionable, }, ], [handleClick, isActionable, options.displayName, options.entityId], ); const isTiny = width < 128 || height < 96; const advancedAttributes = [ { key: "unit" as const, value: entity?.attributes.unit_of_measurement }, { key: "deviceClass" as const, value: entity?.attributes.device_class }, { key: "icon" as const, value: entity?.attributes.icon }, ].filter(({ value }) => typeof value === "string" && value.length > 0); return (
{displayMode === "advanced" && typeof entity?.attributes.friendly_name === "string" ? entity.attributes.friendly_name : options.displayName} {entity?.state ?? "—"} {attribute} {displayMode === "advanced" && entity && ( <> {advancedAttributes.map(({ key, value }) => ( {t(`widget.smartHome-entityState.advanced.attribute.${key}`)}: {String(value)} ))} {t("widget.smartHome-entityState.advanced.entityId", { id: entity.entity_id })} {t("widget.smartHome-entityState.advanced.lastUpdated", { date: new Date(entity.last_updated).toLocaleString(locale), })} )} {error && ( {t("widget.smartHome-entityState.error.toggleFailed")} )}
); }