# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Docs in `docs/`. Su `/init` leggi TUTTI i `.md` in `docs/`.

## Progetto

Refactoring completo del sito web Benza Water Storage SRL — tre aree: **sito pubblico**, **e-commerce**, **pannello admin**. Il vecchio sito è in `/Users/paolo/Server/Siti Web/Lavoro/Benza/sito_old/` (Bootstrap 3, jQuery 1.11, PHP vecchio). Non è più online: per sapere come funzionava si leggono i suoi sorgenti lì. Il nuovo sito è qui.

**Il sito è LIVE su https://riserve-idriche.benza.it dal 30/09/2026** (prima su www.benza.it, go-live 11/07/2026; ora www.benza.it è la pagina del Gruppo Benza e rimanda qui con 301, vedi `docs/MIGRAZIONE.md`). Il dominio sta in `includes/dominio.php`: non scriverlo a mano altrove. Fase di MANUTENZIONE: bug-fix e modifiche richiesti da Benza (Davide) via WhatsApp. Stato/workflow completi nella memoria `project_stato` (deploy FTP in chiaro, DB dev `Benza_sito_new`, secrets a mano, ecc.).

Il gestionale clienti già completato è in `/Users/paolo/Server/Siti Web/Lavoro/Benza/ordini_clienti_26/` — serve come **riferimento architetturale** per admin panel, API, JWT, email, UI.

## DB

Usare la skill globale `db-query` per interrogare il database. Non serve configurazione aggiuntiva.

- DB sito/e-commerce dev: `Benza_sito_new` (NAS) — DB gestionale sul NAS: `Benza_sit_clienti_new` (utf8)
- Produzione **non raggiungibile dall'esterno**: per leggere il catalogo vero si usano le API pubbliche del sito, non un file ponte
- **SOLO SELECT** — migration in `docs/sql/`, eseguite manualmente dall'utente
- Produzione Aruba: `89.46.111.15`, DB `Sql958286_1`

## Stack

- **Backend:** PHP 8.4 nativo, MariaDB, API REST con JWT (Firebase php-jwt)
- **Frontend sito/e-commerce:** Bootstrap 5, jQuery 3.7, CSS custom
- **Frontend admin:** Bootstrap 5 (stessa UI del gestionale clienti: sidebar sx, tabelle, TinyMCE)
- **Auth:** JWT con due ruoli — `admin` (gestione completa) e `utente` (cliente e-commerce). Token separati, endpoint con permessi differenziati
- **Email:** PHPMailer (copiare sistema dal gestionale clienti: `includes/Mailer.php`, `includes/mail_config.php`, `includes/phpmailer/`)
- **Pagamenti:** PayPal (aggiornare da vecchia integrazione a PayPal REST API v2, incluse rate)

## Architettura — Vecchio Sito (da migrare)

### Aree principali
1. **Sito pubblico** (~20 pagine statiche): homepage, categorie prodotti (laghi, piscine, fontane, irrigazione, gazebi, arredamenti), pagine info (storia, staff, orari, contatti, dove siamo, consegne, newsletter)
2. **E-commerce:** catalogo (`shop.php`, `categoria.php`), carrello (`carrello*.php`), checkout con PayPal (`ordine-offerta.php`, `ipn.php`), registrazione/login utente, area utente
3. **Preventivatore laghi:** `prev_*.php` + `preventivo*.php` — calcolo automatico preventivi per laghi artificiali basato su misure. **NON toccare la logica di calcolo**, solo refactoring grafico
4. **Admin:** `admin/` — gestione prodotti, categorie, modelli, dimensioni, disponibilità, offerte, clienti, ordini, gallerie, video, trasporti, vacanze

### Struttura file vecchio sito
- `admin/datalog.php` — connessione DB (rileva locale/produzione da IP)
- `admin/funzioni.php` — funzioni globali + config email + gestione sessione utente
- `header.php` / `footer.php` — layout comune
- `css/style.css` — stile unico, `js/script.js` — JS globale
- File `*-db.php` — operazioni database (pattern form → submit → *-db.php)

## Architettura — Nuovo Sito

