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

159 lines
8.5 KiB
PHP

<div class="mx-auto max-w-3xl space-y-6">
<div class="animate-rise">
<h1 class="text-2xl font-bold tracking-tight text-ink">{{ __('mail_settings.title') }}</h1>
<p class="mt-1 text-sm text-muted">{{ __('mail_settings.subtitle') }}</p>
</div>
{{-- The one thing that makes every mailbox on this page decorative. Said
here as well as on the front page, because this is where somebody comes
to find out why no mail arrived and the test button below reports
success regardless, since MailboxTester builds its own transport on
purpose (a check that honoured MAIL_MAILER=log would report success
while writing to a file). --}}
@if (in_array(config('mail.default'), ['log', 'array', null], true))
<x-ui.alert variant="warning">
{{ __('admin.notice.mail_not_delivering', ['mailer' => (string) (config('mail.default') ?? 'null')]) }}
</x-ui.alert>
@endif
@if (! $usable)
<x-ui.alert variant="warning">{{ __('mail_settings.no_key') }}</x-ui.alert>
@endif
{{-- 1. The server. One of it, so one card. --}}
<x-ui.card>
<h2 class="text-lg font-semibold text-ink">{{ __('mail_settings.server_title') }}</h2>
<p class="mt-1 text-sm text-muted">{{ __('mail_settings.server_hint') }}</p>
<div class="mt-5 grid gap-4 sm:grid-cols-3">
<x-ui.input name="host" wire:model="host" :label="__('mail_settings.host')" />
<x-ui.input name="port" type="number" wire:model="port" :label="__('mail_settings.port')" />
<div>
<label for="encryption" class="text-sm font-medium text-ink">{{ __('mail_settings.encryption') }}</label>
<select id="encryption" wire:model="encryption"
class="mt-1.5 w-full rounded-md border border-line-strong bg-surface px-3 py-2 text-sm text-body">
<option value="tls">TLS</option>
<option value="ssl">SSL</option>
<option value="none">{{ __('mail_settings.encryption_none') }}</option>
</select>
@error('encryption')<p class="mt-1 text-xs text-danger">{{ $message }}</p>@enderror
</div>
</div>
@if (! $passwordConfirmed)
{{-- The second gate. $host is the platform's outbound relay for
every purpose at once — being signed in is not enough to
repoint it, the same reasoning as the credentials page. --}}
<form wire:submit="confirmPassword" class="mt-5 rounded-lg border border-line bg-surface-2 p-4">
<p class="text-sm text-body">{{ __('mail_settings.confirm_first') }}</p>
<div class="mt-3 flex flex-wrap items-start gap-2">
<div class="min-w-56 flex-1">
<x-ui.input name="confirmablePassword" type="password" autocomplete="current-password"
:label="__('admin_settings.password_current')" wire:model="confirmablePassword" />
</div>
<x-ui.button type="submit" variant="secondary" class="mt-7" wire:loading.attr="disabled" wire:target="confirmPassword">
{{ __('mail_settings.confirm_button') }}
</x-ui.button>
</div>
</form>
@else
<x-ui.button wire:click="saveServer" variant="primary" size="md" class="mt-5">
{{ __('mail_settings.save') }}
</x-ui.button>
@endif
</x-ui.card>
{{-- 2. The mailboxes. NO input field inside a <td> — R20. --}}
<x-ui.card>
<h2 class="text-lg font-semibold text-ink">{{ __('mail_settings.boxes_title') }}</h2>
{{-- One shared recipient field for every row's test button below a
field ABOVE the table, not one growing inside a <td> (R20). --}}
<div class="mt-4 max-w-sm">
<x-ui.input name="testRecipient" type="email" wire:model="testRecipient" :label="__('mail_settings.test_recipient')" />
<p class="mt-2 text-sm text-muted">{{ __('mail_settings.test_hint') }}</p>
</div>
@if ($testResult)
<x-ui.alert :variant="$testResult['ok'] ? 'success' : 'danger'" class="mt-4">
<span class="font-medium">{{ $testedKey }}:</span>
@if ($testResult['ok'])
{{ __('mail_settings.test_ok') }}
@else
{{ __('mail_settings.test_failed') }} {{ $testResult['error'] }}
@endif
</x-ui.alert>
@endif
<table class="mt-5 w-full text-sm">
<thead>
<tr class="border-b border-line text-left">
<th class="lbl pb-2">{{ __('mail_settings.address') }}</th>
<th class="lbl pb-2">{{ __('mail_settings.last_verified') }}</th>
<th class="lbl pb-2"></th>
</tr>
</thead>
<tbody>
@foreach ($mailboxes as $box)
<tr wire:key="mailbox-{{ $box->uuid }}" class="border-b border-line last:border-0">
<td class="py-3">
<span class="font-medium text-ink">{{ $box->address }}</span>
<span class="ml-2 text-muted">{{ $box->key }}</span>
</td>
<td class="py-3 text-muted">
{{ $box->last_verified_at?->local()->isoFormat('DD.MM.YYYY HH:mm') ?? __('mail_settings.never_verified') }}
</td>
<td class="py-3 text-right space-x-2">
{{-- R18: icon beside its text, single line, size-4.
Two spans swapped by wire:loading, same
pattern as admin/host-create.blade.php's save
button — the disabled attribute alone left an
operator staring at a greyed-out button with
no sign anything was happening for up to the
full connect timeout. --}}
<x-ui.button size="sm" variant="ghost" wire:click="test('{{ $box->uuid }}')"
wire:loading.attr="disabled" wire:target="test('{{ $box->uuid }}')">
<x-ui.icon name="send" class="size-4" />
<span wire:loading.remove wire:target="test('{{ $box->uuid }}')">{{ __('mail_settings.test') }}</span>
<span wire:loading wire:target="test('{{ $box->uuid }}')">{{ __('mail_settings.testing') }}</span>
</x-ui.button>
<x-ui.button size="sm" variant="ghost"
x-on:click="$dispatch('openModal', { component: 'edit-mailbox', arguments: { uuid: '{{ $box->uuid }}' } })">
<x-ui.icon name="pencil" class="size-4" />{{ __('mail_settings.edit') }}
</x-ui.button>
</td>
</tr>
@endforeach
</tbody>
</table>
</x-ui.card>
{{-- 3. The mapping. One <select> per row — R20's stated exception. --}}
<x-ui.card>
<h2 class="text-lg font-semibold text-ink">{{ __('mail_settings.purposes_title') }}</h2>
<p class="mt-1 text-sm text-muted">{{ __('mail_settings.purposes_hint') }}</p>
<div class="mt-5 space-y-3">
@foreach ($purposeList as $purpose)
<div class="flex items-center justify-between gap-6 border-b border-line py-2">
<span class="text-sm text-ink">{{ __('mail_settings.purpose.'.$purpose) }}</span>
<select wire:model="purposes.{{ $purpose }}"
class="w-64 rounded-md border border-line-strong bg-surface px-3 py-2 text-sm text-body">
<option value=""></option>
@foreach ($mailboxes as $box)
<option value="{{ $box->key }}">{{ $box->address }}</option>
@endforeach
</select>
</div>
@endforeach
</div>
@error('purposes.system')<p class="mt-3 text-xs text-danger">{{ $message }}</p>@enderror
<x-ui.button wire:click="savePurposes" variant="primary" size="md" class="mt-5">
{{ __('mail_settings.save') }}
</x-ui.button>
</x-ui.card>
</div>