feat: Controllo accessi RFID completo con gestione sessioni

- Aggiunto supporto multi-pattern RFID (US/IT layout)
- Implementata invalidazione sessioni al restart del server
- Schermata "badge non trovato" con countdown 30s
- Notifica quando badge validatore passato senza utente
- Database aggiornato con badge reali di test
- Layout ottimizzato per tablet orizzontale
- Banner NumLock per desktop
- Toggle visibilità password
- Carosello benvenuto multilingua (10 lingue)
- Pagina debug RFID (/debug)
This commit is contained in:
2026-01-17 20:06:50 +01:00
parent 21b509c6ba
commit e68f299feb
48 changed files with 3625 additions and 2445 deletions

View File

@@ -1,88 +1,78 @@
/**
* Success Modal - Focolari Voting System
* Modal fullscreen per conferma ingresso
* Modal fullscreen per conferma ingresso con carosello multilingua
*/
import { Modal } from '../components';
import {Modal, WelcomeCarousel} from '../components';
interface SuccessModalProps {
isOpen: boolean;
onClose: () => void;
welcomeMessage: string;
userName?: string;
isOpen: boolean;
onClose: () => void;
userName?: string;
}
export function SuccessModal({
isOpen,
onClose,
welcomeMessage,
userName
}: SuccessModalProps) {
return (
<Modal
isOpen={isOpen}
onClose={onClose}
variant="success"
autoCloseMs={5000}
fullscreen
>
<div className="text-center text-white p-8">
{/* Success Icon */}
<div className="mb-8">
<div className="inline-flex items-center justify-center w-32 h-32 rounded-full bg-white/20 animate-pulse-glow">
<svg
className="w-20 h-20 text-white"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={3}
d="M5 13l4 4L19 7"
/>
</svg>
</div>
</div>
isOpen,
onClose,
userName
}: SuccessModalProps) {
return (
<Modal
isOpen={isOpen}
onClose={onClose}
variant="success"
autoCloseMs={5000}
fullscreen
>
<div className="flex flex-col items-center justify-center min-h-screen p-8">
{/* Success Icon */}
<div className="mb-8">
<div
className="inline-flex items-center justify-center w-32 h-32 rounded-full bg-white/20 animate-pulse-glow">
<svg
className="w-20 h-20 text-white"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={3}
d="M5 13l4 4L19 7"
/>
</svg>
</div>
</div>
{/* User Name */}
{userName && (
<h2 className="text-4xl md:text-5xl font-bold mb-4 animate-slide-up">
{userName}
</h2>
)}
{/* Carosello Messaggi Benvenuto */}
<WelcomeCarousel userName={userName}/>
{/* Welcome Message */}
<h1 className="text-5xl md:text-7xl font-bold mb-8 animate-slide-up">
{welcomeMessage}
</h1>
{/* Sub text */}
<p className="text-2xl md:text-3xl text-white/80 mt-8 animate-fade-in">
Ingresso registrato con successo
</p>
{/* Sub text */}
<p className="text-2xl md:text-3xl opacity-80 animate-fade-in">
Ingresso registrato con successo
</p>
{/* Auto-close indicator */}
<div className="mt-12">
<div className="w-64 h-2 bg-white/30 rounded-full mx-auto overflow-hidden">
<div
className="h-full bg-white rounded-full"
style={{
animation: 'shrink 5s linear forwards',
}}
/>
</div>
<style>{`
{/* Auto-close indicator */}
<div className="mt-12 w-full max-w-md">
<div className="w-full h-2 bg-white/30 rounded-full overflow-hidden">
<div
className="h-full bg-white rounded-full"
style={{
animation: 'shrink 5s linear forwards',
}}
/>
</div>
<style>{`
@keyframes shrink {
from { width: 100%; }
to { width: 0%; }
}
`}</style>
</div>
</div>
</Modal>
);
</div>
</div>
</Modal>
);
}
export default SuccessModal;