Login Operatore con nome + PIN: elenco nomi, tastierino, route login-pin (#59)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,8 +26,50 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Login Form -->
|
||||
<form method="POST" action="{{ url_for('auth.login') }}" class="space-y-6">
|
||||
<div x-data="pinLogin()" x-init="init()">
|
||||
<!-- Vista Operatore: nome + PIN (#59) -->
|
||||
<div x-show="mode === 'pin'" x-cloak>
|
||||
<!-- Elenco nomi -->
|
||||
<div x-show="!selected">
|
||||
<p class="text-sm text-center text-[var(--text-secondary)] mb-4">{{ _('Chi sei?') }}</p>
|
||||
<div class="grid grid-cols-2 gap-3" id="pin-user-list">
|
||||
<template x-for="u in users" :key="u.id">
|
||||
<button type="button" @click="select(u)"
|
||||
class="btn btn-secondary min-h-[64px] text-base w-full" x-text="u.display_name"></button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Tastierino -->
|
||||
<div x-show="selected" id="pin-pad">
|
||||
<p class="text-center font-semibold mb-1" x-text="selected && selected.display_name"></p>
|
||||
<p class="text-sm text-center text-[var(--text-secondary)] mb-3">{{ _('Inserisci il PIN') }}</p>
|
||||
<div class="flex justify-center gap-3 mb-3" aria-hidden="true">
|
||||
<template x-for="i in 4" :key="i">
|
||||
<span class="h-4 w-4 rounded-full border-2 border-[var(--border-color)]"
|
||||
:class="pin.length >= i ? 'bg-primary-600 border-primary-600' : ''"></span>
|
||||
</template>
|
||||
</div>
|
||||
<p class="text-sm text-center text-red-600 min-h-[1.25rem] mb-2" role="alert" x-text="error"></p>
|
||||
<div class="grid grid-cols-3 gap-3 max-w-xs mx-auto">
|
||||
<template x-for="d in ['1','2','3','4','5','6','7','8','9']" :key="d">
|
||||
<button type="button" @click="press(d)" :disabled="busy"
|
||||
class="btn btn-secondary h-16 min-w-[64px] text-2xl" x-text="d"></button>
|
||||
</template>
|
||||
<button type="button" @click="back()" :disabled="busy"
|
||||
class="btn btn-secondary h-16 min-w-[64px] text-sm">{{ _('Indietro') }}</button>
|
||||
<button type="button" @click="press('0')" :disabled="busy"
|
||||
class="btn btn-secondary h-16 min-w-[64px] text-2xl">0</button>
|
||||
<button type="button" @click="del()" :disabled="busy"
|
||||
class="btn btn-secondary h-16 min-w-[64px] text-sm">{{ _('Cancella') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-6 text-center">
|
||||
<a href="#" @click.prevent="mode = 'password'" class="text-sm text-primary-600 hover:underline">{{ _('Accedi con password') }}</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Login Form (password: admin e chi non ha PIN) -->
|
||||
<form x-show="mode === 'password'" method="POST" action="{{ url_for('auth.login') }}" class="space-y-6">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<!-- Username -->
|
||||
<div>
|
||||
@@ -98,6 +140,11 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p class="mt-4 text-center" x-show="mode === 'password' && users.length" x-cloak>
|
||||
<a href="#" @click.prevent="mode = 'pin'" class="text-sm text-primary-600 hover:underline">{{ _('Accedi con PIN') }}</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Help Text -->
|
||||
<div class="mt-6 text-center">
|
||||
<p class="text-xs text-[var(--text-muted)]">
|
||||
@@ -115,3 +162,15 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
/* Configurazione e testi per pin-pad.js (#59) */
|
||||
window.TMF_PIN = {
|
||||
usersUrl: {{ url_for('auth.pin_users')|tojson }},
|
||||
loginUrl: {{ url_for('auth.login_pin')|tojson }},
|
||||
msgNet: {{ _('Errore di connessione al server')|tojson }}
|
||||
};
|
||||
</script>
|
||||
<script src="{{ url_for('static', filename='js/pin-pad.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user