CluPilotCloud/resources/views/livewire/admin/provisioning.blade.php

104 lines
7.0 KiB
PHP

<div class="space-y-5" @if ($hasActive) wire:poll.4s @endif>
<div class="animate-rise">
<h1 class="text-2xl font-semibold tracking-tight text-ink">{{ __('admin.nav.provisioning') }}</h1>
<p class="mt-1 text-sm text-muted">{{ __('admin.provisioning_sub') }}</p>
</div>
<div class="grid grid-cols-1 gap-5 lg:grid-cols-[1fr_300px] lg:items-start">
<div class="overflow-hidden rounded-xl border border-line bg-surface shadow-xs animate-rise [animation-delay:60ms]">
@if (count($rows) === 0)
<p class="p-8 text-center text-sm text-muted">{{ __('admin.no_runs') }}</p>
@else
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b border-line bg-surface-2 text-left text-xs uppercase tracking-wide text-faint">
<th class="px-4 py-3 font-semibold">{{ __('admin.col.customer') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.col.step') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.col.attempt') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.col.status') }}</th>
<th class="px-4 py-3 text-right font-semibold">{{ __('admin.col.actions') }}</th>
</tr>
</thead>
<tbody>
@foreach ($rows as $r)
@php $tone = ['running' => 'provisioning', 'done' => 'active', 'failed' => 'failed'][$r['state']] ?? 'info'; @endphp
<tr wire:key="run-{{ $r['uuid'] }}" class="border-b border-line last:border-0 hover:bg-surface-hover">
<td class="px-4 py-3 font-medium text-ink">{{ $r['customer'] }}
<span class="ml-1 font-mono text-xs text-faint">{{ $r['pipeline'] }}</span></td>
<td class="px-4 py-3"><span class="text-xs text-body">{{ $r['step'] }}</span>
<span class="font-mono text-xs text-faint">{{ $r['n'] }}</span></td>
<td class="px-4 py-3 font-mono text-xs text-muted">{{ $r['attempt'] }}</td>
<td class="px-4 py-3"><x-ui.badge :status="$tone">{{ __('admin.state_'.$r['state']) }}</x-ui.badge></td>
<td class="px-4 py-3 text-right">
@if ($r['failed'])
<button type="button" wire:click="retry('{{ $r['uuid'] }}')" wire:loading.attr="disabled" wire:target="retry('{{ $r['uuid'] }}')"
class="inline-flex items-center gap-1.5 rounded-md border border-line px-2.5 py-1.5 text-xs font-semibold text-body hover:border-accent-border hover:text-accent-text">
<x-ui.icon name="rotate-ccw" class="size-3.5" />{{ __('admin.retry') }}
</button>
@else
<span class="text-xs text-faint"></span>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
</div>
<div class="rounded-xl border border-line bg-surface p-5 shadow-xs animate-rise [animation-delay:120ms]">
<div class="flex items-center justify-between">
<h2 class="text-xs font-semibold uppercase tracking-wider text-faint">{{ __('admin.run_detail') }}</h2>
@if ($panel)
<span class="font-mono text-xs {{ $panel['failed'] ? 'text-danger' : 'text-muted' }}">{{ $panel['percent'] }}%</span>
@endif
</div>
@if (! $panel)
<p class="mt-4 text-sm text-muted">{{ __('admin.no_runs') }}</p>
@else
<p class="mt-2 truncate font-semibold text-ink">{{ $panel['subject'] }}</p>
<p class="font-mono text-xs text-faint">{{ $panel['pipeline'] }} · {{ __('admin.run_attempt', ['n' => $panel['attempt']]) }}</p>
{{-- Progress bar (width is the one allowed inline style, R4) --}}
<div class="mt-4 h-1.5 overflow-hidden rounded-pill bg-surface-2">
<div class="h-full rounded-pill {{ $panel['failed'] ? 'bg-danger' : 'bg-accent' }} transition-[width] duration-500"
style="width: {{ $panel['percent'] }}%"></div>
</div>
<p class="mt-1.5 font-mono text-xs text-muted">{{ __('admin.run_done', ['done' => $panel['done'], 'total' => $panel['total']]) }}</p>
@if ($panel['failed'])
<div class="mt-4 rounded-lg border border-danger-border bg-danger-bg p-3">
<p class="text-xs font-semibold text-danger">{{ __('admin.state_failed') }}</p>
@if ($panel['error'])<p class="mt-0.5 break-words text-xs text-body">{{ $panel['error'] }}</p>@endif
<button type="button" wire:click="retry('{{ $panel['uuid'] }}')" wire:loading.attr="disabled" wire:target="retry('{{ $panel['uuid'] }}')"
class="mt-3 inline-flex items-center gap-1.5 rounded-md border border-danger-border px-2.5 py-1.5 text-xs font-semibold text-danger hover:bg-danger/10">
<x-ui.icon name="rotate-ccw" class="size-3.5" />{{ __('admin.retry') }}
</button>
</div>
@elseif ($panel['current'])
<div class="mt-4">
<p class="text-[0.65rem] font-semibold uppercase tracking-wider text-faint">{{ __('admin.run_current') }}</p>
<div class="mt-1.5 flex items-center gap-2.5">
<span class="size-2 shrink-0 rounded-pill bg-info motion-safe:animate-pulse" aria-hidden="true"></span>
<span class="text-sm font-medium text-ink">{{ $panel['current'] }}</span>
</div>
</div>
@endif
@if ($panel['next'] && ! $panel['failed'])
<div class="mt-4">
<p class="text-[0.65rem] font-semibold uppercase tracking-wider text-faint">{{ __('admin.run_next') }}</p>
<div class="mt-1.5 flex items-center gap-2.5">
<span class="size-2 shrink-0 rounded-pill border border-line-strong" aria-hidden="true"></span>
<span class="text-sm text-muted">{{ $panel['next'] }}</span>
</div>
</div>
@endif
@endif
</div>
</div>
</div>