feat: add previous configuration handling for user selections in quotes
- Implemented session storage management for the last configuration choices made by the user. - Added functionality to prompt users when changing models to retain their previous selections. - Introduced methods to apply previous choices to the newly loaded model, including finishes, handles, glass types, and options. - Enhanced user experience by ensuring selections are automatically applied where applicable.
This commit is contained in:
+52
-16
@@ -13,6 +13,7 @@ import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import 'bootstrap/dist/js/bootstrap.bundle.min.js';
|
||||
import Configurator from './configurator.js';
|
||||
import AuthGate from './auth_gate.js';
|
||||
import ConfigurazionePrecedente from './configurazione_precedente.js';
|
||||
import { API_BASE as PREVENTIVI_API_BASE } from './api_base.js';
|
||||
|
||||
|
||||
@@ -46,6 +47,17 @@ const configReady = (async () => {
|
||||
|
||||
let invioPreventivoInCorso = false;
|
||||
|
||||
// Conferma non bloccante (markup fisso #toast in index.html).
|
||||
let timerToast = null;
|
||||
const mostraToast = (messaggio) => {
|
||||
const toast = document.getElementById('toast');
|
||||
if (!toast) return;
|
||||
toast.querySelector('.toast-messaggio').textContent = messaggio;
|
||||
toast.classList.add('visibile');
|
||||
clearTimeout(timerToast);
|
||||
timerToast = setTimeout(() => toast.classList.remove('visibile'), 3000);
|
||||
};
|
||||
|
||||
// Mostra/aggiorna il link "Vai al preventivo" (markup fisso in index.html, sopra la cart-container).
|
||||
window.mostraLinkPreventivo = (token, count) => {
|
||||
const link = document.getElementById('vai-al-preventivo');
|
||||
@@ -88,6 +100,8 @@ ripristinaLinkPreventivo();
|
||||
|
||||
$(() => {
|
||||
|
||||
ConfigurazionePrecedente.intercettaCambioModello();
|
||||
|
||||
$('.cart-button').on('click', async () => {
|
||||
|
||||
if ($('.cart-button').hasClass('disabled') || invioPreventivoInCorso)
|
||||
@@ -97,18 +111,16 @@ $(() => {
|
||||
try {
|
||||
const params = ParamsParser.getQueryParams();
|
||||
const img = await window.generaImagine();
|
||||
const conf = window.configurazione || {};
|
||||
const inner = conf.configurazione || {};
|
||||
const inner = window.configurazione?.configurazione || {};
|
||||
|
||||
// Prezzo e descrizione delle scelte li ricalcola il backoffice: si inviano solo i codici
|
||||
// (letti ora dal menu) e le voci descrittive che non incidono sul prezzo.
|
||||
const body = {
|
||||
token: localStorage.getItem(CART_TOKEN_KEY) || undefined,
|
||||
sistema: params.sistema,
|
||||
type: params.type,
|
||||
nome: inner.nome,
|
||||
larghezza: parseInt(inner.width) || null,
|
||||
altezza: parseInt(inner.height) || null,
|
||||
qty: parseInt($('.quantity-input').val()) || 1,
|
||||
prezzo: conf.prezzo,
|
||||
scelte: Configurator.raccogliScelte(),
|
||||
payload: inner,
|
||||
img: img,
|
||||
};
|
||||
@@ -124,6 +136,8 @@ $(() => {
|
||||
const data = await res.json();
|
||||
localStorage.setItem(CART_TOKEN_KEY, data.token);
|
||||
window.mostraLinkPreventivo(data.token, data.carrello.items.length);
|
||||
ConfigurazionePrecedente.salva(params.sistema, params.type, body.scelte);
|
||||
mostraToast('Prodotto aggiunto al preventivo');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert('Si è verificato un errore nell\'aggiunta al preventivo. Riprova.');
|
||||
@@ -136,7 +150,7 @@ $(() => {
|
||||
const start = async () => {
|
||||
const params = ParamsParser.getQueryParams();
|
||||
|
||||
// Sistemi e modelli (con icone) sono serviti dal backoffice, già filtrati sui soli attivi
|
||||
// Sistemi e modelli (con icone) sono serviti dal backoffice, già filtrati sui soli attivi con listino
|
||||
// e nell'ordine del menu: il primo sistema è quello di default.
|
||||
const res = await fetch(`${PREVENTIVI_API_BASE}/sistemi`, { headers: { Accept: 'application/json' } });
|
||||
if (!res.ok) throw new Error(`Catalogo non disponibile (HTTP ${res.status})`);
|
||||
@@ -168,23 +182,29 @@ const start = async () => {
|
||||
window.history.replaceState(null, '', url);
|
||||
}
|
||||
|
||||
const data = await (await fetch(`${modello_folder}/${modello.cartella}/form.json?rnd=${Math.random()}`)).json();
|
||||
const data_finiture = modello.moduli.includes('modello') ? (await (await fetch(`${modello_folder}/${modello.cartella}/modello.json?rnd=${Math.random()}`)).json()).filter(el => el.id != "") : [];
|
||||
const data_maniglie = modello.moduli.includes('maniglia') ? (await (await fetch(`${modello_folder}/${modello.cartella}/maniglia.json?rnd=${Math.random()}`)).json()).filter(el => el.id != "") : [];
|
||||
// Menu, finiture, maniglie, vetri, opzioni (con le immagini) e misure del listino dal backoffice.
|
||||
const resConfigurazione = await fetch(`${PREVENTIVI_API_BASE}/sistemi/${encodeURIComponent(params.sistema)}/modelli/${encodeURIComponent(modello.id)}/configurazione`, { headers: { Accept: 'application/json' } });
|
||||
if (!resConfigurazione.ok) throw new Error(`Configurazione non disponibile per il modello ${modello.id} (HTTP ${resConfigurazione.status})`);
|
||||
const configurazione = await resConfigurazione.json();
|
||||
|
||||
const data = configurazione.form;
|
||||
const data_finiture = configurazione.finiture;
|
||||
const data_maniglie = configurazione.maniglie;
|
||||
const data_vetri = configurazione.vetri;
|
||||
const listino = configurazione.misure;
|
||||
const data_avvolgibile = modello.moduli.includes('avvolgibile') ? (await (await fetch(`${modello_folder}/${modello.cartella}/avvolgibile.json?rnd=${Math.random()}`)).json()).filter(el => el.id != "") : [];
|
||||
const data_vetri = modello.moduli.includes('vetro') ? (await (await fetch(`${modello_folder}/${modello.cartella}/vetro.json?rnd=${Math.random()}`)).json()).filter(el => el.id != "") : [];
|
||||
const listino = modello.moduli.includes('listino')
|
||||
? await (await fetch(`${PREVENTIVI_API_BASE}/sistemi/${encodeURIComponent(params.sistema)}/modelli/${encodeURIComponent(modello.id)}/listino`, { headers: { Accept: 'application/json' } })).json()
|
||||
: [];
|
||||
if (modello.moduli.includes('listino') && !listino.length)
|
||||
throw new Error(`Nessun listino caricato per il modello ${modello.id}`);
|
||||
const altezza_maniglia = modello.moduli.includes('altezza_maniglia') ? await (await fetch(`${data_folder}/altezza_maniglia_${modello.categoria}.json?rnd=${Math.random()}`)).json() : [];
|
||||
|
||||
let priceCalculator = await MenuBuilder.build(data, 'left-container', modello.cartella_texture || modello.cartella, {
|
||||
let priceCalculator = await MenuBuilder.build(data, 'left-container', modello.id, {
|
||||
modelli: modelli,
|
||||
categoria: modello.categoria,
|
||||
sistema: params.sistema,
|
||||
data_finiture: data_finiture,
|
||||
// Finiture attive nel modello per lato (menu finiture interne / esterne).
|
||||
data_finiture_interne: configurazione.finiture_interne,
|
||||
data_finiture_esterne: configurazione.finiture_esterne,
|
||||
data_maniglie: data_maniglie,
|
||||
data_avvolgibile: data_avvolgibile,
|
||||
data_vetri: data_vetri,
|
||||
@@ -194,7 +214,8 @@ const start = async () => {
|
||||
|
||||
Configurator.init(priceCalculator, {
|
||||
modello: modello,
|
||||
nome_esteso: data.nome,
|
||||
sistema: params.sistema,
|
||||
form: data,
|
||||
data_finiture: data_finiture,
|
||||
data_maniglie: data_maniglie,
|
||||
data_avvolgibile: data_avvolgibile,
|
||||
@@ -249,6 +270,9 @@ const start = async () => {
|
||||
|
||||
$("#larghezza").first().trigger("change");
|
||||
|
||||
// Scelte del modello precedente, se l'utente ha chiesto di mantenerle.
|
||||
ConfigurazionePrecedente.applica();
|
||||
|
||||
//player.addMarker("Cylinder028", 'left', 'https://www.youtube.com/embed/l_zqI0v7JcU?si=Vq2k8nWHYk13esMQ');
|
||||
//player.addMarker("marker_1", 'left', 'https://www.youtube.com/embed/l_zqI0v7JcU?si=Vq2k8nWHYk13esMQ');
|
||||
//player.addMarker("marker_2", 'right', 'https://www.youtube.com/embed/LCi9jdF_4MQ?si=b8cyxSOI2sKEmmcm');
|
||||
@@ -368,6 +392,18 @@ const start = async () => {
|
||||
render();
|
||||
}
|
||||
|
||||
// Mostra / nasconde le mesh di una categoria (es. maniglia col motore): usate dalle opzioni
|
||||
// dei menu a tendina tramite i parametri func e categoria impostati nel backoffice.
|
||||
window.mostraCategoria = (categoria) => {
|
||||
player.showObject(categoria);
|
||||
render();
|
||||
}
|
||||
|
||||
window.nascondiCategoria = (categoria) => {
|
||||
player.hideObject(categoria);
|
||||
render();
|
||||
}
|
||||
|
||||
window.nascondiCerniere = (categoria) => {
|
||||
player.hideObject(categoria);
|
||||
render();
|
||||
|
||||
Reference in New Issue
Block a user