feat(users): idioma por defecto con banderas SVG + conmutador coherente

- Campo "Idioma por defecto" al crear/editar usuario (columna locale ya existente),
  como desplegable Alpine con banderas SVG reales (no emoji, que en Windows se ven
  como "ES"/"GB") servidas localmente: public/images/flags/{es,gb}.svg.
- User: locale añadido a fillable. UserForm: propiedad/validación/guardado de locale.
- LanguageSwitcher de la cabecera usa las mismas banderas SVG.
- Regla CSS [x-cloak] en el layout para evitar parpadeo de desplegables Alpine.

Tests: UserLocaleTest (2) — crear/editar persisten el idioma.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-18 13:10:27 +02:00
parent 8c774d075d
commit 19e1f57983
8 changed files with 150 additions and 3 deletions
@@ -291,6 +291,46 @@
@error('formRole') <p class="text-error text-xs mt-1">{{ $message }}</p> @enderror
</div>
</div>
<div class="flex items-start gap-4 mt-4">
<label class="w-48 shrink-0 pt-2 text-sm font-medium text-gray-700">
Idioma por defecto <span class="text-error">*</span>
<p class="text-xs text-gray-400 font-normal mt-0.5">Idioma de la interfaz para este usuario</p>
</label>
<div class="flex-1">
<div x-data="{ open: false }" @click.outside="open = false" class="relative w-full max-w-xs">
{{-- Trigger: muestra la bandera + nombre del idioma seleccionado --}}
<button type="button" @click="open = !open"
class="select select-bordered w-full flex items-center gap-2 text-left">
@foreach($languages as $code => $lang)
<span x-show="$wire.locale === '{{ $code }}'" class="flex items-center gap-2">
<img src="{{ asset('images/flags/' . $lang['flag']) }}"
class="w-5 h-auto rounded-sm border border-base-300" alt="{{ $lang['name'] }}">
{{ $lang['name'] }}
</span>
@endforeach
</button>
{{-- Opciones --}}
<ul x-show="open" x-transition x-cloak
class="absolute z-50 mt-1 w-full bg-base-100 border border-base-300 rounded-box shadow-lg p-1">
@foreach($languages as $code => $lang)
<li>
<button type="button"
@click="$wire.set('locale', '{{ $code }}'); open = false"
class="w-full flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-base-200 text-left"
:class="$wire.locale === '{{ $code }}' ? 'bg-base-200 font-medium' : ''">
<img src="{{ asset('images/flags/' . $lang['flag']) }}"
class="w-5 h-auto rounded-sm border border-base-300" alt="{{ $lang['name'] }}">
{{ $lang['name'] }}
</button>
</li>
@endforeach
</ul>
</div>
@error('locale') <p class="text-error text-xs mt-1">{{ $message }}</p> @enderror
</div>
</div>
</div>
{{-- ══════════════════════════════════════════════════════════