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:
@@ -36,6 +36,9 @@ class UserForm extends Component
|
||||
// Permisos
|
||||
public string $formRole = '';
|
||||
|
||||
// Preferencias
|
||||
public string $locale = 'es';
|
||||
|
||||
// Notas
|
||||
public string $notes = '';
|
||||
|
||||
@@ -43,6 +46,12 @@ class UserForm extends Component
|
||||
public $roles;
|
||||
public $companies;
|
||||
|
||||
/** Idiomas disponibles (código => nombre + archivo de bandera). */
|
||||
public array $languages = [
|
||||
'es' => ['name' => 'Español', 'flag' => 'es.svg'],
|
||||
'en' => ['name' => 'English', 'flag' => 'gb.svg'],
|
||||
];
|
||||
|
||||
public function mount(?User $user = null): void
|
||||
{
|
||||
abort_unless(Auth::user()->can('create users') || Auth::user()->can('edit users'), 403);
|
||||
@@ -65,6 +74,7 @@ class UserForm extends Component
|
||||
$this->email = $user->email;
|
||||
$this->notes = $user->notes ?? '';
|
||||
$this->formRole = $user->roles->first()?->name ?? $this->formRole;
|
||||
$this->locale = $user->locale ?? $this->locale;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +93,7 @@ class UserForm extends Component
|
||||
'phone' => 'nullable|string|max:30',
|
||||
'email' => "required|email|max:255|unique:users,email,{$id}",
|
||||
'formRole' => 'required|exists:roles,name',
|
||||
'locale' => 'required|in:' . implode(',', array_keys($this->languages)),
|
||||
];
|
||||
|
||||
if (!$this->user) {
|
||||
@@ -103,6 +114,7 @@ class UserForm extends Component
|
||||
'companyId' => 'empresa',
|
||||
'formPassword'=> 'contraseña',
|
||||
'formRole' => 'rol',
|
||||
'locale' => 'idioma',
|
||||
];
|
||||
|
||||
public function copyCompanyAddress(): void
|
||||
@@ -139,6 +151,7 @@ class UserForm extends Component
|
||||
'phone' => $this->phone ?: null,
|
||||
'email' => $this->email,
|
||||
'notes' => $this->notes ?: null,
|
||||
'locale' => $this->locale,
|
||||
];
|
||||
|
||||
if ($this->formPassword !== '') {
|
||||
|
||||
@@ -25,6 +25,7 @@ class User extends Authenticatable
|
||||
'email', 'password',
|
||||
'status', 'valid_from', 'valid_until',
|
||||
'company_id', 'phone', 'address', 'notes',
|
||||
'locale',
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user