clusev/resources/views/livewire/health/index.blade.php

86 lines
4.9 KiB
PHP

@php
$field = 'h-9 w-full rounded-md border border-line bg-inset px-3 text-sm text-ink placeholder:text-ink-4 focus:border-accent/40 focus:outline-none';
$label = 'mb-1 block font-mono text-[11px] uppercase tracking-wider text-ink-3';
@endphp
<div class="space-y-5" @if (! $ready) wire:init="scan" @endif>
{{-- Header --}}
<div class="flex flex-wrap items-end justify-between gap-3">
<div>
<p class="font-mono text-[11px] uppercase tracking-[0.2em] text-accent-text">{{ __('health.eyebrow') }}</p>
<h2 class="mt-0.5 font-display text-xl font-semibold text-ink sm:text-2xl">{{ __('health.title') }}</h2>
<p class="mt-1 text-sm text-ink-3">{{ __('health.subtitle') }}</p>
</div>
@if ($ready && $total > 0)
<x-status-pill :status="$up === $total ? 'online' : 'offline'">{{ __('health.up_of', ['up' => $up, 'total' => $total]) }}</x-status-pill>
@endif
</div>
{{-- Add check --}}
<x-panel :title="__('health.new_check')">
<form wire:submit="addCheck" class="grid gap-3 sm:grid-cols-[minmax(0,10rem)_7rem_minmax(0,1fr)_6rem_auto] sm:items-end">
<div>
<label class="{{ $label }}">{{ __('health.label_label') }}</label>
<input wire:model="label" type="text" maxlength="60" class="{{ $field }}" />
</div>
<div>
<label class="{{ $label }}">{{ __('health.type_label') }}</label>
<select wire:model.live="type" class="{{ $field }}">
<option value="http">{{ __('health.type_http') }}</option>
<option value="tcp">{{ __('health.type_tcp') }}</option>
</select>
</div>
<div>
<label class="{{ $label }}">{{ __('health.target_label') }}</label>
<input wire:model="target" type="text" maxlength="2048" class="{{ $field }} font-mono"
placeholder="{{ $type === 'tcp' ? __('health.target_tcp_placeholder') : __('health.target_http_placeholder') }}" />
@error('target') <p class="mt-1 font-mono text-[11px] text-offline">{{ $message }}</p> @enderror
</div>
<div @class(['invisible' => $type !== 'tcp'])>
<label class="{{ $label }}">{{ __('health.port_label') }}</label>
<input wire:model="port" type="number" min="1" max="65535" class="{{ $field }} font-mono" />
@error('port') <p class="mt-1 font-mono text-[11px] text-offline">{{ $message }}</p> @enderror
</div>
<x-btn variant="primary" size="field" type="submit">{{ __('health.add') }}</x-btn>
</form>
</x-panel>
{{-- Checks --}}
@if ($checks->isEmpty())
<x-panel>
<div class="flex flex-col items-center gap-2 py-8 text-center">
<span class="grid h-10 w-10 place-items-center rounded-md bg-raised text-ink-4">
<x-icon name="activity" class="h-5 w-5" />
</span>
<p class="font-display text-sm font-semibold text-ink">{{ __('health.no_checks_title') }}</p>
<p class="max-w-sm text-xs text-ink-3">{{ __('health.no_checks') }}</p>
</div>
</x-panel>
@else
<x-panel :padded="false">
<div class="divide-y divide-line">
@foreach ($checks as $check)
@php($r = $results[$check->uuid] ?? null)
<div wire:key="hc-{{ $check->uuid }}" class="flex flex-wrap items-center gap-3 px-4 py-3 sm:px-5">
<x-status-dot :status="$r ? ($r['ok'] ? 'online' : 'offline') : 'pending'" :ping="$r && $r['ok']" class="h-2.5 w-2.5" />
<div class="min-w-0 flex-1">
<p class="truncate text-sm text-ink">{{ $check->label ?: $check->target }}</p>
<p class="truncate font-mono text-[11px] text-ink-3">
<span class="uppercase">{{ $check->type }}</span> · {{ $check->target }}@if ($check->type === 'tcp'):{{ $check->port }}@endif
@if ($r) · {{ $r['detail'] }} @endif
</p>
</div>
@if ($r && ! is_null($r['latency']))
<span class="shrink-0 font-mono text-[11px] text-ink-4">{{ __('health.latency', ['ms' => $r['latency']]) }}</span>
@endif
@if ($r)
<x-status-pill :status="$r['ok'] ? 'online' : 'offline'">{{ $r['ok'] ? __('health.status_up') : __('health.status_down') }}</x-status-pill>
@endif
<x-modal-trigger variant="danger-soft" action="confirmDeleteCheck('{{ $check->uuid }}')">{{ __('health.delete') }}</x-modal-trigger>
</div>
@endforeach
</div>
</x-panel>
@endif
</div>