# Backoffice Preventivi — Architettura, ambienti e deploy Questo documento descrive il sistema di preventivi collegato al configuratore: come sono collegati i tre componenti, come gestiscono le porte/URL in sviluppo, e cosa serve per portarlo in produzione. Per il modello dati, l'API e il flusso applicativo dettagliato vedi [`backoffice/README.md`](../backoffice/README.md). Per il contratto dei parametri URL del configuratore vedi [`URL_PARAMS.md`](./URL_PARAMS.md). ## Architettura: tre componenti separati ``` ┌─────────────────────┐ POST /api/carrello/aggiungi ┌──────────────────────┐ │ Configuratore 3D │ ───────────────────────────────────────▶ │ Backend Laravel │ │ (root del repo, │ │ (backoffice/) │ │ Three.js + Vite) │ ◀─────────────────────────────────────── │ API + Filament │ └──────────┬───────────┘ GET /api/config (frontend url) └──────────┬────────────┘ │ │ │ link "Vai al preventivo" │ GET/DELETE/POST │ https:///?token=XXX │ /api/carrello/... ▼ ▼ ┌──────────────────────┐ ┌──────────────────────┐ │ App cliente Vue │ ───────────────────────────────────────▶ │ (stesso backend) │ │ (backoffice/cliente)│ carrello + checkout │ │ └──────────────────────┘ └──────────────────────┘ ``` Sono **tre processi indipendenti**, ognuno con il proprio server di sviluppo/deploy: | Componente | Cartella | Tecnologia | Ruolo | |---|---|---|---| | Configuratore 3D | `/` (root repo) | Vite + Three.js | UI di configurazione prodotto, genera lo screenshot e invia il primo prodotto al carrello | | Backend | `backoffice/` | Laravel 13 + Filament 3 | API carrello/preventivi, PDF, email, pannello admin | | App cliente | `backoffice/cliente/` | Vue 3 + Vite | Riepilogo carrello, form contatti, conferma preventivo | Il configuratore e l'app cliente **non si parlano mai direttamente**: comunicano solo passando dal backend Laravel (il configuratore scrive nel carrello via API, l'app cliente lo legge via API). Il collegamento tra i due frontend è un singolo `token` passato in query string nel link "Vai al preventivo". ## Il problema che questo documento previene I tre servizi girano su porte/domini diversi. Storicamente questo ha causato due classi di bug: 1. **Porte di sviluppo che collidono silenziosamente** — Vite, se una porta è occupata, ne sceglie un'altra automaticamente. Se due progetti hanno lo stesso default (era il caso: sia il configuratore che l'app cliente avevano `port: 5174`), il secondo processo avviato scivola su un'altra porta senza errori — e i link generati puntano alla porta sbagliata. 2. **URL di produzione indovinati o hardcoded** — se l'indirizzo di un servizio è scritto a mano nel codice dell'altro, ogni cambio di dominio/porta richiede una modifica e un rebuild manuale, facile da dimenticare. Soluzione adottata: **porte fisse in sviluppo** (`strictPort: true`, fallisce rumorosamente invece di scivolare) + **scoperta dinamica degli URL** dove possibile, invece di hardcoding. ## Porte di sviluppo (fisse) | Servizio | Porta | Comando | Config | |---|---|---|---| | Configuratore | `5173` | `pnpm dev` (root) | [`vite.config.js`](../vite.config.js) — `server.port` + `strictPort: true` | | App cliente | `5199` | `pnpm dev` (in `backoffice/cliente/`) | [`backoffice/cliente/vite.config.js`](../backoffice/cliente/vite.config.js) | | Backend Laravel | `8000` | `php artisan serve --port=8000` (in `backoffice/`) | nessuna config fissa, va specificata al comando | Con `strictPort: true`, se una porta è già occupata **l'avvio fallisce con un errore esplicito** invece di spostarsi su un'altra porta a caso. Se capita, il fix è liberare la porta (o capire quale altro processo la sta usando) — non serve più inseguire link rotti. ## Come i due frontend si trovano l'un l'altro ### App cliente → Backend L'app cliente conosce l'indirizzo dell'API tramite `VITE_API_BASE` in [`backoffice/cliente/.env`](../backoffice/cliente/.env) (default `http://localhost:8000/api`). È un valore di build-time (Vite), va impostato per ambiente. ### Configuratore → Backend Il configuratore conosce l'indirizzo dell'API tramite `VITE_PREVENTIVI_API_BASE`, letto a build-time da `.env` / `.env.production` nella **root del repo** (vedi sezione successiva). È l'unico URL che deve essere "noto a priori": da lì in poi il configuratore può fare domande al backend. ### Configuratore → App cliente (il pezzo dinamico) Il configuratore **non conosce a priori** dove gira l'app cliente. All'avvio chiama: ``` GET {VITE_PREVENTIVI_API_BASE}/api/config → { "frontend_cliente_url": "http://localhost:5199" } ``` Il valore restituito viene letto da Laravel dalla variabile `APP_FRONTEND_CLIENTE_URL` nel suo `.env` ([`backoffice/config/preventivi.php`](../backoffice/config/preventivi.php)). Il link "Vai al preventivo" viene costruito con questo valore, non con un default fisso nel bundle del configuratore. **Implicazione pratica**: se l'app cliente cambia dominio/porta, basta aggiornare **una sola variabile** lato Laravel (`APP_FRONTEND_CLIENTE_URL`) — il configuratore già in produzione la recepisce alla prossima richiesta, senza rebuild. Logica in [`src/js/starter.js`](../src/js/starter.js) (`configReady`, `mostraLinkPreventivo`, `ripristinaLinkPreventivo`). Se il backend non è raggiungibile, resta un fallback locale (`window.APP_CLIENTE_URL` se impostato, altrimenti `http://localhost:5199`) — solo per non rompere lo sviluppo offline, non pensato per la produzione. ## Variabili d'ambiente per componente ### Configuratore (root del repo) Attenzione: `vite.config.js` ha `root: 'src'` ma `envDir` è impostato esplicitamente sulla root del repo (dove stanno anche `build.sh`/`deploy.sh`) — i file `.env*` vanno quindi creati **nella root del repo**, non dentro `src/`. | File | Tracciato in git? | Contenuto | |---|---|---| | `.env` | Sì | `VITE_PREVENTIVI_API_BASE=http://localhost:8000/api` — default di sviluppo | | `.env.production` | **No** (in `.gitignore`) | `VITE_PREVENTIVI_API_BASE=` — va creato a mano prima del deploy | | `.env.production.example` | Sì | Traccia/promemoria del formato atteso, da copiare in `.env.production` | `pnpm build` (production mode di Vite) usa `.env.production` se presente. **`build.sh` blocca la build se `.env.production` manca**, per evitare di deployare per sbaglio con `localhost` incorporato nel bundle. Override runtime senza rebuild (usato raramente, es. hotfix): impostare `window.PREVENTIVI_API_BASE` / `window.APP_CLIENTE_URL` in uno script inline prima del bundle in `index.html` — ha priorità sul valore di build. ### Backend Laravel (`backoffice/.env`) | Variabile | Descrizione | Dev | Produzione | |---|---|---|---| | `APP_URL` | URL pubblico del backend stesso (usato per link nelle email e asset Filament) | `http://localhost:8000` | URL reale del backend | | `APP_FRONTEND_CLIENTE_URL` | URL dell'app cliente — letto da `/api/config` | `http://localhost:5199` | URL reale dell'app cliente | | `ADMIN_NOTIFY_EMAIL` | Email che riceve la notifica di nuovo preventivo | — | email reale dell'admin | | `CORS_ALLOWED_ORIGINS` | Origini autorizzate a chiamare l'API | `*` (di default, comodo in dev) | **da restringere** alle origini reali di configuratore + app cliente, separate da virgola | | `DB_*` | MySQL: `127.0.0.1` / `root` / nessuna password / `kreios_preventivi` in locale | — | credenziali del DB di produzione | | `MAIL_*` | `MAIL_MAILER=log` in dev (le email finiscono in `storage/logs/laravel.log`) | — | SMTP reale | ### App cliente (`backoffice/cliente/.env`) | Variabile | Descrizione | Dev | Produzione | |---|---|---|---| | `VITE_API_BASE` | URL base dell'API Laravel | `http://localhost:8000/api` | URL reale dell'API | ## Checklist di deploy in produzione 1. **Backend Laravel** (`backoffice/`) - `.env` di produzione: `APP_URL`, `APP_FRONTEND_CLIENTE_URL`, `DB_*`, `MAIL_*`, `ADMIN_NOTIFY_EMAIL`. - Restringere `CORS_ALLOWED_ORIGINS` alle origini reali (non lasciare `*`). - `php artisan migrate --force`, `php artisan storage:link`, `php artisan config:cache`. 2. **App cliente** (`backoffice/cliente/`) - `cliente/.env` (o `.env.production`) con `VITE_API_BASE` reale. - `pnpm build`, deploy dei file statici generati. 3. **Configuratore** (root del repo) - `cp .env.production.example .env.production` e impostare `VITE_PREVENTIVI_API_BASE` reale. - `./build.sh` (fallisce se `.env.production` manca) → `./deploy.sh`. - **Non serve** impostare l'URL dell'app cliente qui: viene letto da `/api/config` a runtime. 4. Verifica end-to-end: configurare un prodotto → "Aggiungi al preventivo" → il link "Vai al preventivo" deve puntare al dominio reale dell'app cliente → completare il checkout → verificare che il preventivo compaia nel backoffice Filament e che le email (cliente + admin) siano state inviate. ## Riferimenti file - [`src/js/starter.js`](../src/js/starter.js) — integrazione configuratore↔backend, scoperta dinamica dell'URL app cliente. - [`vite.config.js`](../vite.config.js) — porta fissa, `envDir`. - [`backoffice/routes/api.php`](../backoffice/routes/api.php) — endpoint `/api/config` e `/api/carrello/*`. - [`backoffice/config/preventivi.php`](../backoffice/config/preventivi.php) — sorgente di `frontend_cliente_url`. - [`backoffice/config/cors.php`](../backoffice/config/cors.php) — origini autorizzate. - [`build.sh`](../build.sh) — guardia su `.env.production`. - [`backoffice/README.md`](../backoffice/README.md) — setup locale, modello dati, API, branding.