### API REST (copiare pattern dal gestionale clienti)
```
api/
├── config/
│   ├── core.php           # Chiavi JWT, crittografia AES-256
│   ├── database.php       # Connessione DB (3 ambienti: locale/demo/prod)
│   ├── headers.php        # CORS + rate limiting
│   ├── cache_helper.php   # APCu + fallback file JSON
│   └── rate_limiter.php   # 120 req/min generale, 10 req/min login
├── libs/php-jwt-master/   # Firebase JWT
├── objects/               # Classi PHP per entità
├── admin/                 # CRUD admin (login, read, create, update, delete)
├── utenti/                # CRUD utenti e-commerce
├── prodotti/              # CRUD prodotti
├── ordini/                # CRUD ordini
└── validate_token.php     # Validazione JWT
```

### Pattern Endpoint (dal gestionale)
- `GET /api/entita/read.php` — lista
- `GET /api/entita/read_one.php?id=X` — singolo
- `POST /api/entita/create.php` — crea
- `POST /api/entita/update.php` — aggiorna
- `POST /api/entita/delete.php` — elimina
- **PUT+FormData:** PHP non popola `$_POST` su PUT multipart → JS invia `method:'POST'` + `_method=PUT` nel FormData, backend intercetta con `$_POST['_method']==='PUT'`

### JWT — Due token
- **Token admin:** payload con `id_utente` (AES-256), `nominativo`, `email`, `ruolo` (developer/admin/dipendente), `secret` (SHA-512 User-Agent)
- **Token utente:** payload con `id_utente`, `nominativo`, `email`, `tipo: 'utente'`
- Endpoint admin: richiedono token admin, verificano ruolo
- Endpoint pubblici (catalogo, preventivatore): nessun token
- Endpoint utente (carrello, ordini, profilo): richiedono token utente

## Pattern Codice

- `logAttivita($db, $admin, azione, entita, cod, dettaglio)` — NON ripetere #ID entità nel dettaglio
- **bind_param:** contare SEMPRE che i tipi corrispondano al numero di variabili
- JS globali: `showAlert(msg, class)` (toast), `AppModal.confirm()` (Promise), `escapeHtml()`, `formatCurrency()`, `formatDateTime()`, `getTinyMCEContent(id)`, `initTinyMCE(id)`
- Query SQL: compatibili con strict mode (`ONLY_FULL_GROUP_BY`) — tutte le colonne non aggregate nel GROUP BY
- Try/catch: wrappare TUTTA la logica API, non solo la validazione JWT
- Subquery "ultimo stato": usare `MAX(data_ora)` + `MAX(cod_stato)` come tiebreaker
- **Niente N+1**: mai una query dentro un ciclo sui risultati. Le pagine di categoria ne facevano 227 e arrivavano a 39 secondi in produzione; ora sono 4 (`Modello::readByProdotti()`, `mappaSottoTeliDisponibili()`)
- **Colonne nuove: query separata + `bz_column_exists()`**, così l'admin regge dove la migration non è ancora girata (vedi `youtube`, `foto_modello`)
- **Indirizzi pubblici**: `modello.php?m=ID` e `categoria.php?c=ID` (lettera singola). Con il parametro sbagliato si viene rimandati allo shop in silenzio
- **Su Aruba** i pattern `^nome$` nel `.htaccess` non agganciano (mod_rewrite riceve il percorso completo): usare gli **alias di `router.php`**, come per `sitemap.xml`

## Prestazioni

Il peso del sito e' stato rimesso a posto il 09/09/2026: 85 su profilo mobile, 1,9 MB per la home.
Per non perderlo:

- **Caratteri, Bootstrap, Font Awesome e jQuery stanno sul nostro dominio**, in `assets/vendor/` e
  `assets/fonts/`. Non rimettere riferimenti a CDN nel percorso pubblico.
- **Il font delle icone e' ritagliato** alle sole icone usate. Aggiungendone una nuova va rifatto il
  ritaglio, altrimenti in pagina resta un buco invisibile. Elenco in `docs/icone-in-uso.txt`.
