clusev/resources/views/livewire/servers/groups.blade.php

108 lines
6.8 KiB
PHP

@php
// Colour token key -> literal @theme bg utility (literal strings so Tailwind's source scan
// generates them; a dynamic bg-{{ $var }} would never be emitted). R3: tokens only, no hex.
$dot = [
'accent' => 'bg-accent', 'cyan' => 'bg-cyan', 'online' => 'bg-online',
'warning' => 'bg-warning', 'offline' => 'bg-offline', 'ink' => 'bg-ink-3',
];
@endphp
<div class="space-y-5">
{{-- Header --}}
<div class="flex flex-wrap items-end justify-between gap-3">
<div>
<p class="font-mono text-[11px] uppercase tracking-[0.2em] text-accent-text">{{ __('groups.eyebrow') }}</p>
<h2 class="mt-0.5 font-display text-xl font-semibold text-ink sm:text-2xl">{{ __('groups.title') }}</h2>
<p class="mt-1 text-sm text-ink-3">{{ __('groups.subtitle') }}</p>
</div>
<a href="{{ route('servers.index') }}" wire:navigate
class="inline-flex min-h-11 items-center gap-1.5 rounded-md border border-line bg-inset px-3 text-xs text-ink-2 transition-colors hover:bg-raised hover:text-ink">
<x-icon name="server" class="h-3.5 w-3.5" /> {{ __('groups.back_to_servers') }}
</a>
</div>
{{-- New group --}}
<x-panel :title="__('groups.new_group')">
<form wire:submit="create" class="grid gap-4 sm:grid-cols-[minmax(0,1fr)_auto_auto] sm:items-end">
<div>
<label class="mb-1 block font-mono text-[11px] uppercase tracking-wider text-ink-3">{{ __('groups.name_label') }}</label>
<input wire:model="name" type="text" maxlength="60" placeholder="{{ __('groups.name_placeholder') }}"
class="h-9 w-full rounded-md border border-line bg-inset px-3 text-sm text-ink placeholder:text-ink-4 focus:border-accent/40 focus:outline-none" />
@error('name') <p class="mt-1 flex items-center gap-1.5 font-mono text-[11px] text-offline"><x-icon name="alert" class="h-3.5 w-3.5 shrink-0" />{{ $message }}</p> @enderror
</div>
<div>
<label class="mb-1 block font-mono text-[11px] uppercase tracking-wider text-ink-3">{{ __('groups.color_label') }}</label>
<div class="flex h-9 items-center gap-1.5">
@foreach ($colors as $c)
<button type="button" wire:click="$set('color', '{{ $c }}')"
aria-label="{{ $c }}" aria-pressed="{{ $color === $c ? 'true' : 'false' }}"
@class(['grid h-6 w-6 place-items-center rounded-full transition', 'ring-2 ring-offset-2 ring-offset-surface ring-ink' => $color === $c])>
<span class="h-3.5 w-3.5 rounded-full {{ $dot[$c] }}"></span>
</button>
@endforeach
</div>
</div>
<x-btn variant="primary" type="submit">{{ __('groups.create') }}</x-btn>
</form>
</x-panel>
{{-- Groups list --}}
@if ($groups->isEmpty())
<x-panel>
<div class="flex flex-col items-center gap-2 py-8 text-center">
<x-icon name="folder" class="h-6 w-6 text-ink-4" />
<p class="font-display text-sm font-semibold text-ink">{{ __('groups.empty_title') }}</p>
<p class="max-w-sm text-xs text-ink-3">{{ __('groups.empty') }}</p>
</div>
</x-panel>
@else
<div class="space-y-4">
@foreach ($groups as $g)
<x-panel wire:key="group-{{ $g->uuid }}">
<div class="flex flex-wrap items-center gap-3">
<span class="h-3 w-3 shrink-0 rounded-full {{ $dot[$g->color] ?? 'bg-accent' }}"></span>
<input type="text" value="{{ $g->name }}" maxlength="60"
wire:change="rename('{{ $g->uuid }}', $event.target.value)"
class="min-w-0 flex-1 rounded-md border border-transparent bg-transparent px-2 py-1 font-display text-sm font-semibold text-ink hover:border-line focus:border-accent/40 focus:bg-inset focus:outline-none" />
<span class="shrink-0 font-mono text-[11px] text-ink-3">{{ trans_choice('groups.members_count', $g->servers_count, ['count' => $g->servers_count]) }}</span>
{{-- Recolour --}}
<div class="flex shrink-0 items-center gap-1">
@foreach ($colors as $c)
<button type="button" wire:click="setColor('{{ $g->uuid }}', '{{ $c }}')"
aria-label="{{ $c }}" aria-pressed="{{ $g->color === $c ? 'true' : 'false' }}"
@class(['grid h-5 w-5 place-items-center rounded-full transition', 'ring-2 ring-offset-2 ring-offset-surface ring-ink' => $g->color === $c])>
<span class="h-3 w-3 rounded-full {{ $dot[$c] }}"></span>
</button>
@endforeach
</div>
<x-modal-trigger variant="danger-soft" action="confirmDelete('{{ $g->uuid }}')">{{ __('common.delete') }}</x-modal-trigger>
</div>
{{-- Membership grid --}}
<div class="mt-4 border-t border-line pt-4">
<p class="mb-2 font-mono text-[11px] uppercase tracking-wider text-ink-3">{{ __('groups.assign') }}</p>
@if ($servers->isEmpty())
<p class="font-mono text-[11px] text-ink-3">{{ __('groups.no_servers') }}</p>
@else
<div class="grid gap-1.5 sm:grid-cols-2 lg:grid-cols-3">
@php($memberIds = $g->servers->pluck('id'))
@foreach ($servers as $s)
<label class="flex min-h-11 items-center gap-2.5 rounded-md border border-line bg-inset px-3 py-2 text-sm text-ink-2 transition-colors hover:bg-raised sm:min-h-0">
<input type="checkbox" wire:key="member-{{ $g->uuid }}-{{ $s->uuid }}"
@checked($memberIds->contains($s->id))
wire:click="toggleMember('{{ $g->uuid }}', '{{ $s->uuid }}')"
class="h-4 w-4 shrink-0 rounded border-line bg-inset text-accent focus:ring-accent/40" />
<span class="min-w-0 truncate">{{ $s->name }}</span>
</label>
@endforeach
</div>
@endif
</div>
</x-panel>
@endforeach
</div>
@endif
</div>