🕐 Progetto

TimeTracker

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.

JavaScript Graph API MSAL Browser SharePoint Online Cloudflare Pages jsPDF SheetJS OAuth 2.0
Screenshot TimeTracker

Il problema

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 / JavaScript SVG 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.3 Microsoft Graph API OAuth 2.0 Delegated Azure 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 Online localStorage (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.5 jsPDF 2.5.1 jsPDF-AutoTable 3.5.28

Hosting & CI/CD

Cloudflare Pages GitHub (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
// Acquisizione token silenzioso (senza popup se la sessione è attiva) const tokenResponse = await msalApp.acquireTokenSilent({ scopes: ['Sites.ReadWrite.All', 'User.Read', 'Calendars.Read'], account }).catch(() => msalApp.acquireTokenPopup({ scopes, account }) ); // Lettura voci dalla lista SharePoint const res = await fetch( `https://graph.microsoft.com/v1.0/sites/${spSite}/lists/${spList}/items?$expand=fields&$filter=fields/UtenteEmail eq '${email}'`, { headers: { Authorization: `Bearer ${tokenResponse.accessToken}` } } ); // Salvataggio nuova voce await fetch( `https://graph.microsoft.com/v1.0/sites/${spSite}/lists/${spList}/items`, { method: 'POST', headers: { Authorization: `Bearer ${tokenResponse.accessToken}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ fields: { DataOre, Ore, Commessa, Attivita, Straordinario, OraInizio, OraFine, Note, Utente, UtenteEmail } }) } );

Cosa ho imparato

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:

Sviluppi futuri

Il progetto è in uso quotidiano e in continua evoluzione. Le funzionalità ancora in cantiere:

Prova l'app

Il TimeTracker è live e in uso quotidiano. Per accedervi è necessario effettuare il login con un account Microsoft aziendale del tenant configurato.

Apri il TimeTracker
🔐

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.