Manager ore clienti

PhpJs/JquerySql

Il problema

I pacchetti ore prepagati dei miei clienti finivano gestiti su fogli Excel o via email. Il risultato? Il cliente non sapeva mai quante ore gli restavano, gli aggiornamenti erano manuali e gli errori frequenti.
Mi serviva qualcosa di semplice: un pannello dove io registro le lavorazioni e il cliente controlla il suo saldo in autonomia, senza account e senza password.

Come funziona

L’app è volutamente minimale: tre file PHP, un database MySQL con due tabelle, nessun framework.

clients (id, company_name, contact_name, email, total_hours_purchased)
time_entries (id, client_id, hours, website, date, description)

La distinzione tra admin e cliente è gestita in un unico file: se sei loggato come admin vedi tutti i clienti; se accedi tramite un link univoco (?client=c_abc123) vedi solo i tuoi dati, senza bisogno di fare login.

Cosa fa

Lato admin

  • Card per ogni cliente con progress bar che diventa rossa oltre il 90% di utilizzo
  • Aggiunta clienti e registrazione lavorazioni (sito, ore, data, descrizione)
  • Modifica inline del pacchetto ore: click → modifica → Enter per salvare
  • Link univoco per ogni cliente, copiabile in un click
  • Eliminazione cliente con cancellazione automatica di tutte le lavorazioni

Lato cliente

  • Accesso diretto via link, senza login
  • Ore acquistate, consumate e residue sempre in evidenza
  • Tabella con lo storico completo delle lavorazioni
  • Grafico a ciambella con la ripartizione ore per sito web

Sicurezza

Ho rafforzato ogni punto di ingresso dell’applicazione:

  • CSRF — token random a 32 byte su ogni form, verificato con confronto timing-safe
  • Session fixation — rigenerazione ID sessione al login e al logout
  • Input validation — regex su tutti gli ID, validazione email e date con funzioni native PHP
  • Prepared statements — nessuna concatenazione di input utente nelle query
  • ID opachi — gli ID cliente sono stringhe random, non sequenze prevedibili
  • Auth gate — ogni azione admin è protetta con controllo sessione e risposta 403 immediata

Un bug trovato in code review: il cast (int) sugli ID stringa li convertiva a 0, bloccando l’accesso a tutti i clienti. Risolto con una funzione di validazione centralizzata basata su regex.

Interfaccia

Dark mode con Tailwind CSS e componenti glass-morphism. Card con hover che mostra le azioni, modali con backdrop blur, progress bar animate e editing inline riservato all’admin.

Cliente: Me stesso
Anno realizzazione: 2026