23bfc93f1c
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
378 lines
23 KiB
HTML
378 lines
23 KiB
HTML
{# Pannello utenti: incluso nella tab «Utenti» di Impostazioni (#50) #}
|
|
<script>window.__users = {{ users|tojson }};</script>
|
|
|
|
<div x-data="userManagement(window.__users)">
|
|
|
|
<!-- Toolbar -->
|
|
<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 mb-6">
|
|
<!-- Search -->
|
|
<div class="relative w-full sm:w-80">
|
|
<svg class="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-secondary)]" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
|
|
</svg>
|
|
<input type="text" x-model="search"
|
|
placeholder="{{ _('Cerca utente...') }}"
|
|
class="w-full pl-10 pr-4 py-2 rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)]
|
|
text-sm text-[var(--text-primary)] placeholder-[var(--text-secondary)]
|
|
focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary transition-colors">
|
|
</div>
|
|
|
|
<!-- New User Button -->
|
|
<button @click="openCreateModal()"
|
|
class="flex items-center gap-2 px-4 py-2 bg-primary text-white text-sm font-medium rounded-lg
|
|
hover:bg-primary-700 transition-colors shadow-sm">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4"/>
|
|
</svg>
|
|
{{ _('Nuovo Utente') }}
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Users Table -->
|
|
<div class="bg-[var(--bg-card)] rounded-xl border border-[var(--border-color)] shadow-sm overflow-hidden">
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full">
|
|
<thead>
|
|
<tr class="border-b border-[var(--border-color)] bg-[var(--bg-secondary)]">
|
|
<th class="text-left px-4 py-3 text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider">{{ _('Username') }}</th>
|
|
<th class="text-left px-4 py-3 text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider hidden sm:table-cell">{{ _('Nome Visualizzato') }}</th>
|
|
<th class="text-left px-4 py-3 text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider hidden md:table-cell">{{ _('Email') }}</th>
|
|
<th class="text-left px-4 py-3 text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider">{{ _('Ruoli') }}</th>
|
|
<th class="text-center px-4 py-3 text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider">{{ _('Stato') }}</th>
|
|
<th class="text-right px-4 py-3 text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider">{{ _('Azioni') }}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-[var(--border-color)]">
|
|
<template x-for="user in filteredUsers" :key="user.id">
|
|
<tr class="hover:bg-[var(--bg-secondary)] transition-colors cursor-pointer"
|
|
@click="openEditModal(user)">
|
|
<td class="px-4 py-3">
|
|
<div class="flex items-center gap-2">
|
|
<div class="w-8 h-8 rounded-full bg-primary/10 border border-primary/20 flex items-center justify-center text-primary font-semibold text-xs"
|
|
x-text="user.display_name ? user.display_name[0].toUpperCase() : user.username[0].toUpperCase()"></div>
|
|
<div>
|
|
<span class="text-sm font-medium text-[var(--text-primary)]" x-text="user.username"></span>
|
|
<template x-if="user.is_admin">
|
|
<span class="ml-1.5 inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-semibold bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300">Admin</span>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td class="px-4 py-3 text-sm text-[var(--text-secondary)] hidden sm:table-cell" x-text="user.display_name"></td>
|
|
<td class="px-4 py-3 text-sm text-[var(--text-secondary)] hidden md:table-cell" x-text="user.email || '-'"></td>
|
|
<td class="px-4 py-3">
|
|
<div class="flex flex-wrap gap-1">
|
|
<template x-for="role in user.roles" :key="role">
|
|
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[11px] font-medium"
|
|
:class="{
|
|
'bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300': role === 'Maker',
|
|
'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300': role === 'MeasurementTec',
|
|
'bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300': role === 'Metrologist',
|
|
'bg-orange-100 dark:bg-orange-900/30 text-orange-700 dark:text-orange-300': role === 'Supervisor'
|
|
}"
|
|
x-text="role"></span>
|
|
</template>
|
|
<template x-if="!user.roles || user.roles.length === 0">
|
|
<span class="text-xs text-[var(--text-secondary)]">-</span>
|
|
</template>
|
|
</div>
|
|
</td>
|
|
<td class="px-4 py-3 text-center">
|
|
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[11px] font-medium"
|
|
:class="user.active
|
|
? 'bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300'
|
|
: 'bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-300'"
|
|
x-text="user.active ? {{ _('Attivo')|tojson_attr }} : {{ _('Disattivato')|tojson_attr }}"></span>
|
|
</td>
|
|
<td class="px-4 py-3 text-right" @click.stop>
|
|
<div class="flex items-center justify-end gap-1">
|
|
<button @click="openEditModal(user)" class="p-1.5 rounded-lg text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20 transition-colors" :title="{{ _('Modifica')|tojson_attr }}">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
|
|
</svg>
|
|
</button>
|
|
<!-- #51: reset password dall'admin -->
|
|
<button @click="openReset(user)" class="p-1.5 rounded-lg text-[var(--text-secondary)] hover:text-primary hover:bg-primary-50 dark:hover:bg-primary-900/20 transition-colors" :title="{{ _('Reset password')|tojson_attr }}">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"/>
|
|
</svg>
|
|
</button>
|
|
<button @click="toggleActive(user)" class="p-1.5 rounded-lg transition-colors"
|
|
:class="user.active
|
|
? 'text-[var(--text-secondary)] hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20'
|
|
: 'text-[var(--text-secondary)] hover:text-emerald-600 hover:bg-emerald-50 dark:hover:bg-emerald-900/20'"
|
|
:title="user.active ? {{ _('Disattiva')|tojson_attr }} : {{ _('Riattiva')|tojson_attr }}">
|
|
<svg x-show="user.active" class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636"/>
|
|
</svg>
|
|
<svg x-show="!user.active" x-cloak class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</template>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Empty State -->
|
|
<template x-if="filteredUsers.length === 0">
|
|
<div class="px-6 py-12 text-center">
|
|
<svg class="w-12 h-12 mx-auto text-[var(--text-secondary)] opacity-40" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z"/>
|
|
</svg>
|
|
<p class="mt-3 text-sm text-[var(--text-secondary)]">{{ _('Nessun utente trovato') }}</p>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
|
|
<!-- Count -->
|
|
<div class="mt-3 text-xs text-[var(--text-secondary)]">
|
|
<span x-text="filteredUsers.length"></span> {{ _('utenti') }}
|
|
</div>
|
|
|
|
<!-- Modal: Create / Edit User -->
|
|
<div x-show="showModal" x-cloak
|
|
class="fixed inset-0 z-50 flex items-center justify-center p-4"
|
|
@keydown.escape.window="closeModal()">
|
|
<!-- Backdrop -->
|
|
<div class="absolute inset-0 bg-black/50" @click="closeModal()"></div>
|
|
|
|
<!-- Modal Content -->
|
|
<div x-show="showModal"
|
|
x-transition:enter="transition ease-out duration-200"
|
|
x-transition:enter-start="opacity-0 scale-95"
|
|
x-transition:enter-end="opacity-100 scale-100"
|
|
x-transition:leave="transition ease-in duration-150"
|
|
x-transition:leave-start="opacity-100 scale-100"
|
|
x-transition:leave-end="opacity-0 scale-95"
|
|
class="relative bg-[var(--bg-card)] rounded-xl border border-[var(--border-color)] shadow-xl w-full max-w-lg max-h-[90vh] overflow-y-auto">
|
|
|
|
<!-- Modal Header -->
|
|
<div class="flex items-center justify-between px-6 py-4 border-b border-[var(--border-color)]">
|
|
<h2 class="text-lg font-semibold text-[var(--text-primary)]"
|
|
x-text="isEditing ? {{ _('Modifica Utente')|tojson_attr }} : {{ _('Nuovo Utente')|tojson_attr }}"></h2>
|
|
<button @click="closeModal()" class="p-1 rounded-lg text-[var(--text-secondary)] hover:bg-[var(--bg-secondary)] transition-colors">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Modal Body -->
|
|
<div class="px-6 py-4 space-y-4">
|
|
<!-- Username -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-[var(--text-primary)] mb-1">{{ _('Username') }}</label>
|
|
<input type="text" x-model="form.username"
|
|
:disabled="isEditing"
|
|
:class="isEditing ? 'opacity-50 cursor-not-allowed' : ''"
|
|
class="w-full px-3 py-2 rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)]
|
|
text-sm text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary transition-colors"
|
|
placeholder="{{ _('Username') }}">
|
|
<template x-if="isEditing">
|
|
<p class="mt-1 text-xs text-[var(--text-secondary)]">{{ _('Il nome utente non può essere modificato') }}</p>
|
|
</template>
|
|
</div>
|
|
|
|
<!-- Display Name -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-[var(--text-primary)] mb-1">{{ _('Nome Visualizzato') }}</label>
|
|
<input type="text" x-model="form.display_name"
|
|
class="w-full px-3 py-2 rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)]
|
|
text-sm text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary transition-colors"
|
|
placeholder="{{ _('Nome Visualizzato') }}">
|
|
</div>
|
|
|
|
<!-- Email -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-[var(--text-primary)] mb-1">{{ _('Email') }}</label>
|
|
<input type="email" x-model="form.email"
|
|
class="w-full px-3 py-2 rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)]
|
|
text-sm text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary transition-colors"
|
|
placeholder="email@example.com">
|
|
</div>
|
|
|
|
<!-- Password -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-[var(--text-primary)] mb-1">
|
|
{{ _('Password') }}
|
|
<template x-if="isEditing">
|
|
<span class="font-normal text-[var(--text-secondary)]"> ({{ _('lascia vuoto per non modificare') }})</span>
|
|
</template>
|
|
</label>
|
|
<input type="password" x-model="form.password"
|
|
class="w-full px-3 py-2 rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)]
|
|
text-sm text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary transition-colors"
|
|
:placeholder="isEditing ? {{ _('Nuova password (opzionale)')|tojson_attr }} : {{ _('Password')|tojson_attr }}"
|
|
minlength="6">
|
|
</div>
|
|
|
|
<!-- Roles -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-[var(--text-primary)] mb-2">{{ _('Ruoli') }}</label>
|
|
<div class="flex flex-wrap gap-3">
|
|
<label class="flex items-center gap-2 cursor-pointer">
|
|
<input type="checkbox" x-model="form.roles" value="Maker"
|
|
class="rounded border-[var(--border-color)] text-primary focus:ring-primary/30">
|
|
<span class="text-sm text-[var(--text-primary)]">Maker</span>
|
|
</label>
|
|
<label class="flex items-center gap-2 cursor-pointer">
|
|
<input type="checkbox" x-model="form.roles" value="MeasurementTec"
|
|
class="rounded border-[var(--border-color)] text-primary focus:ring-primary/30">
|
|
<span class="text-sm text-[var(--text-primary)]">MeasurementTec</span>
|
|
</label>
|
|
<label class="flex items-center gap-2 cursor-pointer">
|
|
<input type="checkbox" x-model="form.roles" value="Metrologist"
|
|
class="rounded border-[var(--border-color)] text-primary focus:ring-primary/30">
|
|
<span class="text-sm text-[var(--text-primary)]">Metrologist</span>
|
|
</label>
|
|
<label class="flex items-center gap-2 cursor-pointer">
|
|
<input type="checkbox" x-model="form.roles" value="Supervisor"
|
|
class="rounded border-[var(--border-color)] text-primary focus:ring-primary/30">
|
|
<span class="text-sm text-[var(--text-primary)]">{{ _('Supervisor (capoturno)') }}</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Admin + Preferences Row -->
|
|
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
|
<!-- Is Admin -->
|
|
<div>
|
|
<label class="flex items-center gap-2 cursor-pointer">
|
|
<input type="checkbox" x-model="form.is_admin"
|
|
class="rounded border-[var(--border-color)] text-primary focus:ring-primary/30">
|
|
<span class="text-sm font-medium text-[var(--text-primary)]">{{ _('Amministratore') }}</span>
|
|
</label>
|
|
</div>
|
|
|
|
<!-- Language -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-[var(--text-primary)] mb-1">{{ _('Lingua') }}</label>
|
|
<select x-model="form.language_pref"
|
|
class="w-full px-3 py-2 rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)]
|
|
text-sm text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary transition-colors">
|
|
<option value="it">{{ _('Italiano') }}</option>
|
|
<option value="en">{{ _('English') }}</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Theme -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-[var(--text-primary)] mb-1">{{ _('Tema') }}</label>
|
|
<select x-model="form.theme_pref"
|
|
class="w-full px-3 py-2 rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)]
|
|
text-sm text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary transition-colors">
|
|
<option value="light">{{ _('Chiaro') }}</option>
|
|
<option value="dark">{{ _('Scuro') }}</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Error Message -->
|
|
<template x-if="errorMsg">
|
|
<div class="px-3 py-2 rounded-lg bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800">
|
|
<p class="text-sm text-red-700 dark:text-red-300" x-text="errorMsg"></p>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
|
|
<!-- Modal Footer -->
|
|
<div class="flex items-center justify-end gap-3 px-6 py-4 border-t border-[var(--border-color)]">
|
|
<button @click="closeModal()"
|
|
class="px-4 py-2 text-sm font-medium text-[var(--text-secondary)] rounded-lg
|
|
hover:bg-[var(--bg-secondary)] transition-colors">
|
|
{{ _('Annulla') }}
|
|
</button>
|
|
<button @click="saveUser()"
|
|
:disabled="saving"
|
|
class="px-4 py-2 bg-primary text-white text-sm font-medium rounded-lg
|
|
hover:bg-primary-700 transition-colors shadow-sm disabled:opacity-50">
|
|
<span x-show="!saving" x-text="isEditing ? {{ _('Salva Modifiche')|tojson_attr }} : {{ _('Crea Utente')|tojson_attr }}"></span>
|
|
<span x-show="saving" x-cloak>{{ _('Salvataggio...') }}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Confirm Toggle Modal -->
|
|
<div x-show="showToggleConfirm" x-cloak
|
|
class="fixed inset-0 z-50 flex items-center justify-center p-4">
|
|
<div class="absolute inset-0 bg-black/50" @click="showToggleConfirm = false"></div>
|
|
<div x-show="showToggleConfirm"
|
|
x-transition
|
|
class="relative bg-[var(--bg-card)] rounded-xl border border-[var(--border-color)] shadow-xl w-full max-w-sm p-6">
|
|
<h3 class="text-lg font-semibold text-[var(--text-primary)] mb-2"
|
|
x-text="toggleUser?.active ? {{ _('Conferma Disattivazione')|tojson_attr }} : {{ _('Conferma Riattivazione')|tojson_attr }}"></h3>
|
|
<p class="text-sm text-[var(--text-secondary)] mb-4">
|
|
<span x-text="toggleUser?.active
|
|
? "{{ _('Sei sicuro di voler disattivare l\'utente') }}"
|
|
: "{{ _('Sei sicuro di voler riattivare l\'utente') }}""></span>
|
|
<strong x-text="toggleUser?.username"></strong>?
|
|
</p>
|
|
<div class="flex justify-end gap-3">
|
|
<button @click="showToggleConfirm = false"
|
|
class="px-4 py-2 text-sm font-medium text-[var(--text-secondary)] rounded-lg hover:bg-[var(--bg-secondary)] transition-colors">
|
|
{{ _('Annulla') }}
|
|
</button>
|
|
<button @click="confirmToggle()"
|
|
:disabled="saving"
|
|
class="px-4 py-2 text-sm font-medium text-white rounded-lg shadow-sm disabled:opacity-50 transition-colors"
|
|
:class="toggleUser?.active ? 'bg-red-600 hover:bg-red-700' : 'bg-emerald-600 hover:bg-emerald-700'">
|
|
<span x-text="toggleUser?.active ? {{ _('Disattiva')|tojson_attr }} : {{ _('Riattiva')|tojson_attr }}"></span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- #51: Modal reset password (la password attuale non si mostra mai) -->
|
|
<div x-show="showReset" x-cloak
|
|
class="fixed inset-0 z-50 flex items-center justify-center p-4"
|
|
@keydown.escape.window="closeReset()">
|
|
<div class="absolute inset-0 bg-black/50" @click="closeReset()"></div>
|
|
<div class="relative bg-[var(--bg-card)] rounded-xl border border-[var(--border-color)] shadow-xl w-full max-w-md p-6">
|
|
<h3 class="text-lg font-semibold text-[var(--text-primary)] mb-2">
|
|
{{ _('Reset password') }}: <span x-text="resetUser?.username"></span>
|
|
</h3>
|
|
<p class="text-sm text-[var(--text-secondary)] mb-4">
|
|
{{ _('Le sessioni aperte dell\'utente verranno chiuse e dovrà accedere con la nuova password.') }}
|
|
</p>
|
|
<template x-if="!resetDone">
|
|
<div>
|
|
<label class="block text-sm font-medium text-[var(--text-primary)] mb-1">{{ _('Nuova password (minimo 8 caratteri)') }}</label>
|
|
<div class="flex gap-2">
|
|
<input type="text" x-model="resetPw" autocomplete="off"
|
|
class="flex-1 px-3 py-2 rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)] text-sm font-mono text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary">
|
|
<button @click="generateResetPw()" type="button"
|
|
class="px-3 py-2 text-sm font-medium rounded-lg border border-[var(--border-color)] text-[var(--text-primary)] hover:bg-[var(--bg-secondary)]">
|
|
{{ _('Genera') }}
|
|
</button>
|
|
</div>
|
|
<template x-if="resetError">
|
|
<p class="mt-2 text-sm text-red-600" x-text="resetError"></p>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
<template x-if="resetDone">
|
|
<div class="px-3 py-2 rounded-lg bg-emerald-50 dark:bg-emerald-900/20 border border-emerald-200 dark:border-emerald-800">
|
|
<p class="text-sm text-emerald-700 dark:text-emerald-300">{{ _('Password cambiata. Annotala ora: non verrà mostrata di nuovo.') }}</p>
|
|
<p class="mt-1 text-base font-mono font-semibold text-[var(--text-primary)] select-all" x-text="resetPw"></p>
|
|
</div>
|
|
</template>
|
|
<div class="flex justify-end gap-3 mt-5">
|
|
<button @click="closeReset()"
|
|
class="px-4 py-2 text-sm font-medium text-[var(--text-secondary)] rounded-lg hover:bg-[var(--bg-secondary)]">
|
|
<span x-text="resetDone ? {{ _('Chiudi')|tojson_attr }} : {{ _('Annulla')|tojson_attr }}"></span>
|
|
</button>
|
|
<button x-show="!resetDone" @click="confirmReset()" :disabled="saving"
|
|
class="px-4 py-2 bg-primary text-white text-sm font-medium rounded-lg hover:bg-primary-700 shadow-sm disabled:opacity-50">
|
|
{{ _('Imposta password') }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|