160 lines
10 KiB
PHP
160 lines
10 KiB
PHP
{{--
|
|
The processing agreement, in the console.
|
|
|
|
Upload left, what is in force and who has it right, the versions underneath.
|
|
Uploading and publishing are two acts on purpose: publishing leaves every
|
|
customer outstanding again, and that is not something to trigger by dropping
|
|
a file on a form.
|
|
--}}
|
|
<div class="space-y-6">
|
|
|
|
<header class="animate-rise">
|
|
<p class="lbl">{{ __('dpa_admin.eyebrow') }}</p>
|
|
<h1 class="mt-[7px] text-[23px] font-bold leading-[1.12] tracking-[-0.03em] text-ink min-[901px]:text-[30px]">
|
|
{{ __('dpa_admin.title') }}
|
|
</h1>
|
|
<p class="mt-2 max-w-[76ch] text-sm leading-relaxed text-muted">{{ __('dpa_admin.subtitle') }}</p>
|
|
</header>
|
|
|
|
<div class="grid gap-5 lg:grid-cols-[minmax(0,1fr)_360px] lg:items-start">
|
|
|
|
{{-- ── Upload ─────────────────────────────────────────────────────── --}}
|
|
<form wire:submit="upload" class="space-y-5 rounded-lg border border-line bg-surface p-6 shadow-xs animate-rise [animation-delay:40ms]">
|
|
<div>
|
|
<h2 class="text-sm font-bold text-ink">{{ __('dpa_admin.upload_title') }}</h2>
|
|
<p class="mt-1 text-sm leading-relaxed text-muted">{{ __('dpa_admin.upload_sub') }}</p>
|
|
</div>
|
|
|
|
<div class="grid gap-4 sm:grid-cols-2">
|
|
<x-ui.input name="version" wire:model="version" :label="__('dpa_admin.version')" :hint="__('dpa_admin.version_hint')" />
|
|
<x-ui.input name="note" wire:model="note" :label="__('dpa_admin.note')" :hint="__('dpa_admin.note_hint')" />
|
|
</div>
|
|
|
|
<div class="grid gap-4 sm:grid-cols-2">
|
|
<div>
|
|
<label class="text-sm font-medium text-body">{{ __('dpa_admin.file_agreement') }}</label>
|
|
<input type="file" wire:model="agreement" accept="application/pdf"
|
|
class="mt-1.5 w-full text-sm text-body file:mr-3 file:rounded file:border-0 file:bg-surface-2 file:px-3 file:py-1.5 file:text-sm file:font-semibold file:text-body" />
|
|
@error('agreement')<p class="mt-1 text-xs text-danger">{{ $message }}</p>@enderror
|
|
</div>
|
|
<div>
|
|
<label class="text-sm font-medium text-body">{{ __('dpa_admin.file_measures') }}</label>
|
|
<input type="file" wire:model="measures" accept="application/pdf"
|
|
class="mt-1.5 w-full text-sm text-body file:mr-3 file:rounded file:border-0 file:bg-surface-2 file:px-3 file:py-1.5 file:text-sm file:font-semibold file:text-body" />
|
|
@error('measures')<p class="mt-1 text-xs text-danger">{{ $message }}</p>@enderror
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex justify-end border-t border-line pt-4">
|
|
<x-ui.button type="submit" variant="primary" wire:loading.attr="disabled" wire:target="upload,agreement,measures">
|
|
{{ __('dpa_admin.upload_cta') }}
|
|
</x-ui.button>
|
|
</div>
|
|
</form>
|
|
|
|
{{-- ── What is in force ───────────────────────────────────────────── --}}
|
|
<div class="space-y-4 rounded-lg border border-line bg-surface p-6 shadow-xs animate-rise [animation-delay:80ms]">
|
|
<h2 class="text-sm font-bold text-ink">{{ __('dpa_admin.current_title') }}</h2>
|
|
|
|
@if ($current === null)
|
|
<p class="text-sm leading-relaxed text-muted">{{ __('dpa_admin.none_yet') }}</p>
|
|
@else
|
|
<p class="font-mono text-lg font-semibold text-ink">{{ $current->version }}</p>
|
|
{{-- R19: stored in UTC, read on the wall clock. --}}
|
|
<p class="text-xs text-muted">{{ __('dpa_admin.in_force_since', ['when' => $current->published_at->local()->isoFormat('LL')]) }}</p>
|
|
|
|
<div class="border-t border-line pt-4">
|
|
<p class="text-sm text-body">
|
|
{{ __('dpa_admin.accepted_count', ['accepted' => $accepted, 'total' => $customers]) }}
|
|
</p>
|
|
@if ($outstanding > 0)
|
|
<p class="mt-1 text-sm font-semibold text-warning">{{ __('dpa_admin.outstanding', ['count' => $outstanding]) }}</p>
|
|
@endif
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
{{-- ── The versions ───────────────────────────────────────────────────── --}}
|
|
<div class="overflow-hidden rounded-lg border border-line bg-surface shadow-xs animate-rise [animation-delay:120ms]">
|
|
<div class="border-b border-line px-6 py-4">
|
|
<h2 class="text-sm font-bold text-ink">{{ __('dpa_admin.versions_title') }}</h2>
|
|
</div>
|
|
|
|
@if ($versions->isEmpty())
|
|
<p class="px-6 py-10 text-center text-sm text-muted">{{ __('dpa_admin.no_versions') }}</p>
|
|
@else
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full text-sm">
|
|
<thead>
|
|
<tr class="border-b border-line text-left">
|
|
<th class="px-6 py-3 font-medium text-muted">{{ __('dpa_admin.col_version') }}</th>
|
|
<th class="px-6 py-3 font-medium text-muted">{{ __('dpa_admin.col_state') }}</th>
|
|
<th class="px-6 py-3 font-medium text-muted">{{ __('dpa_admin.col_accepted') }}</th>
|
|
<th class="px-6 py-3 font-medium text-muted">{{ __('dpa_admin.col_files') }}</th>
|
|
<th class="px-6 py-3"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach ($versions as $v)
|
|
<tr wire:key="dpa-{{ $v->uuid }}" class="border-b border-line last:border-0">
|
|
<td class="px-6 py-3">
|
|
<span class="font-mono font-semibold text-ink">{{ $v->version }}</span>
|
|
@if ($v->note)
|
|
<span class="mt-0.5 block text-xs text-muted">{{ $v->note }}</span>
|
|
@endif
|
|
</td>
|
|
<td class="px-6 py-3">
|
|
@if ($v->isPublished())
|
|
<x-ui.badge status="{{ $current?->id === $v->id ? 'success' : 'neutral' }}">
|
|
{{ $current?->id === $v->id ? __('dpa_admin.state_current') : __('dpa_admin.state_superseded') }}
|
|
</x-ui.badge>
|
|
<span class="mt-0.5 block text-xs text-muted">{{ $v->published_at->local()->isoFormat('LL') }}</span>
|
|
@else
|
|
<x-ui.badge status="warning">{{ __('dpa_admin.state_draft') }}</x-ui.badge>
|
|
@endif
|
|
</td>
|
|
<td class="px-6 py-3 font-mono tabular-nums text-body">{{ $v->acceptances_count }}</td>
|
|
<td class="px-6 py-3">
|
|
<div class="flex flex-wrap gap-2">
|
|
<a href="{{ route('admin.dpa.file', ['uuid' => $v->uuid, 'which' => 'agreement']) }}"
|
|
target="_blank" rel="noopener"
|
|
class="text-xs font-semibold text-accent-text underline-offset-4 hover:underline">
|
|
{{ __('dpa_admin.file_agreement') }}
|
|
</a>
|
|
@if ($v->measures_path)
|
|
<a href="{{ route('admin.dpa.file', ['uuid' => $v->uuid, 'which' => 'measures']) }}"
|
|
target="_blank" rel="noopener"
|
|
class="text-xs font-semibold text-accent-text underline-offset-4 hover:underline">
|
|
{{ __('dpa_admin.file_measures') }}
|
|
</a>
|
|
@endif
|
|
{{-- A download, so it says so and looks like
|
|
a control rather than a third link in
|
|
a row of two. --}}
|
|
<a href="{{ route('admin.dpa.file', ['uuid' => $v->uuid, 'which' => 'agreement', 'download' => 1]) }}"
|
|
download
|
|
class="inline-flex items-center gap-1 rounded border border-line-strong bg-surface px-2 py-0.5 text-xs font-semibold text-body hover:bg-surface-hover">
|
|
<x-ui.icon name="download" class="size-3.5" />{{ __('dpa_admin.download') }}
|
|
</a>
|
|
</div>
|
|
</td>
|
|
<td class="px-6 py-3 text-right">
|
|
@if (! $v->isPublished())
|
|
{{-- R23: a modal, because publishing leaves every
|
|
customer outstanding again. --}}
|
|
<x-ui.button size="sm" variant="secondary"
|
|
x-on:click="$dispatch('openModal', { component: 'admin.confirm-publish-dpa', arguments: { uuid: '{{ $v->uuid }}' } })">
|
|
{{ __('dpa_admin.publish') }}
|
|
</x-ui.button>
|
|
@endif
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|