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

77 lines
4.3 KiB
PHP

@php
$ratingStatus = ['strong' => 'online', 'fair' => 'warning', 'weak' => 'offline'];
$scoreColor = fn (int $s) => $s >= 90 ? 'text-online' : ($s >= 60 ? 'text-warning' : 'text-offline');
@endphp
<div class="space-y-4" @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">{{ __('posture.eyebrow') }}</p>
<h2 class="mt-0.5 font-display text-xl font-semibold text-ink sm:text-2xl">{{ __('posture.title') }}</h2>
<p class="mt-1 text-sm text-ink-3">{{ __('posture.subtitle') }}</p>
</div>
@if ($ready && ! is_null($average))
<div class="text-right">
<p class="font-mono text-[10px] uppercase tracking-wider text-ink-3">{{ __('posture.fleet_avg') }}</p>
<p class="tabular font-mono text-2xl font-semibold {{ $scoreColor($average) }}">{{ $average }}<span class="text-sm text-ink-3">/100</span></p>
</div>
@endif
</div>
@if ($servers->isEmpty())
<x-panel>
<div class="py-8 text-center">
<p class="font-display text-sm font-semibold text-ink">{{ __('posture.no_servers_title') }}</p>
<p class="mt-1 text-xs text-ink-3">{{ __('posture.no_servers') }}</p>
</div>
</x-panel>
@elseif (! $ready)
<div class="space-y-2">
@foreach ($servers as $s)
<div wire:key="sk-{{ $s->uuid }}" class="h-20 animate-pulse rounded-lg bg-raised/50"></div>
@endforeach
<p class="text-center font-mono text-[11px] text-ink-4">{{ __('posture.scan_hint') }}</p>
</div>
@else
<div class="space-y-3">
@foreach ($servers as $s)
@php($r = $scores[$s->uuid] ?? null)
<x-panel wire:key="pk-{{ $s->uuid }}">
@if (! $r || isset($r['error']))
<div class="flex items-center gap-3">
<x-status-dot status="offline" class="h-2.5 w-2.5" />
<span class="min-w-0 flex-1 truncate font-mono text-sm text-ink">{{ $s->name }}</span>
<span class="font-mono text-[11px] text-offline">{{ __('posture.scan_error') }}</span>
</div>
@else
<div class="flex flex-wrap items-center gap-4">
<div class="shrink-0 text-center">
<p class="tabular font-mono text-3xl font-semibold {{ $scoreColor($r['score']) }}">{{ $r['score'] }}</p>
<x-status-pill :status="$ratingStatus[$r['rating']]">{{ __('posture.rating_'.$r['rating']) }}</x-status-pill>
</div>
<div class="min-w-0 flex-1">
<a href="{{ route('servers.show', $s->uuid) }}" wire:navigate class="font-display text-sm font-semibold text-ink hover:text-accent-text">{{ $s->name }}</a>
<p class="mt-0.5 font-mono text-[11px] text-ink-3">{{ __('posture.passed_of', ['passed' => $r['passed'], 'applicable' => $r['applicable']]) }}</p>
<div class="mt-2 flex flex-wrap gap-1.5">
@foreach ($r['checks'] as $c)
@if ($c['counts'])
<span @class([
'inline-flex items-center gap-1 rounded-sm border px-1.5 py-0.5 font-mono text-[10px]',
'border-online/20 bg-online/10 text-online' => $c['secure'],
'border-offline/20 bg-offline/10 text-offline' => ! $c['secure'],
])>
{{ $c['label'] }}
</span>
@endif
@endforeach
</div>
</div>
</div>
@endif
</x-panel>
@endforeach
</div>
@endif
</div>