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:
@@ -1,206 +1,150 @@
|
||||
# 🎯 Focolari Voting System - Guida Agente
|
||||
# 🗳️ Focolari Voting System - Welcome Agent
|
||||
|
||||
## Panoramica Progetto
|
||||
|
||||
**Nome:** Sistema Controllo Accessi "Focolari Voting System"
|
||||
**Committente:** Movimento dei Focolari
|
||||
**Scopo:** Gestione dei varchi di accesso per le assemblee di voto del Movimento.
|
||||
|
||||
### Contesto d'Uso
|
||||
|
||||
Il sistema funziona su **tablet Android** (via browser Chrome) posizionati ai varchi d'ingresso delle sale votazione. Ogni tablet è collegato a un **lettore RFID USB** che emula tastiera.
|
||||
Sistema di controllo accessi per le assemblee di voto del **Movimento dei Focolari**.
|
||||
Applicazione web ottimizzata per **tablet in orizzontale** che gestisce i varchi d'ingresso alle sale votazione tramite
|
||||
**lettori RFID USB** (emulano tastiera).
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Architettura
|
||||
## Stack Tecnologico
|
||||
|
||||
### Backend Mock
|
||||
|
||||
- **Python 3.11+** con **FastAPI**
|
||||
- **Pydantic** per validazione dati
|
||||
- **Uvicorn** come server ASGI
|
||||
- **Pipenv** per gestione dipendenze
|
||||
|
||||
### Frontend
|
||||
|
||||
- **React 18** + **TypeScript**
|
||||
- **Vite** come build tool
|
||||
- **Tailwind CSS 4** per styling
|
||||
- **React Router** per navigazione
|
||||
|
||||
---
|
||||
|
||||
## Struttura Progetto
|
||||
|
||||
```
|
||||
VotoFocolari/
|
||||
├── ai-prompts/ # Documentazione e piani di sviluppo
|
||||
├── backend-mock/ # Python FastAPI (server mock)
|
||||
│ ├── main.py # Entry point con argparse
|
||||
│ ├── Pipfile # Dipendenze pipenv
|
||||
│ ├── api/ # Routes FastAPI
|
||||
│ ├── schemas/ # Modelli Pydantic
|
||||
│ └── data/ # Dataset JSON (default, test)
|
||||
└── frontend/ # React + TypeScript + Vite + Tailwind
|
||||
├── dev.sh # Script di sviluppo (install, dev, server, ...)
|
||||
├── README.md
|
||||
├── ai-prompts/ # Documentazione sviluppo
|
||||
│ ├── 00-welcome-agent.md # Questo file
|
||||
│ ├── 01-backend-plan.md # Piano backend
|
||||
│ └── 02-frontend-plan.md # Piano frontend
|
||||
├── backend-mock/
|
||||
│ ├── main.py # Entry point con argparse
|
||||
│ ├── Pipfile # Dipendenze Python
|
||||
│ ├── api/routes.py # Endpoint API
|
||||
│ ├── schemas/models.py # Modelli Pydantic
|
||||
│ └── data/
|
||||
│ ├── users_default.json
|
||||
│ └── users_test.json
|
||||
└── frontend/
|
||||
├── package.json
|
||||
├── vite.config.ts
|
||||
└── src/
|
||||
├── App.tsx # State machine principale
|
||||
├── hooks/ # Custom hooks (RFID scanner)
|
||||
├── hooks/ # useRFIDScanner
|
||||
├── components/ # UI components
|
||||
├── screens/ # Schermate complete
|
||||
├── services/ # API layer
|
||||
├── types/ # TypeScript definitions
|
||||
└── tests/ # Test automatici use case
|
||||
├── screens/ # Schermate
|
||||
├── services/ # API client
|
||||
└── types/ # TypeScript types
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Stack Tecnologico
|
||||
## Funzionalità Principali
|
||||
|
||||
### Backend Mock
|
||||
- **Python 3.10+**
|
||||
- **FastAPI** - Framework web asincrono
|
||||
- **Uvicorn** - ASGI server
|
||||
- **Pydantic** - Validazione dati
|
||||
- **pipenv** - Gestione ambiente virtuale
|
||||
- **argparse** - Parametri CLI (porta, dataset)
|
||||
### Flusso Utente
|
||||
|
||||
### Frontend
|
||||
- **React 19** - UI Library
|
||||
- **TypeScript 5.9** - Type safety
|
||||
- **Vite 7** - Build tool
|
||||
- **Tailwind CSS 4** - Styling utility-first
|
||||
- **React Router** - Routing (/, /debug)
|
||||
- **Vitest** - Testing framework
|
||||
- **Design:** Ottimizzato per touch tablet
|
||||
1. **Login Validatore**: Passa badge + inserisci password → Sessione 30 min
|
||||
2. **Attesa Partecipante**: Schermata grande "Passa il badge"
|
||||
3. **Visualizzazione Utente**: Card con foto, nome, ruolo, stato ammissione
|
||||
4. **Conferma Ingresso**: Validatore ripassa il badge → Carosello benvenuto multilingua
|
||||
|
||||
### Gestione RFID
|
||||
|
||||
- **Multi-pattern**: Supporta layout tastiera US (`;?`) e IT (`ò_`)
|
||||
- **Timeout 2.5s**: Per scansioni accidentali
|
||||
- **ESC annulla**: Scansione in corso
|
||||
- **Enter handling**: Gestito automaticamente
|
||||
|
||||
### Sicurezza Sessioni
|
||||
|
||||
- Sessione salvata in localStorage
|
||||
- **Invalidazione automatica** se il server riparte
|
||||
- Timeout 30 minuti
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Design System
|
||||
## Comandi Rapidi
|
||||
|
||||
| Colore | Hex | Uso |
|
||||
|--------|-----|-----|
|
||||
| Blu Istituzionale | `#0072CE` | Colore primario, brand |
|
||||
| Arancio Accento | `#F5A623` | Azioni secondarie |
|
||||
| Giallo | `#FFD700` | Evidenze |
|
||||
| Verde Success | `#22C55E` | Conferme, ammesso |
|
||||
| Rosso Error | `#EF4444` | Errori, non ammesso |
|
||||
|
||||
---
|
||||
|
||||
## 📟 Logica RFID (CRITICA)
|
||||
|
||||
Il lettore RFID simula una tastiera. **Non possiamo distinguerlo dalla digitazione umana** in base alla velocità.
|
||||
|
||||
### Protocollo
|
||||
- **Formato:** `<start_sentinel><codice><end_sentinel>`
|
||||
- **Esempio US:** `;00012345?`
|
||||
- **Esempio IT:** `ò00012345_`
|
||||
|
||||
### Pattern Supportati
|
||||
```typescript
|
||||
const VALID_PATTERNS = [
|
||||
{ start: ';', end: '?' }, // Layout US
|
||||
{ start: 'ò', end: '_' }, // Layout IT
|
||||
];
|
||||
```
|
||||
|
||||
### Strategia
|
||||
1. Ascolto globale `keydown`
|
||||
2. Se ricevo un carattere `start` → avvio buffer + timeout (2.5s)
|
||||
3. Accumulo caratteri nel buffer
|
||||
4. Se ricevo il corretto `end` → emetto codice pulito
|
||||
5. Se timeout scade → scarto buffer
|
||||
|
||||
---
|
||||
|
||||
## 🔄 State Machine Applicativa
|
||||
|
||||
```
|
||||
LOADING → WAITING_VALIDATOR → [badge validatore]
|
||||
→ VALIDATOR_PASSWORD → [password OK]
|
||||
→ GATE_ACTIVE → [badge partecipante]
|
||||
→ SHOWING_USER → [badge validatore]
|
||||
→ SUCCESS_MODAL (5s, carosello multilingua) → GATE_ACTIVE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🌍 Messaggi Benvenuto (Frontend)
|
||||
|
||||
Il backend risponde in modo **asettico** (solo `success: true`).
|
||||
Il frontend mostra un **carosello automatico** di messaggi multilingua:
|
||||
|
||||
- Italiano, English, Français, Deutsch, Español, Português, 中文, 日本語
|
||||
|
||||
Scorrimento ogni ~2 secondi, durata modale 5 secondi.
|
||||
|
||||
---
|
||||
|
||||
## 📁 File Chiave
|
||||
|
||||
| File | Descrizione |
|
||||
|------|-------------|
|
||||
| `backend-mock/main.py` | Entry point con argparse |
|
||||
| `backend-mock/api/routes.py` | Definizione endpoint |
|
||||
| `backend-mock/schemas/models.py` | Modelli Pydantic |
|
||||
| `backend-mock/data/*.json` | Dataset utenti |
|
||||
| `frontend/src/hooks/useRFIDScanner.ts` | Cuore del sistema - gestione lettore |
|
||||
| `frontend/src/App.tsx` | State machine e orchestrazione |
|
||||
| `frontend/src/components/WelcomeCarousel.tsx` | Carosello multilingua |
|
||||
| `frontend/src/screens/DebugScreen.tsx` | Diagnostica RFID |
|
||||
| `frontend/src/tests/` | Test automatici use case |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Backend
|
||||
```bash
|
||||
cd backend-mock
|
||||
pipenv install
|
||||
pipenv run python main.py # Default
|
||||
pipenv run python main.py -p 9000 # Porta custom
|
||||
pipenv run python main.py -d data/test.json # Dataset test
|
||||
```
|
||||
# Setup iniziale
|
||||
./dev.sh install
|
||||
|
||||
### Frontend
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
npm run dev # Sviluppo
|
||||
npm run test # Test suite
|
||||
npm run test:ui # Test con UI
|
||||
# Sviluppo (hot reload)
|
||||
./dev.sh dev
|
||||
# Frontend: http://localhost:5173
|
||||
# Backend: http://localhost:8000
|
||||
|
||||
# Produzione locale
|
||||
./dev.sh server
|
||||
# App completa: http://localhost:8000
|
||||
|
||||
# Debug RFID
|
||||
# Vai a http://localhost:8000/debug
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Test Automatici
|
||||
## Badge di Test
|
||||
|
||||
Suite di test per validazione use case:
|
||||
| Badge | Nome | Ruolo | Ammesso |
|
||||
|--------------|----------------|---------|---------------|
|
||||
| `0008988288` | Marco Bianchi | Votante | ✅ |
|
||||
| `0007399575` | Laura Rossi | Votante | ✅ |
|
||||
| `0000514162` | Giuseppe Verdi | Tecnico | ❌ |
|
||||
| `0006478281` | - | - | ⚠️ Non nel DB |
|
||||
|
||||
| Test | Descrizione |
|
||||
|------|-------------|
|
||||
| UC01 | Login validatore |
|
||||
| UC02 | Accesso partecipante ammesso |
|
||||
| UC03 | Accesso negato |
|
||||
| UC04 | Timeout sessione |
|
||||
| UC05 | Cambio rapido badge |
|
||||
| UC06 | Pattern RFID multipli |
|
||||
**Password validatore:** `focolari`
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Debug
|
||||
## Dove Trovare Cosa
|
||||
|
||||
### Console Browser
|
||||
Tutti i log sono prefissati:
|
||||
- `[RFID]` - Eventi lettore badge
|
||||
- `[FLOW]` - Transizioni stato
|
||||
- `[API]` - Chiamate HTTP
|
||||
|
||||
### Pagina Debug (`/debug`)
|
||||
Accesso: logo cliccabile 5 volte.
|
||||
Mostra in tempo reale:
|
||||
- Ultimi 20 tasti premuti
|
||||
- Stato scanner (idle/scanning)
|
||||
- Buffer corrente
|
||||
- Pattern attivo
|
||||
| Cosa cerchi | Dove guardare |
|
||||
|----------------------------|----------------------------------------|
|
||||
| Logica flusso applicazione | `frontend/src/App.tsx` |
|
||||
| Hook lettura RFID | `frontend/src/hooks/useRFIDScanner.ts` |
|
||||
| Chiamate API | `frontend/src/services/api.ts` |
|
||||
| Endpoint backend | `backend-mock/api/routes.py` |
|
||||
| Dati mock utenti | `backend-mock/data/users_default.json` |
|
||||
| Configurazione Vite | `frontend/vite.config.ts` |
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Note Importanti
|
||||
## Note Importanti
|
||||
|
||||
1. **Badge Validatore:** `999999` con password `focolari`
|
||||
2. **Sessione:** 30 minuti di timeout, salvata in localStorage
|
||||
3. **Timeout utente:** 60 secondi sulla schermata decisione
|
||||
4. **Multi-layout:** Il sistema supporta RFID su tastiera US e IT
|
||||
5. **Backend asettico:** Nessun messaggio multilingua dal server
|
||||
6. **Git:** Il progetto sfrutta un Repository per versionare e sviluppare, ma solo l'utente può eseguire comandi git, eccetto se richiesto diversamente, l'agente può solo chiedere di eseguire o suggerire cosa fare, ma mai prendere iniziative
|
||||
1. **Layout Tastiera**: Il lettore RFID potrebbe inviare caratteri diversi in base al layout OS. La pagina `/debug`
|
||||
aiuta a diagnosticare.
|
||||
|
||||
2. **Server Restart**: Quando il server riparte, tutte le sessioni frontend vengono invalidate (controllato via
|
||||
`server_start_time`).
|
||||
|
||||
3. **Badge Validatore**: Qualsiasi badge può diventare validatore se la password è corretta. Il badge viene memorizzato
|
||||
nella sessione.
|
||||
|
||||
4. **NumLock**: Su desktop, viene mostrato un banner per ricordare di attivare NumLock.
|
||||
|
||||
---
|
||||
|
||||
## 📚 Documentazione Correlata
|
||||
## TODO (da concordare con committenti)
|
||||
|
||||
- `01-backend-plan.md` - Piano sviluppo backend
|
||||
- `02-frontend-plan.md` - Piano sviluppo frontend
|
||||
- [ ] Verificare se il badge validatore debba essere validato anche lato server
|
||||
- [ ] Test automatici E2E per regression detection
|
||||
|
||||
@@ -13,7 +13,6 @@ Struttura modulare con separazione tra API, modelli e dati.
|
||||
backend-mock/
|
||||
├── main.py # Entry point con argparse
|
||||
├── Pipfile # Dipendenze pipenv
|
||||
├── requirements.txt # Backup dipendenze
|
||||
├── .gitignore
|
||||
├── api/
|
||||
│ ├── __init__.py
|
||||
@@ -22,7 +21,7 @@ backend-mock/
|
||||
│ ├── __init__.py
|
||||
│ └── models.py # Modelli Pydantic
|
||||
└── data/
|
||||
├── users_default.json # Dataset utenti default
|
||||
├── users_default.json # Dataset utenti default (badge reali)
|
||||
└── users_test.json # Dataset per test
|
||||
```
|
||||
|
||||
@@ -35,36 +34,40 @@ backend-mock/
|
||||
- [x] Creare cartella `backend-mock/`
|
||||
- [x] Creare `Pipfile` per pipenv
|
||||
- [x] Configurare `.gitignore` per Python
|
||||
- [ ] Creare struttura cartelle (`api/`, `schemas/`, `data/`)
|
||||
- [x] Creare struttura cartelle (`api/`, `schemas/`, `data/`)
|
||||
|
||||
### 2. Modelli Pydantic (`schemas/models.py`)
|
||||
|
||||
- [x] `LoginRequest` - badge + password
|
||||
- [x] `EntryRequest` - user_badge + validator_password
|
||||
- [x] `UserResponse` - dati utente + warning opzionale
|
||||
- [x] `RoomInfoResponse` - nome sala + meeting_id
|
||||
- [x] `RoomInfoResponse` - nome sala + meeting_id + **server_start_time**
|
||||
- [x] `LoginResponse` - success + message + token
|
||||
- [x] `EntryResponse` - success + message (SENZA welcome_message)
|
||||
- [ ] **DA FARE:** Spostare modelli in file dedicato
|
||||
- [x] Spostare modelli in file dedicato
|
||||
|
||||
### 3. Dati Mock (`data/*.json`)
|
||||
|
||||
- [x] Costanti validatore (badge `999999`, password `focolari`)
|
||||
- [x] Lista utenti mock (7 utenti con dati realistici)
|
||||
- [x] Mix di ruoli: Votante, Tecnico, Ospite
|
||||
- [x] Alcuni con `ammesso: false` per test
|
||||
- [x] URL foto placeholder (randomuser.me)
|
||||
- [ ] **DA FARE:** Estrarre dati in file JSON separato
|
||||
- [ ] **DA FARE:** Creare dataset alternativo per test
|
||||
- [ ] **DA FARE:** Caricare dati dinamicamente all'avvio
|
||||
- [x] Password validatore (solo password, badge gestito dal frontend)
|
||||
- [x] Lista utenti mock con **badge reali**:
|
||||
- `0008988288` - Marco Bianchi (Votante, ammesso)
|
||||
- `0007399575` - Laura Rossi (Votante, ammessa)
|
||||
- `0000514162` - Giuseppe Verdi (Tecnico, NON ammesso)
|
||||
- `0006478281` - **NON nel DB** (per test "non trovato")
|
||||
- [x] Estrarre dati in file JSON separato
|
||||
- [x] Creare dataset alternativo per test (`users_test.json`)
|
||||
- [x] Caricare dati dinamicamente all'avvio
|
||||
|
||||
**Nota:** I messaggi di benvenuto multilingua sono stati **RIMOSSI** dal backend.
|
||||
Il frontend gestirà autonomamente la visualizzazione internazionale con carosello.
|
||||
**Nota:** I messaggi di benvenuto multilingua sono gestiti dal frontend con carosello.
|
||||
|
||||
**TODO (da concordare con committenti):**
|
||||
|
||||
- Valutare se `login-validate` debba ricevere e verificare anche il badge del validatore
|
||||
|
||||
### 4. Routes API (`api/routes.py`)
|
||||
|
||||
- [x] `GET /info-room` - info sala
|
||||
- [x] `POST /login-validate` - autenticazione validatore
|
||||
- [x] `GET /info-room` - info sala + **server_start_time** per invalidare sessioni
|
||||
- [x] `POST /login-validate` - verifica solo password validatore
|
||||
- [x] `GET /anagrafica/{badge_code}` - ricerca utente
|
||||
- [x] Pulizia caratteri sentinel dal badge
|
||||
- [x] Confronto con e senza zeri iniziali
|
||||
@@ -73,27 +76,25 @@ Il frontend gestirà autonomamente la visualizzazione internazionale con carosel
|
||||
- [x] Verifica password validatore
|
||||
- [x] Verifica utente ammesso
|
||||
- [x] Risposta asettica (solo success + message)
|
||||
- [ ] **DA FARE:** Spostare routes in file dedicato
|
||||
- [x] Spostare routes in file dedicato
|
||||
|
||||
### 5. Entry Point (`main.py`)
|
||||
|
||||
- [x] Blocco `if __name__ == "__main__"`
|
||||
- [x] Configurazione uvicorn (host, port)
|
||||
- [x] Messaggi console all'avvio
|
||||
- [ ] **DA FARE:** Implementare argparse con opzioni:
|
||||
- `--port` / `-p` : porta server (default: 8000)
|
||||
- `--data` / `-d` : path file JSON dati (default: `data/users_default.json`)
|
||||
- `--host` : host binding (default: `0.0.0.0`)
|
||||
- [ ] **DA FARE:** Caricamento dinamico dati da JSON
|
||||
- [ ] **DA FARE:** Import routes da modulo `api`
|
||||
- [x] Implementare argparse con opzioni:
|
||||
- `--port` / `-p` : porta server (default: 8000)
|
||||
- `--data` / `-d` : path file JSON dati (default: `data/users_default.json`)
|
||||
- `--host` : host binding (default: `0.0.0.0`)
|
||||
- [x] Caricamento dinamico dati da JSON
|
||||
- [x] Import routes da modulo `api`
|
||||
|
||||
### 6. Struttura Base FastAPI
|
||||
### 6. Invalidazione Sessioni
|
||||
|
||||
- [x] Import FastAPI e dipendenze
|
||||
- [x] Configurazione app con titolo e descrizione
|
||||
- [x] Middleware CORS (allow all origins)
|
||||
- [x] Endpoint root `/` per health check
|
||||
- [ ] **DA FARE:** Refactor in struttura modulare
|
||||
- [x] `SERVER_START_TIME` generato all'avvio del server
|
||||
- [x] Restituito in `/info-room` per permettere al frontend di invalidare sessioni vecchie
|
||||
- [x] Se il server riparte, tutte le sessioni frontend vengono invalidate
|
||||
|
||||
---
|
||||
|
||||
@@ -101,19 +102,16 @@ Il frontend gestirà autonomamente la visualizzazione internazionale con carosel
|
||||
|
||||
```json
|
||||
{
|
||||
"validator": {
|
||||
"badge": "999999",
|
||||
"password": "focolari"
|
||||
},
|
||||
"validator_password": "focolari",
|
||||
"room": {
|
||||
"room_name": "Sala Assemblea",
|
||||
"meeting_id": "VOT-2024"
|
||||
},
|
||||
"users": [
|
||||
{
|
||||
"badge_code": "000001",
|
||||
"nome": "Maria",
|
||||
"cognome": "Rossi",
|
||||
"badge_code": "0008988288",
|
||||
"nome": "Marco",
|
||||
"cognome": "Bianchi",
|
||||
"url_foto": "https://...",
|
||||
"ruolo": "Votante",
|
||||
"ammesso": true
|
||||
@@ -126,25 +124,22 @@ Il frontend gestirà autonomamente la visualizzazione internazionale con carosel
|
||||
|
||||
## Comandi Esecuzione
|
||||
|
||||
### Avvio Standard
|
||||
### Via Script (consigliato)
|
||||
|
||||
```bash
|
||||
./dev.sh server # Avvia server con frontend
|
||||
./dev.sh server -p 9000 # Porta custom
|
||||
./dev.sh backend # Solo API, no frontend
|
||||
```
|
||||
|
||||
### Manuale
|
||||
|
||||
```bash
|
||||
cd backend-mock
|
||||
pipenv install
|
||||
pipenv run python main.py
|
||||
```
|
||||
|
||||
### Avvio con Parametri Custom
|
||||
```bash
|
||||
# Porta diversa
|
||||
pipenv run python main.py --port 9000
|
||||
|
||||
# Dataset test
|
||||
pipenv run python main.py --data data/users_test.json
|
||||
|
||||
# Combinato
|
||||
pipenv run python main.py -p 9000 -d data/users_test.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test Rapidi
|
||||
@@ -153,29 +148,28 @@ pipenv run python main.py -p 9000 -d data/users_test.json
|
||||
# Health check
|
||||
curl http://localhost:8000/
|
||||
|
||||
# Info sala
|
||||
# Info sala (include server_start_time)
|
||||
curl http://localhost:8000/info-room
|
||||
|
||||
# Ricerca utente
|
||||
curl http://localhost:8000/anagrafica/000001
|
||||
# Ricerca utente reale
|
||||
curl http://localhost:8000/anagrafica/0008988288
|
||||
|
||||
# Badge non trovato
|
||||
curl http://localhost:8000/anagrafica/0006478281
|
||||
|
||||
# Login validatore
|
||||
curl -X POST http://localhost:8000/login-validate \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"badge": "999999", "password": "focolari"}'
|
||||
-d '{"badge": "qualsiasi", "password": "focolari"}'
|
||||
|
||||
# Richiesta ingresso (risposta asettica)
|
||||
# Richiesta ingresso
|
||||
curl -X POST http://localhost:8000/entry-request \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"user_badge": "000001", "validator_password": "focolari"}'
|
||||
-d '{"user_badge": "0008988288", "validator_password": "focolari"}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Note Implementative
|
||||
## ✅ BACKEND COMPLETATO
|
||||
|
||||
- Gli endpoint puliscono automaticamente i caratteri `;`, `?`, `ò`, `_` dai badge
|
||||
- Il confronto badge avviene sia con che senza zeri iniziali
|
||||
- Le risposte seguono lo standard HTTP (200 OK, 401 Unauthorized, 404 Not Found, 403 Forbidden)
|
||||
- La documentazione OpenAPI è auto-generata su `/docs`
|
||||
- **Risposta `/entry-request`:** JSON asettico `{ success: true, message: "..." }` senza messaggi multilingua
|
||||
Tutti i task sono stati implementati e testati.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## Obiettivo
|
||||
|
||||
Applicazione React per tablet che gestisce il flusso di accesso ai varchi votazione, con lettura badge RFID.
|
||||
Include sistema di test automatici per validazione e regression detection.
|
||||
Ottimizzata per tablet in orizzontale.
|
||||
|
||||
---
|
||||
|
||||
@@ -14,8 +14,11 @@ Include sistema di test automatici per validazione e regression detection.
|
||||
- [x] Inizializzare Vite + React + TypeScript
|
||||
- [x] Installare Tailwind CSS 4
|
||||
- [x] Configurare `tsconfig.json`
|
||||
- [x] Configurare `vite.config.ts`
|
||||
- [x] Configurare `vite.config.ts` con proxy API
|
||||
- [x] Configurare `.gitignore`
|
||||
- [x] Path relativi per build (base: './')
|
||||
- [x] Output build in `frontend/dist/`
|
||||
- [x] Favicon con logo Focolari
|
||||
|
||||
### 2. Design System
|
||||
|
||||
@@ -29,15 +32,14 @@ Include sistema di test automatici per validazione e regression detection.
|
||||
|
||||
### 3. Tipi TypeScript (`types/index.ts`)
|
||||
|
||||
- [x] `RoomInfo` - info sala
|
||||
- [x] `RoomInfo` - info sala + **server_start_time**
|
||||
- [x] `User` - dati utente
|
||||
- [x] `LoginRequest/Response`
|
||||
- [x] `EntryRequest/Response` (SENZA welcome_message)
|
||||
- [x] `AppState` - stati applicazione
|
||||
- [x] `ValidatorSession` - sessione validatore
|
||||
- [x] `ValidatorSession` - sessione validatore + **serverStartTime**
|
||||
- [x] `RFIDScannerState` - stato scanner
|
||||
- [x] `RFIDScanResult` - risultato scan
|
||||
- [ ] **DA FARE:** Aggiornare `EntryResponse` rimuovendo `welcome_message`
|
||||
|
||||
### 4. API Service (`services/api.ts`)
|
||||
|
||||
@@ -47,259 +49,90 @@ Include sistema di test automatici per validazione e regression detection.
|
||||
- [x] `loginValidator()` - POST /login-validate
|
||||
- [x] `getUserByBadge()` - GET /anagrafica/{badge}
|
||||
- [x] `requestEntry()` - POST /entry-request
|
||||
- [ ] **DA FARE:** Logging con prefisso `[API]`
|
||||
- [x] Logging con prefisso `[API]`
|
||||
- [x] Path relativi (proxy Vite in dev, stesso server in prod)
|
||||
|
||||
### 5. Hook RFID Scanner (`hooks/useRFIDScanner.ts`)
|
||||
|
||||
#### Implementazione Base (v1)
|
||||
|
||||
- [x] Listener `keydown` globale
|
||||
- [x] Stati: idle → scanning → idle
|
||||
- [x] Singolo pattern (`;` / `?`)
|
||||
- [x] Timeout sicurezza (3s)
|
||||
- [x] `preventDefault` durante scan
|
||||
- [x] Callback `onScan`, `onTimeout`, `onScanStart`
|
||||
|
||||
#### ⚠️ AGGIORNAMENTO RICHIESTO (v2) - Multi-Pattern
|
||||
|
||||
- [ ] Supporto pattern multipli (US, IT, altri)
|
||||
```typescript
|
||||
const VALID_PATTERNS = [
|
||||
{ start: ';', end: '?' }, // Layout US
|
||||
{ start: 'ò', end: '_' }, // Layout IT
|
||||
];
|
||||
```
|
||||
- [ ] Rilevamento automatico pattern in uso
|
||||
- [ ] Memorizzazione pattern attivo durante scan
|
||||
- [ ] Validazione `end` solo per pattern corretto
|
||||
- [ ] Logging avanzato con prefisso `[RFID]`
|
||||
- [ ] Esportare info pattern attivo per debug page
|
||||
- [x] Supporto pattern multipli (US: `;?`, IT: `ò_`)
|
||||
- [x] Rilevamento automatico pattern in uso
|
||||
- [x] Gestione Enter post-completamento
|
||||
- [x] Timeout 2.5s per scansioni accidentali
|
||||
- [x] ESC annulla scansione in corso
|
||||
- [x] Logging avanzato con prefisso `[RFID]`
|
||||
- [x] Export `keyLog` per debug
|
||||
|
||||
### 6. Componenti UI (`components/`)
|
||||
|
||||
- [x] `Logo.tsx` - logo Focolari
|
||||
- [x] `Button.tsx` - varianti primary/secondary/danger
|
||||
- [x] `Input.tsx` - campo input styled
|
||||
- [x] `Input.tsx` - campo input styled + **toggle password visibility**
|
||||
- [x] `Modal.tsx` - modale base
|
||||
- [x] `RFIDStatus.tsx` - indicatore stato scanner
|
||||
- [x] `UserCard.tsx` - card utente con foto e ruolo
|
||||
- [x] `CountdownTimer.tsx` - timer con progress bar
|
||||
- [x] `index.ts` - barrel export
|
||||
- [ ] **DA FARE:** `WelcomeCarousel.tsx` - carosello messaggi multilingua
|
||||
- [x] `WelcomeCarousel.tsx` - carosello messaggi multilingua
|
||||
- [x] `NumLockBanner.tsx` - avviso NumLock per desktop
|
||||
|
||||
### 7. Schermate (`screens/`)
|
||||
|
||||
- [x] `LoadingScreen.tsx` - caricamento iniziale
|
||||
- [x] `ValidatorLoginScreen.tsx` - attesa badge + password
|
||||
- [x] `ActiveGateScreen.tsx` - varco attivo + scheda utente
|
||||
- [x] `SuccessModal.tsx` - conferma ingresso fullscreen
|
||||
- [x] `LoadingScreen.tsx` - caricamento iniziale + ping automatico
|
||||
- [x] `ValidatorLoginScreen.tsx` - attesa badge + password + NumLockBanner
|
||||
- [x] `ActiveGateScreen.tsx` - varco attivo:
|
||||
- [x] Card utente (layout largo per tablet)
|
||||
- [x] **Schermata "badge non trovato"** con countdown 30s
|
||||
- [x] **Notifica badge validatore ignorato**
|
||||
- [x] NumLockBanner
|
||||
- [x] `SuccessModal.tsx` - conferma ingresso con carosello
|
||||
- [x] `ErrorModal.tsx` - errore fullscreen
|
||||
- [x] `index.ts` - barrel export
|
||||
- [ ] **DA FARE:** `DebugScreen.tsx` - pagina diagnostica RFID
|
||||
- [x] `DebugScreen.tsx` - pagina diagnostica RFID
|
||||
|
||||
### 8. State Machine (`App.tsx`)
|
||||
|
||||
- [x] Stati applicazione gestiti
|
||||
- [x] Integrazione `useRFIDScanner`
|
||||
- [x] Gestione sessione validatore (localStorage)
|
||||
- [x] **Qualsiasi badge può essere validatore** (verificato con password)
|
||||
- [x] Password salvata in sessione per conferme ingresso
|
||||
- [x] **Invalidazione sessione se server riparte** (serverStartTime)
|
||||
- [x] Timeout sessione 30 minuti
|
||||
- [x] Timeout utente 60 secondi
|
||||
- [x] **Timeout badge non trovato 30 secondi**
|
||||
- [x] Cambio rapido badge partecipante
|
||||
- [x] Conferma con badge validatore
|
||||
- [ ] **DA FARE:** Logging transizioni con prefisso `[FLOW]`
|
||||
- [x] Conferma con badge validatore (quello della sessione)
|
||||
- [x] **Notifica se badge validatore rippassato senza utente**
|
||||
- [x] Logging transizioni con prefisso `[FLOW]`
|
||||
|
||||
### 9. Modale Successo - Carosello Internazionale
|
||||
|
||||
#### ⚠️ MODIFICA RICHIESTA
|
||||
|
||||
Il backend **NON** restituisce più messaggi multilingua.
|
||||
Il frontend gestisce autonomamente la visualizzazione con un **carosello automatico**.
|
||||
|
||||
**Specifiche:**
|
||||
- [ ] Creare componente `WelcomeCarousel.tsx`
|
||||
- [ ] Lista messaggi di benvenuto in diverse lingue:
|
||||
```typescript
|
||||
const WELCOME_MESSAGES = [
|
||||
{ lang: 'it', text: 'Benvenuto!' },
|
||||
{ lang: 'en', text: 'Welcome!' },
|
||||
{ lang: 'fr', text: 'Bienvenue!' },
|
||||
{ lang: 'de', text: 'Willkommen!' },
|
||||
{ lang: 'es', text: 'Bienvenido!' },
|
||||
{ lang: 'pt', text: 'Bem-vindo!' },
|
||||
{ lang: 'zh', text: '欢迎!' },
|
||||
{ lang: 'ja', text: 'ようこそ!' },
|
||||
];
|
||||
```
|
||||
- [ ] Scorrimento automatico (es. ogni 2 secondi)
|
||||
- [ ] Animazione transizione fluida (fade o slide)
|
||||
- [ ] Modale fullscreen verde con carosello al centro
|
||||
- [ ] Durata totale modale: 5 secondi
|
||||
- [x] Componente `WelcomeCarousel.tsx`
|
||||
- [x] 10 lingue supportate
|
||||
- [x] Scorrimento automatico ogni 800ms
|
||||
- [x] Modale fullscreen verde
|
||||
- [x] Durata totale: 5 secondi
|
||||
|
||||
### 10. Debug & Diagnostica
|
||||
|
||||
#### ⚠️ DA IMPLEMENTARE
|
||||
|
||||
- [ ] Pagina `/debug` dedicata
|
||||
- [ ] Log ultimi 20 tasti premuti (key + code)
|
||||
- [ ] Stato scanner real-time (idle/scanning)
|
||||
- [ ] Buffer corrente
|
||||
- [ ] Pattern attivo (US/IT/...)
|
||||
- [ ] Ultimo codice rilevato
|
||||
- [ ] Timestamp eventi
|
||||
- [ ] Link/pulsante nascosto per accesso debug (es. logo cliccabile 5 volte)
|
||||
- [ ] Logging console strutturato:
|
||||
- [ ] `[RFID]` - eventi scanner
|
||||
- [ ] `[FLOW]` - transizioni stato
|
||||
- [ ] `[API]` - chiamate HTTP
|
||||
- [x] Pagina `/debug` dedicata
|
||||
- [x] Logging console strutturato `[RFID]`, `[FLOW]`, `[API]`
|
||||
|
||||
### 11. Routing
|
||||
|
||||
- [ ] Installare React Router
|
||||
- [ ] Route principale `/`
|
||||
- [ ] Route debug `/debug`
|
||||
|
||||
### 12. Test Automatici (E2E / Use Case Validation)
|
||||
|
||||
#### ⚠️ NUOVA SEZIONE
|
||||
|
||||
Sistema di test per validazione formale dei flussi e regression detection.
|
||||
|
||||
**Struttura:**
|
||||
```
|
||||
frontend/
|
||||
├── src/
|
||||
│ └── tests/
|
||||
│ ├── usecase/
|
||||
│ │ ├── UC01_ValidatorLogin.test.ts
|
||||
│ │ ├── UC02_ParticipantAccess.test.ts
|
||||
│ │ ├── UC03_DeniedAccess.test.ts
|
||||
│ │ ├── UC04_SessionTimeout.test.ts
|
||||
│ │ ├── UC05_QuickBadgeSwitch.test.ts
|
||||
│ │ └── UC06_RFIDMultiPattern.test.ts
|
||||
│ └── helpers/
|
||||
│ ├── mockRFID.ts # Simulatore eventi tastiera RFID
|
||||
│ └── testUtils.ts # Utility comuni
|
||||
```
|
||||
|
||||
**Use Case da Testare:**
|
||||
|
||||
- [ ] **UC01 - Login Validatore**
|
||||
- Simula badge validatore (`;999999?`)
|
||||
- Inserisce password corretta
|
||||
- Verifica transizione a stato `gate-active`
|
||||
- Verifica sessione salvata in localStorage
|
||||
|
||||
- [ ] **UC02 - Accesso Partecipante Ammesso**
|
||||
- Da stato `gate-active`
|
||||
- Simula badge partecipante ammesso
|
||||
- Verifica caricamento dati utente
|
||||
- Simula badge validatore per conferma
|
||||
- Verifica modale successo con carosello
|
||||
- Verifica ritorno a `gate-active`
|
||||
|
||||
- [ ] **UC03 - Accesso Negato**
|
||||
- Simula badge partecipante NON ammesso
|
||||
- Verifica visualizzazione warning rosso
|
||||
- Verifica che conferma validatore sia bloccata
|
||||
- Verifica pulsante annulla funzionante
|
||||
|
||||
- [ ] **UC04 - Timeout Sessione**
|
||||
- Verifica scadenza sessione 30 minuti
|
||||
- Verifica redirect a login validatore
|
||||
- Verifica pulizia localStorage
|
||||
|
||||
- [ ] **UC05 - Cambio Rapido Badge**
|
||||
- Con utente a schermo
|
||||
- Simula nuovo badge partecipante
|
||||
- Verifica sostituzione immediata dati
|
||||
|
||||
- [ ] **UC06 - Pattern RFID Multipli**
|
||||
- Testa pattern US (`;` / `?`)
|
||||
- Testa pattern IT (`ò` / `_`)
|
||||
- Verifica stesso risultato finale
|
||||
|
||||
**Dipendenze Test:**
|
||||
```bash
|
||||
npm install -D vitest @testing-library/react @testing-library/user-event jsdom
|
||||
```
|
||||
|
||||
**Script npm:**
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"test": "vitest",
|
||||
"test:ui": "vitest --ui",
|
||||
"test:coverage": "vitest --coverage"
|
||||
}
|
||||
}
|
||||
```
|
||||
- [x] React Router
|
||||
- [x] Route principale `/`
|
||||
- [x] Route debug `/debug`
|
||||
|
||||
---
|
||||
|
||||
## Correzioni Necessarie
|
||||
## Badge di Test
|
||||
|
||||
### Hook RFID - Da Aggiornare
|
||||
|
||||
Il file `useRFIDScanner.ts` attualmente supporta **solo** il pattern US (`;` / `?`).
|
||||
|
||||
**Modifiche richieste:**
|
||||
|
||||
1. Aggiungere costante `VALID_PATTERNS` con pattern multipli
|
||||
2. Modificare logica `handleKeyDown` per:
|
||||
- Riconoscere qualsiasi `start` sentinel
|
||||
- Memorizzare quale pattern è in uso
|
||||
- Validare solo con l'`end` corrispondente
|
||||
3. Aggiungere stato `activePattern` per debug
|
||||
4. Migliorare logging
|
||||
|
||||
### Success Modal - Da Aggiornare
|
||||
|
||||
Attualmente usa `welcome_message` dal backend.
|
||||
|
||||
**Modifiche richieste:**
|
||||
|
||||
1. Rimuovere dipendenza da `welcome_message` API
|
||||
2. Implementare `WelcomeCarousel` con messaggi hardcoded
|
||||
3. Carosello auto-scroll ogni 2 secondi
|
||||
4. Animazioni fluide tra messaggi
|
||||
|
||||
### Logging Console
|
||||
|
||||
Attualmente i log usano messaggi generici. Aggiornare tutti i `console.log` con prefissi standardizzati.
|
||||
| Badge | Nome | Ruolo | Ammesso |
|
||||
|--------------|----------------|---------|---------------|
|
||||
| `0008988288` | Marco Bianchi | Votante | ✅ Sì |
|
||||
| `0007399575` | Laura Rossi | Votante | ✅ Sì |
|
||||
| `0000514162` | Giuseppe Verdi | Tecnico | ❌ No |
|
||||
| `0006478281` | - | - | ⚠️ Non nel DB |
|
||||
|
||||
---
|
||||
|
||||
## Dipendenze da Aggiungere
|
||||
|
||||
```bash
|
||||
# Routing
|
||||
npm install react-router-dom
|
||||
|
||||
# Testing
|
||||
npm install -D vitest @testing-library/react @testing-library/user-event jsdom @vitest/ui @vitest/coverage-v8
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Comandi Esecuzione
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
npm run dev # Sviluppo
|
||||
npm run build # Build produzione
|
||||
npm run test # Test suite
|
||||
npm run test:ui # Test con UI interattiva
|
||||
npm run test:coverage # Coverage report
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Note UI/UX
|
||||
|
||||
- Font grandi per leggibilità tablet
|
||||
- Pulsanti touch-friendly (min 48px)
|
||||
- Feedback visivo immediato su azioni
|
||||
- Animazioni fluide ma non invasive
|
||||
- Supporto landscape e portrait
|
||||
- Carosello benvenuto: transizioni smooth, leggibilità massima
|
||||
## ✅ FRONTEND COMPLETATO
|
||||
|
||||
Reference in New Issue
Block a user