291 lines
11 KiB
JavaScript
291 lines
11 KiB
JavaScript
/**
|
|
* Fonctions utilitaires partagées entre les écrans RC Tarif et Projet.
|
|
*/
|
|
|
|
(function(window) {
|
|
'use strict';
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════
|
|
// CONSTANTES
|
|
// ═══════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* Champs qui influencent le calcul du tarif.
|
|
* On s'en sert pour savoir quand proposer un retour vers l'onglet Tarif.
|
|
*/
|
|
const TARIF_IMPACTING_FIELDS = [
|
|
// Chiffre d'affaires et type de contrat
|
|
'ca', 'chiffreAffaires', 'CA',
|
|
'typeCotisation', 'cotisation',
|
|
'nombreVehicules', 'nbVehicules',
|
|
|
|
// Activités RCC
|
|
'checkVoiturier', 'capitalVoiturier', 'actVoiturier',
|
|
'checkCommissionnaire', 'capitalCommissionnaire', 'actMultimodal',
|
|
'checkDemenageur', 'capitalDemenageur',
|
|
'checkLogistique', 'capitalLogistique',
|
|
'checkAutocariste', 'capitalAutocariste',
|
|
'checkAutres', 'capitalAutres',
|
|
|
|
// RCE
|
|
'checkRCE', 'autresRC',
|
|
|
|
// Activités complémentaires
|
|
'actComplVoiturier', 'actComplCommissionnaire', 'actComplDemenageur', 'actComplLogistique',
|
|
'activitesVoiturier', 'activitesCommissionnaire', 'activitesDemenageur', 'activitesLogistique',
|
|
|
|
// Marchandises
|
|
'marchandisesVoiturier', 'marchandisesCommissionnaire', 'marchandisesDemenageur',
|
|
'marchandisesLogistique', 'marchandisesAutocariste', 'marchandisesAutres',
|
|
'marOrdinaire', 'marRoulant', 'marEngins', 'marRoulantDem', 'marMobilerUsag',
|
|
'marPerissable', 'marAnimaux', 'marCiterne', 'marBeton', 'marExceptionnels', 'marVrac',
|
|
|
|
// Zones géographiques
|
|
'zone1', 'zone2', 'zone3', 'zone4', 'zone5', 'zone6',
|
|
|
|
// Extensions de garantie RCC
|
|
'extRCCModifCalArrim', 'extRCCFerroutage', 'extRCCFraisRecons',
|
|
'extRCCConfie', 'typeExtConfies', 'extRCCTPPC', 'extRCCRegie', 'extRCCSansMontageDemontage',
|
|
'checkDomImmat', 'capitalDomImmat', 'checkContConf', 'capitalContConf',
|
|
'checkDiffInv', 'capitalDiffInv', 'checkTPPC', 'capitalTPPC', 'vehiculesTPPC',
|
|
|
|
// Extensions de garantie RCE
|
|
'extRCEBraDebra', 'extRCEMontageDemontage',
|
|
|
|
// Garanties additionnelles
|
|
'checkStationLavage', 'checkGarageInterne', 'checkCSE', 'checkPJ', 'pj',
|
|
|
|
// Sinistralité
|
|
'sinistre', 'nbSinistres3ans', 'montantSinistres3ans'
|
|
];
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════
|
|
// HELPERS - MANIPULATION DE VALEURS
|
|
// ═══════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* Convertit une valeur texte/nombre en nombre JS.
|
|
* Accepte les formats FR/EN (espaces, virgules, points).
|
|
*/
|
|
function toNumber(x) {
|
|
if (x == null) return 0;
|
|
|
|
let value = String(x).trim();
|
|
if (!value) return 0;
|
|
|
|
value = value
|
|
.replace(/\s/g, '')
|
|
.replace(/[^\d.,-]/g, '');
|
|
|
|
if (!value) return 0;
|
|
|
|
const isNegative = value.startsWith('-');
|
|
value = value.replace(/-/g, '');
|
|
if (isNegative && value) {
|
|
value = '-' + value;
|
|
}
|
|
|
|
const hasComma = value.includes(',');
|
|
const hasDot = value.includes('.');
|
|
|
|
if (hasComma) {
|
|
value = value.replace(/\./g, '').replace(/,/g, '.');
|
|
} else if (hasDot) {
|
|
const dotMatches = value.match(/\./g);
|
|
const dotCount = dotMatches ? dotMatches.length : 0;
|
|
if (dotCount > 1) {
|
|
const parts = value.split('.');
|
|
const lastSegment = parts[parts.length - 1];
|
|
if (lastSegment.length === 3) {
|
|
value = parts.join('');
|
|
} else {
|
|
value = parts.slice(0, -1).join('') + '.' + lastSegment;
|
|
}
|
|
}
|
|
}
|
|
|
|
const parsed = Number(value);
|
|
return Number.isFinite(parsed) ? parsed : 0;
|
|
}
|
|
|
|
/**
|
|
* Récupère un élément par id, avec fallback querySelector.
|
|
*/
|
|
function getElementByIdFlexible(id) {
|
|
if (!id) return null;
|
|
const direct = document.getElementById(id);
|
|
if (direct) return direct;
|
|
try {
|
|
return document.querySelector(`[id="${id.replace(/"/g, '\\"')}"]`);
|
|
} catch (err) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Lit la valeur d'un champ de formulaire selon son type.
|
|
*/
|
|
function getValue(elementId) {
|
|
const element = getElementByIdFlexible(elementId);
|
|
if (!element) return null;
|
|
|
|
if (element.type === 'checkbox') {
|
|
return element.checked;
|
|
} else if (element.type === 'radio') {
|
|
const checked = document.querySelector(`input[name="${element.name}"]:checked`);
|
|
return checked ? checked.value : null;
|
|
} else if (element.tagName === 'SELECT') {
|
|
return element.value;
|
|
} else if (element.value !== undefined) {
|
|
return element.value;
|
|
} else {
|
|
return element.textContent || element.innerText || null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ecrit une valeur dans un champ de formulaire selon son type.
|
|
*/
|
|
function setValue(elementId, value) {
|
|
const element = getElementByIdFlexible(elementId);
|
|
if (!element) {
|
|
console.warn(`Élément non trouvé: ${elementId}`);
|
|
return;
|
|
}
|
|
|
|
if (element.type === 'checkbox') {
|
|
element.checked = Boolean(value);
|
|
} else if (element.type === 'radio') {
|
|
const radio = document.querySelector(`input[name="${element.name}"][value="${value}"]`);
|
|
if (radio) radio.checked = true;
|
|
} else if (element.tagName === 'SELECT') {
|
|
element.value = value;
|
|
// Réinitialiser Materialize select si présent
|
|
if (window.M && window.M.FormSelect) {
|
|
const instance = window.M.FormSelect.getInstance(element);
|
|
if (instance) instance.destroy();
|
|
window.M.FormSelect.init(element);
|
|
}
|
|
} else if (element.value !== undefined) {
|
|
element.value = value;
|
|
} else {
|
|
element.textContent = value;
|
|
}
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════
|
|
// DÉTECTION DE CHANGEMENTS IMPACTANTS
|
|
// ═══════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* Dit si un nom de champ fait partie des champs qui influencent le tarif.
|
|
*/
|
|
function isFieldImpactingTarif(fieldName) {
|
|
return TARIF_IMPACTING_FIELDS.some(field =>
|
|
fieldName.includes(field) || field.includes(fieldName)
|
|
);
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════
|
|
// MODAL DE RETOUR AU TARIF
|
|
// ═══════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* Ouvre le modal "modif tarif" déjà présent dans la vue projet.
|
|
*/
|
|
function showReturnToTarifModal(fieldName) {
|
|
const modal = document.getElementById('modalModif');
|
|
if (!modal) {
|
|
console.warn('Modal "modalModif" introuvable');
|
|
return;
|
|
}
|
|
|
|
if (fieldName) {
|
|
console.warn(`Modification impactant le tarif: ${fieldName}`);
|
|
}
|
|
|
|
const okBtn = document.getElementById('modif-OK');
|
|
const noBtn = document.getElementById('modif-NO');
|
|
|
|
if (okBtn) {
|
|
okBtn.onclick = (event) => {
|
|
event?.preventDefault?.();
|
|
navigateToTarif();
|
|
};
|
|
}
|
|
|
|
if (noBtn) {
|
|
noBtn.onclick = (event) => {
|
|
event?.preventDefault?.();
|
|
if (!window.M || !window.M.Modal) return;
|
|
const instance = window.M.Modal.getInstance(modal);
|
|
if (instance) instance.close();
|
|
};
|
|
}
|
|
|
|
if (window.M && window.M.Modal) {
|
|
const instance = window.M.Modal.getInstance(modal) || window.M.Modal.init(modal);
|
|
instance.open();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Redirige vers l'onglet Tarif depuis le Projet.
|
|
*/
|
|
function navigateToTarif() {
|
|
// Fermer le modal
|
|
const modal = document.getElementById('modalModif');
|
|
if (modal && window.M) {
|
|
const instance = window.M.Modal.getInstance(modal);
|
|
if (instance) instance.close();
|
|
}
|
|
|
|
// Si on est sur le formulaire projet, on garde un snapshot local
|
|
// pour pré-remplir le tarif juste après la navigation.
|
|
try {
|
|
if (typeof window.collectProjetDataForTarifPrefill === 'function') {
|
|
const projetData = window.collectProjetDataForTarifPrefill();
|
|
if (projetData) {
|
|
sessionStorage.setItem('rc_projet_data', JSON.stringify(projetData));
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Impossible de stocker les donnees projet avant redirection:', error);
|
|
}
|
|
|
|
// Naviguer vers le tarif
|
|
const numParcours = new URLSearchParams(window.location.search).get('numParcours');
|
|
if (numParcours) {
|
|
window.location.href = `/navParcours?numParcours=${numParcours}&submenu=tarif`;
|
|
}
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════
|
|
// EXPORT PUBLIC
|
|
// ═══════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* API publique du module RC Sync.
|
|
*/
|
|
window.RCSync = {
|
|
// Helpers
|
|
toNumber,
|
|
getValue,
|
|
setValue,
|
|
getElementByIdFlexible,
|
|
|
|
// Détection changements
|
|
isFieldImpactingTarif,
|
|
|
|
// Modal
|
|
showReturnToTarifModal,
|
|
navigateToTarif,
|
|
|
|
// Constantes
|
|
TARIF_IMPACTING_FIELDS
|
|
};
|
|
|
|
console.log('RC Sync Utils loaded');
|
|
|
|
})(window);
|