Un'app web per il tracciamento delle ore lavorative per team aziendali — con calendario interattivo, integrazione SharePoint, importazione da Outlook e report PDF. Tutto in un singolo file HTML, senza backend, senza installazioni.
In un team IT di consulenza, consuntivare le ore su ogni commessa è un'attività quotidiana obbligatoria — ma spesso viene gestita con strumenti non pensati per questo: fogli Excel condivisi, form SharePoint grezzi, note sparse. Il risultato è che a fine mese mancano sempre dati, si perde tempo a ricostruire cosa si è fatto e i report per il management diventano un esercizio di pazienza.
Gli strumenti commerciali come Clockify o Toggl esistono, ma in contesti enterprise spesso non si possono adottare per motivi di compliance o di governance dei dati. Serviva qualcosa che girasse sull'infrastruttura Microsoft già in uso, senza dipendenze esterne e senza richiedere approvazioni IT complesse.
💡
I dati delle ore restano su SharePoint Online del tenant aziendale — nessun dato esce verso servizi di terze parti. L'autenticazione avviene tramite Azure AD con lo stesso account Microsoft 365 già in uso.
La soluzione
Ho costruito un'app web a singolo file HTML che si autentica tramite MSAL Browser con l'account Microsoft aziendale e salva ogni voce direttamente su una lista SharePoint Online tramite Microsoft Graph API. Nessun backend, nessun server intermedio — il browser chiama Graph API direttamente, con token OAuth 2.0 acquisito in modo silenzioso.
Il deploy è su Cloudflare Pages con auto-deploy da GitHub: ogni aggiornamento del file HTML viene pubblicato automaticamente in 30-60 secondi. Il fallback è localStorage — se SharePoint non è raggiungibile, l'app continua a funzionare offline e si risincronizza appena la connessione torna.
Come funziona
Browser (TimeTracker — singolo file HTML) │ [non autenticato] → login popup Microsoft │ [autenticato] → token MSAL silenzioso ▼ MSAL Browser (Azure AD — flusso delegato) │ acquireTokenSilent / acquireTokenPopup │ scopes: Sites.ReadWrite.All · User.Read · Calendars.Read ▼ Microsoft Graph API │ GET/POST/PATCH/DELETE /sites/{site}/lists/{list}/items │ GET /me/calendarview (importazione eventi Outlook) ▼ SharePoint Online (lista OreCommesse) │ cache locale ──► localStorage (fallback offline) ▼ Browser renderizza calendario, dashboard e report
Ogni voce salvata contiene: data, ore, orario di inizio e fine, commessa, attività, flag straordinario, note, nome utente ed email. Il filtro per email garantisce che ogni utente veda solo le proprie ore — più persone possono usare la stessa lista SharePoint senza interferenze.
Funzionalità
L'app è organizzata in sezioni distinte, ognuna pensata per rispondere a un'esigenza concreta del lavoro quotidiano.
📅
Calendario multi-vista
Cinque viste: Mese, Settimana lavorativa, Settimana completa, Giorno e Agenda. Griglia 24h con blocchi posizionati all'orario esatto e drag-and-drop con snap ogni 30 minuti.
🎌
Festivi italiani automatici
Pasqua e Pasquetta calcolate algoritmicamente per ogni anno. Tutti i festivi nazionali evidenziati nel calendario, esclusi dall'inserimento ricorrente e dal conteggio ore mancanti.
🔄
Inserimento ricorrente
Inserisce la stessa voce su tutti i giorni lavorativi di un periodo, saltando weekend e festivi. Anteprima live e gestione conflitti con scelta di saltare i giorni occupati.
📅
Importazione da Outlook
Carica eventi dal calendario Outlook via Graph API per un periodo selezionato. Controllo automatico di duplicati, sovrapposizioni e limite ore giornaliero prima dell'importazione.
🍽️
Pausa pranzo automatica
Intervallo configurabile (default 13:00-14:00) saltato automaticamente nel calcolo dell'orario di fine e nell'auto-split. Visualizzato come blocco decorativo nel calendario.
🎯
Budget ore per commessa
Ogni commessa ha un tetto massimo configurabile. Barra di avanzamento colorata (verde/arancione/rosso) nella tab Commesse e nel tab Report con ore usate e rimanenti.
📄
Export PDF e Excel
Report PDF mensile in A4 landscape con tabella completa e riepilogo per commessa. Export Excel su tre fogli: Dettaglio, Per commessa e Mensile.
📈
Tab Report
Ore rimanenti su progetto, giorni lavorativi del mese con ore mancanti da consuntivare (esclusi festivi), consuntivazioni effettuate con selettore mese/anno dal 2025.
💾
Cache offline automatica
Ogni operazione aggiorna anche il localStorage. Se SharePoint non è raggiungibile, l'app carica i dati dalla cache locale e si risincronizza automaticamente al ripristino.
📂
Backup & ripristino ore
Export/Import JSON di tutte le voci — utile per backup completi o migrazione tra tenant diversi. Controllo automatico dei duplicati prima dell'inserimento.
🕐
Orologio SVG animato
Schermata di login con orologio SVG in tempo reale — lancette calcolate in JavaScript al millisecondo, senza immagini o GIF esterne.
⚙️
Commesse e attività configurabili
Ogni commessa ha nome, colore, attività collegate e budget ore. Export/Import della configurazione in JSON per portarla tra dispositivi o browser diversi.
✓
L'app include anche auto-split degli orari (una voce che copre la pausa pranzo viene divisa automaticamente in due), validazione sovrapposizioni, drag-and-drop nel calendario con salvataggio immediato su SharePoint, dark/light mode, lingua IT/EN, date picker custom con tastiera, paginazione nella lista giornaliera e modalità demo senza credenziali configurate.
Stack tecnico
Il progetto è volutamente minimalista lato dipendenze — tutto in un singolo file HTML, senza framework né build step.
Frontend
HTML / CSS / JavaScriptSVG animato (orologio)Drag-and-drop nativo
Single file HTML senza framework. Tutto il CSS è inline, tutto il JS è vanilla. Il calendario, le viste colonna, il date picker e i modal sono costruiti da zero senza dipendenze UI.
Autenticazione e API
MSAL Browser 2.38.3Microsoft Graph APIOAuth 2.0 DelegatedAzure AD App Registration
L'autenticazione avviene tramite flusso OAuth 2.0 delegato — l'utente si autentica con il proprio account Microsoft, MSAL acquisisce il token e il browser chiama Graph API direttamente. I permessi richiesti sono Sites.ReadWrite.All, User.Read e Calendars.Read.
Storage
SharePoint OnlinelocalStorage (cache offline)
I dati vengono salvati su una lista SharePoint Online (OreCommesse) tramite le API REST di Graph. Ad ogni operazione riuscita, localStorage viene aggiornato come cache offline — se SharePoint non è raggiungibile al reload, l'app usa i dati locali senza interruzioni.
Librerie esterne (CDN)
SheetJS 0.18.5jsPDF 2.5.1jsPDF-AutoTable 3.5.28
Hosting & CI/CD
Cloudflare PagesGitHub (auto-deploy)
Ogni push su GitHub aggiorna il sito in automatico tramite Cloudflare Pages in 30-60 secondi — senza pipeline complesse, senza build step.
JavaScript — autenticazione MSAL e chiamata Graph API
Costruire questo tool da zero — con requisiti reali e uso quotidiano da parte di un team — ha messo alla prova ogni decisione tecnica in condizioni reali. In particolare:
Il flusso OAuth 2.0 Delegated con MSAL Browser — la differenza tra acquireTokenSilent e acquireTokenPopup, la gestione del refresh token e come evitare popup indesiderati quando la sessione è ancora valida.
Graph API per le liste SharePoint — le API REST di SharePoint tramite Graph hanno comportamenti diversi rispetto alle API Files: le colonne vanno create manualmente o via provisioning, alcuni tipi (DateTime, Boolean) richiedono formati specifici, e le colonne opzionali vanno gestite con fallback per i tenant dove non esistono.
Architettura offline-first con localStorage — tenere localStorage sempre sincronizzato con SharePoint (non solo in fallback) richiede di aggiornare la cache ad ogni operazione riuscita, non solo al caricamento iniziale.
Auto-split degli orari — l'algoritmo che divide automaticamente una voce nei slot liberi del giorno (saltando voci esistenti e la pausa pranzo virtuale) ha richiesto diversi cicli di correzione per gestire edge case come l'ordine dei blocchi, i buchi multipli e il calcolo delle ore parziali.
Sviluppi futuri
Il progetto è in uso quotidiano e in continua evoluzione. Le funzionalità ancora in cantiere:
Timer live — bottone "Avvia" che conta i secondi in tempo reale e crea la voce automaticamente allo stop.
Pill cliccabili nella vista Mese — apertura del modal di modifica/elimina direttamente dalla cella del giorno.
Notifiche browser — promemoria automatico se a fine giornata non sono state inserite ore.
Vista manager — possibilità per un utente admin di visualizzare le ore di tutto il team in una vista aggregata.
Prova l'app
Il TimeTracker è live e in uso quotidiano. Per accedervi è necessario effettuare il login con un account Microsoft aziendale del tenant configurato.
L'accesso è riservato agli utenti del mio tenant Microsoft. L'app richiede il login con un account aziendale Microsoft appartenente al tenant configurato — non è accessibile con account esterni. Se sei interessato a implementarla nel tuo tenant o vuoi saperne di più, scrivimi via email o tramite i social nel portfolio.