'use client' import { useState, useEffect } from 'react' import { Fan, Lightbulb, Tv, Snowflake, Power } from 'lucide-react' interface DeviceCardProps { id: string name: string icon: string entityId?: string domain?: string initialState: boolean isMock?: boolean extraInfo?: string } type DeviceKind = 'air_purifier' | 'light' | 'tv' | 'ac' | 'default' function getDeviceKind(id: string): DeviceKind { if (id.includes('air_purifier')) return 'air_purifier' if (id.includes('light')) return 'light' if (id.includes('tv')) return 'tv' if (id.includes('ac')) return 'ac' return 'default' } // Каждый тип устройства — свой data-token (а не хардкод hex) const DEVICE_ACCENT: Record = { air_purifier: 'var(--data-violet)', light: 'var(--data-warm)', tv: 'var(--data-info)', ac: 'var(--data-cool)', default: 'var(--accent)', } function getDeviceIcon(kind: DeviceKind, isOn: boolean) { const color = isOn ? DEVICE_ACCENT[kind] : 'var(--text-tertiary)' const size = 26 const strokeWidth = 1.9 switch (kind) { case 'air_purifier': return case 'light': return case 'tv': return case 'ac': return default: return } } export default function DeviceCard({ id, name, icon, entityId, domain, initialState, isMock = false, extraInfo, }: DeviceCardProps) { const kind = getDeviceKind(id) const accent = DEVICE_ACCENT[kind] const [isOn, setIsOn] = useState(initialState) const [synced, setSynced] = useState(false) const [loading, setLoading] = useState(false) useEffect(() => { if (!synced && !isMock) { setIsOn(initialState) setSynced(true) } }, [initialState, isMock, synced]) const toggle = async () => { const next = !isOn setIsOn(next) if (!isMock && entityId && domain) { setLoading(true) try { await fetch('/api/ha', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ domain, service: next ? 'turn_on' : 'turn_off', entity_id: entityId, }), }) } catch { setIsOn(!next) } finally { setLoading(false) } } } const activeBg = `color-mix(in srgb, ${accent} 14%, var(--surface-1))` const activeBorder = `color-mix(in srgb, ${accent} 35%, var(--border-subtle))` const activeGlow = `color-mix(in srgb, ${accent} 22%, transparent)` return (
{/* Subtle accent glow when on */} {isOn && (
)} {/* Top: icon + toggle */}
{getDeviceIcon(kind, isOn)}
{/* Toggle switch — 60x36, touch-friendly */}
{/* Bottom: name + status */}
{name}
{isOn ? 'Включён' : 'Выключен'} {extraInfo && isOn ? ` · ${extraInfo}` : ''}
{isMock && (
demo
)}
) }