import { useCallback } from 'react'; import * as FaIcons from 'react-icons/fa'; import { FaCube, FaLock } from 'react-icons/fa'; import { useSessionActions, useSessionSelector } from '../../context/SessionContext'; import CardFrame from '../CardFrame'; // Each control keeps its own JSX file; this panel only selects its renderer. import ReadOnlyControl from './controls/ReadOnlyControl'; import ToggleControl from './controls/ToggleControl'; import NumberControl from './controls/NumberControl'; import TextControl from './controls/TextControl'; import SelectControl from './controls/SelectControl'; import ButtonControl from './controls/ButtonControl'; const controls = { readOnly: ReadOnlyControl, toggle: ToggleControl, number: NumberControl, text: TextControl, select: SelectControl, button: ButtonControl }; function ActivityTile({ entity, connected, allowed, admin }) { const { homeAssistantActivityAct } = useSessionActions(); const onChange = useCallback((value) => homeAssistantActivityAct(entity.id, value), [homeAssistantActivityAct, entity.id]); // Resolve precisely the same Font Awesome names accepted by social links. // Unknown names remain usable with a neutral fallback rather than an error. const candidate = FaIcons[entity.icon?.trim()]; const Icon = typeof candidate === 'function' ? candidate : FaCube; // Translucent fills preserve text contrast; an amber border still identifies // locked tiles regardless of the admin's chosen color. const color = /^#[0-9a-f]{6}$/i.test(entity.color) ? entity.color : '#3b82f6'; // Ordinary users see only the value; admins retain the entity's actual input. const Control = entity.readOnly && !admin ? ReadOnlyControl : controls[entity.type] || ReadOnlyControl; const disabled = !connected || !entity.available || !allowed || ((entity.locked || entity.readOnly) && !admin); return
{socketConnected ? 'Home Assistant is offline.' : 'Server disconnected.'} Values may be out of date.
: null} {!allowed ?Controls are read-only with your current access.
: null}