- **Prima di mettere un'immagine in produzione, guardarne le dimensioni vere.** I due loghi erano
  file da stampa da 10981 pixel su ogni pagina.

## SEO e GEO

Fanno parte del lavoro concordato, non sono un extra. Ogni pagina deve avere titolo e descrizione veri **generati lato server**: i crawler dei modelli di IA in genere non eseguono JavaScript, quindi un titolo scritto dal JS per loro non esiste.

- Dati strutturati: `Organization`/`Store` in `header_pub.php` (tutte le pagine), `Product` in `modello.php`, `FAQPage` in `faq.php`
- `sitemap.php` genera la sitemap dal database e si serve come `/sitemap.xml`: non va aggiornata a mano
- `llms.txt` in root descrive l'azienda ai modelli; `robots.txt` nomina i loro crawler per accoglierli
- Un markup che dichiara contenuti **assenti dalla pagina visibile** viene penalizzato: se si aggiunge una domanda al blocco FAQ, va aggiunta anche al testo

## Brand e Tema

- **Colori brand Benza (variabili CSS in sito.css):**
  - `--bz-primary: #00a1e6` (azzurro primario)
  - `--bz-primary-hover: #0090ce`
  - `--bz-primary-active: #007fb5`
  - `--bz-navy: #0a2540` (titoli, hero, footer)
  - `--bz-accent: #00c9a7` (CTA, successo)
- **Font:** Sora (display) + Source Sans 3 (body)
- **Design:** stile "Liquid Precision" — glassmorphism, onde, card con hover lift
- Logo azzurro (`assets/img/logo_azzurro.png`) e bianco (`logo_bianco.png`)

## Frontend — Convenzioni

- **Footer sempre in fondo** (body flexbox min-height 100vh)
- **Pagine statiche con layout DIVERSIFICATO** — non tutte uguali: timeline, card colorate, step visivi, hero immersivi, grid asimmetriche
- **Contenuti dal vecchio sito**: riportare COMPLETI (video YouTube, foto, specifiche, nomi, marchi, norme)
- **Timeline storia**: stile Gibertini (progetto in `/Users/paolo/Server/Siti Web/Lavoro/Gibertini/`) — linea verticale, card alternate, dot azzurri
- **Navbar**: no sottolineatura su dropdown-toggle e separatore pipe
- **Immagini hero**: le vecchie erano verdi — servono NUOVE in tema azzurro dal cliente

## Cosa NON modificare

- **Logica di calcolo del preventivatore laghi** — solo refactoring UI, logica PHP intatta
- **Struttura database** — solo ottimizzazione (indici, FK). Migration in `docs/sql/`, eseguite manualmente
- **Contenuti testuali originali** — migrare fedelmente dal vecchio sito, non abbreviare

## Preferenze

- Italiano per commenti, UI, nomi variabili/funzioni dove sensato
- Documentare modifiche in `docs/REFACTORING_LOG.md`
- Plan mode per task non banali
- Copiare immagini con logica (capire a cosa servono), non alla rinfusa
- **Risposte corte**, anche quelle tecniche: dritti al risultato, senza raccontare i comandi lanciati (si vedono già) e senza riassunti finali. Si spiega il perché solo quando il rischio è alto, cioè in produzione o su scelte architetturali
- **Prima di dire che funziona, va verificato**: dimensioni dei file sul server dopo il deploy e prova sulla pagina vera, non deduzioni
- **Non reinventare i flussi**: si guarda come faceva il vecchio sito in `sito_old/`, che è la fonte di verità sul comportamento atteso

## REGOLA FONDAMENTALE — Memoria automatica

**Dopo OGNI task completato, bug fix, correzione dall'utente o indicazione sul progetto:**
1. Aggiornare `MEMORY.md` con lezioni apprese e stato progetto
2. Aggiornare questo `CLAUDE.md` se ci sono nuovi pattern/convenzioni da ricordare
3. Aggiornare `docs/REFACTORING_LOG.md` con le modifiche fatte

**NON aspettare che l'utente chieda "hai memorizzato?".** Farlo in autonomia, sempre.
