111 lines
7.1 KiB
PHP
111 lines
7.1 KiB
PHP
<div class="mx-auto max-w-[1120px] space-y-5">
|
|
<div class="animate-rise">
|
|
<h1 class="text-2xl font-bold tracking-tight text-ink">{{ __('templates.title') }}</h1>
|
|
<p class="mt-1 max-w-[75ch] text-sm text-muted">{{ __('templates.subtitle') }}</p>
|
|
</div>
|
|
|
|
<div class="grid gap-5 lg:grid-cols-[1fr_320px] lg:items-start">
|
|
<div class="space-y-5">
|
|
{{-- The list. Order is the operator's own, because the order they
|
|
think in is neither alphabetical nor the order these happened to
|
|
be written in. --}}
|
|
<div class="overflow-hidden rounded-lg border border-line bg-surface shadow-xs animate-rise">
|
|
<h2 class="border-b border-line px-6 py-4 font-semibold text-ink">{{ __('templates.list') }}</h2>
|
|
|
|
@if ($templates->isEmpty())
|
|
<p class="p-8 text-center text-sm text-muted">{{ __('templates.empty') }}</p>
|
|
@else
|
|
<ul class="divide-y divide-line">
|
|
@foreach ($templates as $template)
|
|
<li wire:key="tpl-{{ $template->uuid }}" class="px-6 py-4">
|
|
<div class="flex flex-wrap items-baseline gap-x-3 gap-y-1">
|
|
<span @class(['font-medium', 'text-ink' => $template->active, 'text-muted line-through' => ! $template->active])>
|
|
{{ $template->name }}
|
|
</span>
|
|
@if (! $template->active)
|
|
<x-ui.badge status="warning">{{ __('templates.retired') }}</x-ui.badge>
|
|
@endif
|
|
<span class="ml-auto flex items-center gap-1">
|
|
{{-- Two clicks, one value each, no height
|
|
change: R20's exception. --}}
|
|
<button type="button" wire:click="move('{{ $template->uuid }}', -15)"
|
|
class="rounded p-1.5 text-muted hover:text-ink" aria-label="{{ __('templates.up') }}">
|
|
<x-ui.icon name="chevron-down" class="size-4 rotate-180" />
|
|
</button>
|
|
<button type="button" wire:click="move('{{ $template->uuid }}', 15)"
|
|
class="rounded p-1.5 text-muted hover:text-ink" aria-label="{{ __('templates.down') }}">
|
|
<x-ui.icon name="chevron-down" class="size-4" />
|
|
</button>
|
|
</span>
|
|
</div>
|
|
|
|
<p class="mt-1 text-sm text-body">{{ $template->subject }}</p>
|
|
<p class="mt-1.5 line-clamp-2 text-xs leading-relaxed text-muted">{{ $template->body }}</p>
|
|
|
|
<div class="mt-3 flex flex-wrap gap-2">
|
|
{{-- R20: editing opens a modal. A five-line
|
|
textarea in a list row is the height jump
|
|
the rule exists to stop. --}}
|
|
<x-ui.button variant="secondary" size="sm"
|
|
x-on:click="$dispatch('openModal', { component: 'admin.edit-mail-template', arguments: { uuid: '{{ $template->uuid }}' } })">
|
|
<x-ui.icon name="pencil" class="size-4" />{{ __('templates.edit') }}
|
|
</x-ui.button>
|
|
<x-ui.button variant="ghost" size="sm" wire:click="toggleActive('{{ $template->uuid }}')">
|
|
{{ $template->active ? __('templates.retire') : __('templates.restore') }}
|
|
</x-ui.button>
|
|
</div>
|
|
</li>
|
|
@endforeach
|
|
</ul>
|
|
@endif
|
|
</div>
|
|
|
|
{{-- Creating. A form that IS the page rather than a modal — R20
|
|
exempts exactly this, because nothing is being edited in place. --}}
|
|
<form wire:submit="create" class="space-y-4 rounded-lg border border-line bg-surface p-6 shadow-xs animate-rise [animation-delay:60ms]">
|
|
<h2 class="font-semibold text-ink">{{ __('templates.new') }}</h2>
|
|
|
|
<div class="grid gap-4 sm:grid-cols-2">
|
|
<x-ui.input name="name" wire:model="name" :label="__('templates.name')" :placeholder="__('templates.name_hint')" />
|
|
<x-ui.input name="subject" wire:model="subject" :label="__('templates.subject')" :placeholder="__('templates.subject_hint')" />
|
|
</div>
|
|
|
|
<div>
|
|
<label for="body" class="block text-sm font-medium text-body">{{ __('templates.body') }}</label>
|
|
<textarea id="body" rows="8" wire:model="body"
|
|
class="mt-1.5 block w-full rounded border border-line bg-surface px-3.5 py-2.5 text-sm text-ink placeholder:text-faint"
|
|
placeholder="{{ __('templates.body_hint') }}"></textarea>
|
|
@error('body')<p class="mt-1.5 text-xs text-danger">{{ $message }}</p>@enderror
|
|
</div>
|
|
|
|
<x-ui.button type="submit" variant="primary" wire:loading.attr="disabled" wire:target="create">
|
|
<x-ui.icon name="plus" class="size-4" />{{ __('templates.create') }}
|
|
</x-ui.button>
|
|
</form>
|
|
</div>
|
|
|
|
{{-- The placeholders, rendered from the renderer's own list so a token
|
|
added there appears here without anybody writing it down twice. --}}
|
|
<div class="space-y-4 rounded-lg border border-line bg-surface p-6 shadow-xs animate-rise [animation-delay:120ms] lg:sticky lg:top-6">
|
|
<h2 class="font-semibold text-ink">{{ __('templates.placeholders') }}</h2>
|
|
<p class="text-xs leading-relaxed text-muted">{{ __('templates.placeholders_note') }}</p>
|
|
|
|
<dl class="space-y-3">
|
|
@foreach ($placeholders as $token => $explanation)
|
|
{{-- Assembled in PHP, not inline: Blade's echo tag ends at
|
|
the first }} it finds, so a literal one inside the
|
|
expression cuts the tag in half and compiles to
|
|
nonsense. Caught by the test that renders this page. --}}
|
|
@php $literal = '{{'.$token.'}}'; @endphp
|
|
<div>
|
|
<dt class="select-all font-mono text-xs font-semibold text-accent-text">{{ $literal }}</dt>
|
|
<dd class="mt-0.5 text-xs leading-relaxed text-muted">{{ __($explanation) }}</dd>
|
|
</div>
|
|
@endforeach
|
|
</dl>
|
|
|
|
<p class="border-t border-line pt-3 text-xs leading-relaxed text-muted">{{ __('templates.unknown_note') }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|