111 lines
6.7 KiB
PHP
111 lines
6.7 KiB
PHP
<div class="space-y-5">
|
|
<div class="animate-rise">
|
|
<h1 class="text-2xl font-bold tracking-tight text-ink">{{ __('readiness.page_title') }}</h1>
|
|
<p class="mt-1 text-sm text-muted">{{ __('readiness.page_sub') }}</p>
|
|
</div>
|
|
|
|
{{-- The one line that matters. Everything below is detail. --}}
|
|
<div class="flex items-center gap-3 rounded-lg border p-5 shadow-xs animate-rise
|
|
{{ $ready ? 'border-success-border bg-success-bg' : 'border-warning-border bg-warning-bg' }}">
|
|
<x-ui.icon :name="$ready ? 'shield-check' : 'alert-triangle'"
|
|
class="{{ $ready ? 'text-success' : 'text-warning' }}" />
|
|
<p class="text-lg font-semibold {{ $ready ? 'text-success' : 'text-warning' }}">
|
|
@if ($ready)
|
|
{{ $mode->isTest() ? __('readiness.ready_test') : __('readiness.ready_live') }}
|
|
@else
|
|
{{ trans_choice('readiness.not_ready', $blockingCount, ['n' => $blockingCount]) }}
|
|
@endif
|
|
</p>
|
|
</div>
|
|
|
|
@foreach ($groups as $groupKey => $checks)
|
|
<div class="rounded-lg border border-line bg-surface p-5 shadow-xs animate-rise">
|
|
<h2 class="font-semibold text-ink">{{ __('readiness.group.'.$groupKey) }}</h2>
|
|
|
|
<ul class="mt-3 divide-y divide-line">
|
|
@foreach ($checks as $check)
|
|
@php
|
|
$badgeStatus = $check->satisfied ? 'active' : ($check->isBlocking() ? 'failed' : 'warning');
|
|
$statusLabel = $check->satisfied
|
|
? __('readiness.status.satisfied')
|
|
: ($check->isBlocking() ? __('readiness.status.blocking') : __('readiness.status.warning'));
|
|
$iconName = $check->satisfied ? 'check' : ($check->isBlocking() ? 'x' : 'alert-triangle');
|
|
$iconTone = $check->satisfied ? 'text-success' : ($check->isBlocking() ? 'text-danger' : 'text-warning');
|
|
$result = $results[$check->key] ?? null;
|
|
$heartbeat = $heartbeats[$check->key] ?? null;
|
|
@endphp
|
|
<li class="flex flex-wrap items-start gap-3 py-3">
|
|
<x-ui.icon :name="$iconName" class="mt-0.5 size-4 shrink-0 {{ $iconTone }}" />
|
|
|
|
<div class="min-w-0 flex-1">
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
<span class="font-medium text-ink">{{ $check->label }}</span>
|
|
<x-ui.badge :status="$badgeStatus">{{ $statusLabel }}</x-ui.badge>
|
|
</div>
|
|
|
|
@unless ($check->satisfied)
|
|
<p class="mt-1 text-sm text-muted">{{ $check->breaks }}</p>
|
|
@endunless
|
|
|
|
@if ($heartbeat !== null)
|
|
<p class="mt-1 font-mono text-xs text-faint">
|
|
{{ __('readiness.last_heartbeat', ['when' => $heartbeat]) }}
|
|
</p>
|
|
@endif
|
|
|
|
@if ($result !== null)
|
|
<p class="mt-1 text-xs {{ $result['ok'] ? 'text-success' : 'text-danger' }}">
|
|
{{ $result['ok'] ? __('readiness.check_ok') : __('readiness.check_failed') }}
|
|
@if (($result['reason'] ?? null) !== null)
|
|
— <span class="font-mono">{{ $result['reason'] }}</span>
|
|
@endif
|
|
</p>
|
|
|
|
{{-- StripeCheck rechnet die Kontoart des Schlüssels längst aus,
|
|
und diese Seite hat sie bislang weggeworfen: wer „Prüfen"
|
|
drückte, las „Geprüft: in Ordnung" über einen Live-Schlüssel
|
|
im Testplatz. Die Prüfung selbst blockiert dafür jetzt
|
|
(BillingChecks); hier steht, was der Knopf gerade gesehen
|
|
hat, damit er ihr nicht widerspricht. --}}
|
|
@if (array_key_exists('live', $result))
|
|
@php $keyMode = $result['live'] ? 'live' : 'test'; @endphp
|
|
<p class="mt-1 text-xs {{ $keyMode === $mode->value ? 'text-muted' : 'text-danger' }}">
|
|
{{ __('readiness.check_key_mode', ['mode' => __('readiness.mode.'.$keyMode)]) }}
|
|
@unless ($keyMode === $mode->value)
|
|
{{ __('readiness.check_key_mode_conflict', ['mode' => __('readiness.mode.'.$mode->value)]) }}
|
|
@endunless
|
|
</p>
|
|
@endif
|
|
@endif
|
|
</div>
|
|
|
|
<div class="flex shrink-0 items-center gap-3">
|
|
{{-- mount() only requires hosts.manage OR secrets.manage, so an
|
|
Admin (hosts.manage alone) can reach this page — but runCheck()
|
|
itself demands secrets.manage and 403s otherwise. A button that
|
|
is visible and throws when pressed is worse than no button. --}}
|
|
@if (in_array($check->key, $runnable, true))
|
|
@can('secrets.manage')
|
|
<x-ui.button variant="secondary" size="sm"
|
|
wire:click="runCheck('{{ $check->key }}')"
|
|
wire:loading.attr="disabled"
|
|
wire:target="runCheck('{{ $check->key }}')">
|
|
<x-ui.icon name="refresh" class="size-4" />
|
|
{{ __('readiness.run_check') }}
|
|
</x-ui.button>
|
|
@endcan
|
|
@endif
|
|
|
|
<a href="{{ $this->checkUrl($check) }}" wire:navigate
|
|
class="inline-flex items-center gap-1 text-xs font-semibold text-accent-text hover:underline">
|
|
{{ __('readiness.fix_link') }}
|
|
<x-ui.icon name="external-link" class="size-4" />
|
|
</a>
|
|
</div>
|
|
</li>
|
|
@endforeach
|
|
</ul>
|
|
</div>
|
|
@endforeach
|
|
</div>
|