homeos/resources/views/livewire/devices/show.blade.php

152 lines
10 KiB
PHP

<div>
<x-topbar :title="$device->name" :subtitle="$device->model">
<x-slot:actions>
<a href="{{ route('devices.index') }}" wire:navigate
class="inline-flex items-center gap-1.5 rounded-lg border border-line-soft bg-raised px-2.5 py-1.5 text-[12px] font-semibold text-ink-2 hover:text-ink transition-colors">
<x-icon name="chevron" :size="14" class="rotate-180" />
<span class="hidden sm:inline">{{ __('nav.devices') }}</span>
</a>
</x-slot:actions>
</x-topbar>
<div class="px-5 lg:px-[26px] py-6 flex flex-col gap-5 max-w-[1560px] mx-auto w-full">
@if ($flash)
<div @class([
'flex items-center gap-3 rounded-card border border-line-soft px-4 py-3',
'bg-online/10' => $flashOk,
'bg-offline/10' => ! $flashOk,
])>
<x-icon :name="$flashOk ? 'check' : 'alert'" :size="17" @class(['shrink-0', 'text-online' => $flashOk, 'text-offline' => ! $flashOk]) />
<span class="text-[13px] text-ink">{{ $flash }}</span>
<button type="button" wire:click="$set('flash', null)" class="ml-auto text-ink-3 hover:text-ink">
<x-icon name="close" :size="16" />
</button>
</div>
@endif
@if ($mqttCredential)
<div class="rounded-card border border-accent/30 bg-accent/10 p-4 flex flex-col gap-2">
<div class="flex items-center gap-2 text-[13px] font-bold text-ink"><x-icon name="lock" :size="16" class="text-accent" /> {{ __('devices.mqtt_credential_title') }}</div>
<p class="text-[12px] text-ink-2 max-w-2xl">{{ __('devices.mqtt_credential_hint') }}</p>
<dl class="grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-2 mt-1">
<x-detail :label="__('devices.mqtt_username')" mono>{{ $mqttCredential['username'] }}</x-detail>
<x-detail :label="__('devices.mqtt_password')" mono>{{ $mqttCredential['password'] }}</x-detail>
<x-detail label="Port" mono>{{ $mqttCredential['port'] }}</x-detail>
</dl>
</div>
@endif
<div class="grid grid-cols-1 lg:grid-cols-[1fr_340px] gap-5 items-start">
{{-- main --}}
<div class="flex flex-col gap-5">
{{-- identity + name edit --}}
<x-panel :title="__('devices.device')">
<div class="flex flex-col gap-4">
<div class="flex items-center gap-3">
<x-status-dot :state="$device->isOnline() ? 'online' : 'offline'" :pulse="$device->isOnline()" />
<x-status-pill :state="$device->isOnline() ? 'online' : 'offline'">
{{ $device->isOnline() ? __('devices.online') : __('devices.offline') }}
</x-status-pill>
@if ($device->status !== 'active')
<x-status-pill state="neutral">{{ __('devices.status_'.$device->status) }}</x-status-pill>
@endif
</div>
<div class="flex flex-col gap-1.5">
<label for="name" class="text-[12px] font-semibold text-ink-2">{{ __('devices.name') }}</label>
<div class="flex gap-2">
<input wire:model="name" id="name" type="text"
class="flex-1 rounded-lg bg-raised border border-line px-3 py-2.5 text-sm text-ink outline-none transition-colors focus:border-accent focus:ring-1 focus:ring-accent">
<button type="button" wire:click="saveName"
class="rounded-lg bg-accent px-4 py-2.5 text-sm font-bold text-base transition-[filter] hover:brightness-110">
{{ __('devices.save') }}
</button>
</div>
@error('name') <p class="text-[12px] text-offline">{{ $message }}</p> @enderror
</div>
<dl class="grid grid-cols-2 sm:grid-cols-3 gap-x-4 gap-y-3 pt-1">
<x-detail :label="__('devices.vendor')">{{ $device->vendor ?? '—' }}</x-detail>
<x-detail :label="__('devices.model')">{{ $device->model ?? '—' }}</x-detail>
<x-detail :label="__('devices.protocol')" mono>{{ $device->protocol ?? '—' }}</x-detail>
<x-detail :label="__('devices.room')">{{ $device->room?->name ?? '—' }}</x-detail>
<x-detail :label="__('devices.last_seen')" mono>{{ $device->last_seen_at?->diffForHumans() ?? '—' }}</x-detail>
<x-detail :label="__('devices.uuid')" mono>{{ \Illuminate\Support\Str::limit($device->uuid, 13, '…') }}</x-detail>
</dl>
</div>
</x-panel>
{{-- capabilities / entities --}}
<x-panel :title="__('devices.capabilities')">
@if ($device->entities->isEmpty())
<p class="text-[13px] text-ink-3">{{ __('devices.no_capabilities') }}</p>
@else
<div class="flex flex-col divide-y divide-line-soft -my-1">
@foreach ($device->entities as $entity)
<div class="flex items-center gap-3 py-3 first:pt-1 last:pb-1">
<span class="text-[13px] font-semibold text-ink">{{ $entity->name ?? $entity->key }}</span>
<span class="text-[11px] font-mono text-ink-3">{{ $entity->type }}</span>
<div class="ml-auto flex items-center gap-3">
<x-entity-state :entity="$entity" />
@if (in_array($entity->type, ['switch', 'light']))
<x-toggle :on="(bool) data_get($entity->state?->state, 'on', false)"
wire:click="toggleEntity({{ $entity->id }})" :label="$entity->name ?? $entity->key" />
@endif
</div>
</div>
@endforeach
</div>
@endif
</x-panel>
</div>
{{-- rail: actions + settings --}}
<div class="flex flex-col gap-5">
<x-panel :title="__('devices.actions')">
<div class="flex flex-col gap-2">
<button type="button"
wire:click="$dispatch('openModal', { component: 'modals.confirm', arguments: { title: @js(__('devices.restart_confirm_title')), body: @js(__('devices.restart_confirm_body', ['name' => $device->name])), confirmLabel: @js(__('devices.restart')), event: 'restartDevice', to: 'devices.show', danger: true } })"
class="flex items-center gap-2.5 rounded-lg border border-line-soft bg-raised px-3 py-2.5 text-[13px] font-semibold text-ink hover:border-line transition-colors">
<x-icon name="activity" :size="16" class="text-ink-2" /> {{ __('devices.restart') }}
</button>
<button type="button" wire:click="checkUpdate"
class="flex items-center gap-2.5 rounded-lg border border-line-soft bg-raised px-3 py-2.5 text-[13px] font-semibold text-ink hover:border-line transition-colors">
<x-icon name="wifi" :size="16" class="text-ink-2" /> {{ __('devices.check_update') }}
</button>
</div>
<p class="mt-3 text-[11.5px] text-ink-3">{{ __('devices.actions_demo_hint') }}</p>
</x-panel>
<x-panel :title="__('devices.settings')">
<div class="flex flex-col gap-4">
<div class="flex flex-col gap-1.5">
<label for="room" class="text-[12px] font-semibold text-ink-2">{{ __('devices.room') }}</label>
<div class="flex gap-2">
<select wire:model="roomId" id="room"
class="flex-1 rounded-lg bg-raised border border-line px-3 py-2.5 text-sm text-ink outline-none focus:border-accent focus:ring-1 focus:ring-accent">
<option value="">{{ __('devices.no_room') }}</option>
@foreach ($rooms as $room)
<option value="{{ $room->id }}">{{ $room->name }}</option>
@endforeach
</select>
<button type="button" wire:click="saveRoom"
class="rounded-lg border border-line px-3.5 py-2.5 text-[13px] font-semibold text-ink-2 hover:text-ink hover:bg-raised transition-colors">
{{ __('devices.save') }}
</button>
</div>
</div>
<div class="flex items-center gap-3 border-t border-line-soft pt-3">
<div class="min-w-0">
<div class="text-[13px] font-semibold text-ink">{{ __('devices.active') }}</div>
<div class="text-[11.5px] text-ink-3">{{ __('devices.active_hint') }}</div>
</div>
<x-toggle :on="$device->status === 'active'" wire:click="toggleStatus" :label="__('devices.active')" class="ml-auto" />
</div>
</div>
</x-panel>
</div>
</div>
</div>
</div>