credit-direct/assets/js/form_main.old.js
2025-12-18 09:44:42 +01:00

1438 lines
56 KiB
JavaScript

jQuery(function($) {
jQuery('form.load_simulator').each(function() {
jQuery(this).attr('action', window.location.origin + '/credit-step1')
})
/**
* Système de sauvegarde localStorage
*/
const FORM_STORAGE_KEY = 'credit_direct_form_data';
const FORM_STORAGE_TIMESTAMP = 'credit_direct_form_timestamp';
const STORAGE_EXPIRY_HOURS = 24; // Les données expirent après 24h
/**
* Affiche l'indicateur de sauvegarde
*/
function showSaveIndicator(message, type = 'success') {
let indicator = jQuery('.auto-save-indicator');
if (indicator.length === 0) {
indicator = jQuery('<div class="auto-save-indicator"></div>');
jQuery('body').append(indicator);
}
indicator.removeClass('show saving error').addClass('show ' + type);
indicator.text(message);
// Masquer après 3 secondes
setTimeout(() => {
indicator.removeClass('show');
}, 3000);
}
/**
* Sauvegarde les données du formulaire dans localStorage
*/
function saveFormData() {
// Afficher l'indicateur de sauvegarde
showSaveIndicator('Sauvegarde en cours...', 'saving');
const formData = {};
const currentStep = getCurrentStep();
// Récupérer tous les champs du formulaire
jQuery('form.form-submit').find('input, select, textarea').each(function() {
const $field = jQuery(this);
const name = $field.attr('name');
const type = $field.attr('type');
if (!name) return;
let value = '';
switch (type) {
case 'checkbox':
value = $field.is(':checked') ? $field.val() : '';
break;
case 'radio':
if ($field.is(':checked')) {
value = $field.val();
}
break;
case 'file':
// Ne pas sauvegarder les fichiers
return;
default:
value = $field.val() || '';
break;
}
// Ne sauvegarder que si la valeur n'est pas vide
if (value !== '') {
formData[name] = value;
}
});
// Sauvegarder avec l'étape actuelle et le timestamp
const dataToSave = {
step: currentStep,
data: formData,
timestamp: Date.now()
};
try {
localStorage.setItem(FORM_STORAGE_KEY, JSON.stringify(dataToSave));
localStorage.setItem(FORM_STORAGE_TIMESTAMP, Date.now().toString());
console.log('Données sauvegardées dans localStorage:', dataToSave);
// Afficher le succès
setTimeout(() => {
showSaveIndicator('Données sauvegardées', 'success');
}, 500);
} catch (e) {
console.error('Erreur lors de la sauvegarde localStorage:', e);
showSaveIndicator('Erreur de sauvegarde', 'error');
}
}
/**
* Restaure les données du formulaire depuis localStorage
*/
function restoreFormData() {
try {
const savedData = localStorage.getItem(FORM_STORAGE_KEY);
if (!savedData) return false;
const parsedData = JSON.parse(savedData);
const now = Date.now();
const savedTime = parsedData.timestamp || 0;
// Vérifier si les données ne sont pas expirées
if (now - savedTime > STORAGE_EXPIRY_HOURS * 60 * 60 * 1000) {
console.log('Données localStorage expirées, suppression...');
clearFormData();
return false;
}
const formData = parsedData.data || {};
let restoredCount = 0;
// Restaurer les valeurs
Object.keys(formData).forEach(name => {
const $field = jQuery('form.form-submit').find(`[name="${name}"]`);
if ($field.length === 0) return;
const value = formData[name];
const type = $field.attr('type');
switch (type) {
case 'checkbox':
if (value) {
$field.prop('checked', true);
}
break;
case 'radio':
$field.filter(`[value="${value}"]`).prop('checked', true);
break;
default:
$field.val(value);
break;
}
// Ajouter un effet visuel temporaire
$field.addClass('field-restored');
setTimeout(() => {
$field.removeClass('field-restored');
}, 2000);
restoredCount++;
});
console.log(`${restoredCount} champs restaurés depuis localStorage`);
if (restoredCount > 0) {
showSaveIndicator(`${restoredCount} champs restaurés`, 'success');
}
return restoredCount > 0;
} catch (e) {
console.error('Erreur lors de la restauration localStorage:', e);
return false;
}
}
/**
* Efface les données du formulaire du localStorage
*/
function clearFormData() {
try {
localStorage.removeItem(FORM_STORAGE_KEY);
localStorage.removeItem(FORM_STORAGE_TIMESTAMP);
console.log('Données localStorage effacées');
// Masquer le message d'information
jQuery('.localstorage-info').fadeOut();
// Afficher un message de confirmation
showSaveIndicator('Données effacées', 'success');
} catch (e) {
console.error('Erreur lors de l\'effacement localStorage:', e);
showSaveIndicator('Erreur lors de l\'effacement', 'error');
}
}
// Rendre la fonction accessible globalement
window.clearFormData = clearFormData;
/**
* Détermine l'étape actuelle basée sur l'URL
*/
function getCurrentStep() {
const path = window.location.pathname;
if (path.includes('credit-step1')) return 'step1';
if (path.includes('credit-step2')) return 'step2';
if (path.includes('credit-step3')) return 'step3';
if (path.includes('credit-step4')) return 'step4';
if (path.includes('credit-step5')) return 'step5';
return 'unknown';
}
/**
* Sauvegarde automatique lors de la modification des champs
*/
function setupAutoSave() {
// Sauvegarde sur clic du lien "previous-step"
jQuery('a.previous-step').on('click', function(e) {
/* e.preventDefault(); */
saveFormData();
});
// Sauvegarde sur changement de valeur (désactivé)
// jQuery('form.form-submit').on('change input', 'input, select, textarea', function() {
// // Debounce pour éviter trop de sauvegardes
// clearTimeout(window.autoSaveTimeout);
// window.autoSaveTimeout = setTimeout(saveFormData, 1000);
// });
// Sauvegarde sur clic des boutons radio/checkbox (désactivé)
// jQuery('form.form-submit').on('click', 'input[type="radio"], input[type="checkbox"]', function() {
// setTimeout(saveFormData, 100);
// });
// Sauvegarde avant soumission du formulaire (désactivé)
// jQuery('form.form-submit').on('submit', function() {
// saveFormData();
// });
// Sauvegarde avant navigation (bouton étape précédente) (désactivé)
// jQuery('a[href*="credit-step"]').on('click', function() {
// saveFormData();
// });
// Sauvegarde lors de l'ajout/suppression de crédits en cours (désactivé)
// $(document).on('currentLoanAdded currentLoanRemoved', function() {
// setTimeout(saveFormData, 500);
// });
}
/**
* Affiche le message d'information localStorage
*/
function showLocalStorageInfo() {
const savedData = localStorage.getItem(FORM_STORAGE_KEY);
if (!savedData) return;
// Vérifier si le message existe déjà
if (jQuery('.localstorage-info').length > 0) return;
const infoHtml = `
<div class="localstorage-info">
<span class="icon">💾</span>
Vos données sont sauvegardées automatiquement.
<button class="clear-storage-btn" onclick="clearFormData()">Effacer</button>
</div>
`;
// Insérer au début du formulaire
jQuery('form.form-submit').prepend(infoHtml);
}
/**
* Initialise le système de sauvegarde
*/
function initFormStorage() {
if(hasCreditDirectToken())
return;
//check if localStorage is empty
if(localStorage.getItem(FORM_STORAGE_KEY) === null)
return;
// Restaurer les données au chargement
const restored = restoreFormData();
// Configurer la sauvegarde automatique
setupAutoSave();
// Effacer les données après soumission réussie (optionnel)
jQuery(document).on('formSubmitted', function() {
clearFormData();
});
// Si des données ont été restaurées, initialiser l'affichage des zones conditionnelles
if (restored) {
setTimeout(function() {
initializePreFilledValues();
}, 200);
}
// Afficher le message d'information
showLocalStorageInfo();
console.log('Système de sauvegarde localStorage initialisé');
}
function hasCreditDirectToken() {
return window.location.search.includes('credit-direct-token');
}
// Initialiser le système de sauvegarde UNIQUEMENT si le paramètre est présent dans l'URL
initFormStorage();
if (hasCreditDirectToken()) {
}
/**
* General
*/
function empty(value) { return value == undefined || value == null || value == [] || value == ''; }
function makeLabelRequired(containerSelector = 'body') {
if (jQuery(containerSelector).length > 0) {
jQuery(containerSelector).find('input:required, select:required, textarea:required').each(function() {
var labelId = jQuery(this).attr('id');
var label = jQuery('label[for="' + labelId + '"]')
if (label.length > 0 && label.html().charAt(label.html().length - 1) !== '*') {
label.html(label.html() + '*')
}
})
}
}
if (jQuery('.wpcf-borrower').length > 0) {
makeLabelRequired('.wpcf-borrower')
} else {
makeLabelRequired('.form-submit')
}
/**
* Step 2
*/
function changeJobLabels(value, container) {
var jobLabels = {
independent: {
factory: 'de l\'entreprise',
salary: 'Revenu imposable annuel',
startDate: 'de début d\'activité'
},
withoutEmployer: {
employer: 'de l\'employeur/organisme de paiement',
salary: 'Indemnités mensuelles',
startDate: 'd\'engagement'
},
withEmployer: {
employer: 'de l\'employeur/organisme de paiement',
salary: 'Salaire net mensuel',
startDate: 'd\'engagement'
}
}, job = {
independent: 5,
withoutEmployer: ['1','6','9','12']
};
console.log('job', value, job.independent);
var prefix = container.find('#IDcofirstname').length > 0 ? 'co' : ''
var fields = ['emname', 'emaddress', 'emzip', 'emcity', 'emcountry', 'commitmentdate', 'salary']
fields.forEach(id => {
var labelText = null
switch (id) {
case 'commitmentdate':
if(value === job.independent) {
labelText = jobLabels.independent.startDate
} else if(job.withoutEmployer.includes(value)) {
labelText = jobLabels.withoutEmployer.startDate
} else {
labelText = jobLabels.withEmployer.startDate
}
break;
case 'salary':
if(value === job.independent) {
labelText = jobLabels.independent.salary
} else if(job.withoutEmployer.includes(value)) {
labelText = jobLabels.withoutEmployer.salary
} else {
labelText = jobLabels.withEmployer.salary
}
break;
default:
if(value === job.independent) {
labelText = jobLabels.independent.factory
} else if(job.withoutEmployer.includes(value)) {
labelText = jobLabels.withoutEmployer.employer
} else {
labelText = jobLabels.withEmployer.employer
}
break;
}
container.find('label[for="ID' + prefix + id + '"] > span').text(labelText);
console.log('labelText', labelText);
});
/* console.log('container', container);
console.log('prefix', container.find('.'+prefix+'independent_section')); */
console.log('value', value);
if(value == job.independent) {
container.find('.'+prefix+'independent_section').fadeIn().removeClass('hidden');
//remove required attributes
container.find('.'+prefix+'employee_section').find('input, select').removeAttr('required');
container.find('.'+prefix+'employee_section').fadeOut().addClass('hidden');
container.find('.'+prefix+'independent_section').find('input, select').attr('required', true);
} else if(job.withoutEmployer.includes(value)) {
container.find('.withemployer_section').fadeOut().addClass('hidden');
container.find('.withemployer_section').find('input, select').removeAttr('required');
console.log((jobLabels.withoutEmployer.salary));
/* container.find('.'+prefix+'IDsalary').prev().text(jobLabels.withoutEmployer.salary);
console.log(container.find('#'+prefix+'IDsalary').prev()); */
} else {
container.find('.'+prefix+'independent_section').fadeOut().addClass('hidden');
//not input field required
container.find('.'+prefix+'employee_section').find('input:not([type="file"]), select').attr('required', true);
container.find('.'+prefix+'employee_section').fadeIn().removeClass('hidden');
//except file inputs
container.find('.'+prefix+'independent_section').find('input:not([type="file"]), select').removeAttr('required');
if(jQuery('.withemployer_section').hasClass('hidden')) {
jQuery('.withemployer_section').fadeIn().removeClass('hidden');
jQuery('.withemployer_section').find('input, select').attr('required', true);
}
}
container
.find('#ID' + prefix + 'emnumber')
.attr('required', value === job.independent)
.parent()
.toggleClass('d-none', value !== job.independent)
makeLabelRequired()
}
function displayCoBorrower() {
var
excludedFieldsName = [
'cocontract_type',
'coemname',
'coemaddress',
'coemzip',
'coemcity',
'coemcountry',
'cocommitmentdate',
'cooiamouthmealvoucher',
'cooiamouthrentalincome',
'cooiamouthunemployment',
'cooiamouthother',
'cooiothertext',
'co_secteur_activite',
'co_num_tva',
'coMtn_loyer'
],
hasCoBorrower =
jQuery('input[name="hascoborrower"]:checked').length > 0 &&
jQuery('input[name="hascoborrower"]:checked').val() == 1,
key = '.wpcf-coborrower',
cols_key = '.credit-cols';
console.log('hasCoBorrower', hasCoBorrower);
// Gestion de l'affichage/masquage
jQuery(key).toggleClass('d-none', !hasCoBorrower);
// Gestion des colonnes
if (hasCoBorrower) {
// Mode deux colonnes
jQuery(cols_key).removeClass('col-md-12').addClass('col-md-6');
// Ajuster les colonnes internes
jQuery('.credit-cols [class*="col-md-"]').each(function() {
var classes = jQuery(this).attr('class').split(' ');
classes.forEach(function(className) {
if (className.startsWith('col-md-')) {
var currentSize = parseInt(className.replace('col-md-', ''));
console.log('currentSize', currentSize);
// Sauvegarder la taille originale si ce n'est pas déjà fait
if (!jQuery(this).data('original-size')) {
jQuery(this).data('original-size', className);
}
// Définir la nouvelle taille
jQuery(this).removeClass(className).addClass('col-md-12');
}
}.bind(this));
});
} else {
// Mode une colonne
jQuery('.credit-cols .wpcf-borrower').removeClass('col-md-6');
if(!jQuery(cols_key).hasClass('col-md-12'))
jQuery(cols_key).addClass('col-md-12').removeClass('col-md-6');
// Restaurer les colonnes internes à leur taille d'origine
jQuery('.credit-cols [class*="col-md-"]').each(function() {
var originalSize = jQuery(this).data('original-size');
if (originalSize) {
// Supprimer toutes les classes col-md-* actuelles
var classes = jQuery(this).attr('class').split(' ');
classes.forEach(function(className) {
if (className.startsWith('col-md-')) {
jQuery(this).removeClass(className);
}
}.bind(this));
// Restaurer la taille originale
jQuery(this).addClass(originalSize);
}
});
}
// Gestion des champs requis
jQuery(key).find('input[type="text"], input[type="number"], input[type="date"], select, textarea').each(function() {
if (excludedFieldsName.indexOf(jQuery(this).attr('name')) < 0) {
jQuery(this).attr('required', hasCoBorrower)
}
})
if (!hasCoBorrower) {
jQuery(key).find('input[type="checkbox"]:checked, input[type="radio"][value="0"]').each(function() {
jQuery(this).prop('checked', jQuery(this).attr('type') === 'radio')
})
jQuery(key).find('input:not([type="checkbox"]):not([type="radio"]), select, textarea').each(function() {
jQuery(this).val('')
})
}
makeLabelRequired(key)
displayOtherIncome(
hasCoBorrower && jQuery('input[name="cohasotherincome"]:checked').length > 0 && jQuery('input[name="cohasotherincome"]:checked').val() == 1,
'.co'
)
}
function displayOtherIncome(show, key) {
var target = jQuery('.wpcf-otherincome' + key)
if (target.length > 0) {
target.toggleClass('d-none', !show);
if (!show) {
target.find('input[type="checkbox"]:checked, input[type="radio"][value="0"]').each(function() {
jQuery(this).prop('checked', jQuery(this).attr('type') === 'radio')
})
}
displayOtherIncomeSubFields(target.find('input[type="checkbox"], input[type="radio"]:checked'))
}
}
function displayOtherIncomeSubFields(el) {
el.each(function() {
var subFields = jQuery(this).closest('.form-row').find('.form-group')
if (subFields.length > 0) {
subFields.toggleClass('d-none', !jQuery(this).is(':checked'))
subFields.find('input').attr('required', jQuery(this).is(':checked'))
}
})
}
function initializePreFilledValues() {
// Gérer l'affichage des sections basé sur les valeurs pré-remplies
setTimeout(function() {
// Vérifier si hascoborrower est pré-rempli
var hasCoBorrowerChecked = jQuery('input[name="hascoborrower"]:checked');
if (hasCoBorrowerChecked.length > 0) {
displayCoBorrower();
}
// Vérifier si hasotherincome est pré-rempli (emprunteur)
var hasOtherIncomeChecked = jQuery('input[name="hasotherincome"]:checked');
if (hasOtherIncomeChecked.length > 0) {
displayOtherIncome(hasOtherIncomeChecked.val() == 1, '.em');
}
// Vérifier si cohasotherincome est pré-rempli (co-emprunteur)
var coHasOtherIncomeChecked = jQuery('input[name="cohasotherincome"]:checked');
if (coHasOtherIncomeChecked.length > 0) {
displayOtherIncome(coHasOtherIncomeChecked.val() == 1, '.co');
}
// Vérifier si hascurrentloan est pré-rempli
var hasCurrentLoanChecked = jQuery('input[name="hascurrentloan"]:checked');
if (hasCurrentLoanChecked.length > 0) {
var isChecked = hasCurrentLoanChecked.val() == '1';
jQuery('.wpcf-currentloan').toggleClass('d-none', !isChecked);
}
// Vérifier si cohascurrentloan est pré-rempli
var coHasCurrentLoanChecked = jQuery('input[name="cohascurrentloan"]:checked');
if (coHasCurrentLoanChecked.length > 0) {
var isChecked = coHasCurrentLoanChecked.val() == '1';
jQuery('.wpcf-cocurrentloan').toggleClass('d-none', !isChecked);
}
// Gérer les champs autres revenus pré-remplis
jQuery('.wpcf-otherincome input[type="checkbox"]:checked').each(function() {
displayOtherIncomeSubFields(jQuery(this));
});
// Gérer les champs indépendant pré-remplis
var jobSelect = jQuery('select[name="job"]');
if (jobSelect.length > 0 && jobSelect.val()) {
changeJobLabels(jobSelect.val(), jobSelect.closest('fieldset'));
}
var coJobSelect = jQuery('select[name="cojob"]');
if (coJobSelect.length > 0 && coJobSelect.val()) {
changeJobLabels(coJobSelect.val(), coJobSelect.closest('fieldset'));
}
}, 100); // Petit délai pour s'assurer que le DOM est chargé
}
var hasCoBorrowerField = jQuery('input[name="hascoborrower"]:checked')
if (hasCoBorrowerField.length > 0) {
displayCoBorrower()
}
if (jQuery('input[name="hasotherincome"]:checked').length > 0) {
displayOtherIncome(jQuery('input[name="hasotherincome"]:checked').val() == 1, '.em')
}
// Initialisation pour les valeurs pré-remplies
initializePreFilledValues();
jQuery('body').on('change', 'input[name="hascoborrower"]', displayCoBorrower);
jQuery('body').on('change', 'input[name="hasotherincome"]', function() {
displayOtherIncome(jQuery(this).val() == 1, '.em')
});
jQuery('body').on('change', 'input.wpcf-otherincome--oitype', function(e) {
displayOtherIncomeSubFields(jQuery(e.target))
});
jQuery('body').on('change', 'input[name="cohasotherincome"]', function() {
displayOtherIncome(jQuery(this).val() == 1, '.co')
});
jQuery('body').on('change', 'select[name="job"], select[name="cojob"]', function() {
changeJobLabels(jQuery(this).val(), jQuery(this).closest('fieldset'))
});
/**
* Step 3
*/
jQuery('body').on('change', 'select[name="hometype"], select[name="cohometype"]', function(e) {
var val = jQuery(this).val(),
c = 'd-none',
cname = 'wpcf-' + jQuery(this).attr('name') + '--complement-home' + val,
elements = jQuery('.wpcf-' + jQuery(this).attr('name') + '--complement .form-group');
elements.addClass(c);
elements.each(function() {
if (jQuery(this).hasClass(cname)) {
jQuery('.' + cname).removeClass(c);
}
jQuery(this).find('input, select').attr('required', !jQuery(this).hasClass(c))
makeLabelRequired(jQuery(this).context)
})
});
var currentLoanProto = jQuery('.wpcf-currentloan--block').length > 0 ? jQuery('.wpcf-currentloan--block') : null;
var currentLoanCount = 0;
if (currentLoanProto !== null) {
currentLoanProto.removeClass('wpcf-prototype');
currentLoanProto = currentLoanProto[0].outerHTML
jQuery('.wpcf-currentloan--block').remove()
}
var coCurrentLoanProto = jQuery('.wpcf-cocurrentloan--block').length > 0 ? jQuery('.wpcf-cocurrentloan--block') : null;
var coCurrentLoanCount = 0;
if (coCurrentLoanProto !== null) {
coCurrentLoanProto.removeClass('wpcf-prototype');
coCurrentLoanProto = coCurrentLoanProto[0].outerHTML
jQuery('.wpcf-cocurrentloan--block').remove()
}
jQuery('body').on('change', 'input[name="hascurrentloan"], input[name="cohascurrentloan"]', function(e) {
var selector = jQuery(this).attr('name') === 'hascurrentloan' ? '.wpcf-currentloan' : '.wpcf-cocurrentloan';
var elem = jQuery(selector),
c = 'd-none';
// Pour les radio, on vérifie la value sélectionnée
var isChecked = jQuery('input[name="' + jQuery(this).attr('name') + '"]:checked').val() == '1';
elem.toggleClass(c, !isChecked);
if (!isChecked) {
jQuery(this).attr('name') === 'hascurrentloan' ? jQuery('.wpcf-currentloan--block').remove() : jQuery('.wpcf-cocurrentloan--block').remove();
} else if (elem.find(selector + '--block').length < 1) {
jQuery(this).attr('name') === 'hascurrentloan' ? addCurrentLoan() : addCoCurrentLoan();
}
});
// Affichage initial au chargement de la page
function updateCurrentLoanVisibility() {
var isChecked = jQuery('input[name="hascurrentloan"]:checked').val() == '1';
jQuery('.wpcf-currentloan').toggleClass('d-none', !isChecked);
if (!isChecked) {
jQuery('.wpcf-currentloan--block').remove();
} else if (jQuery('.wpcf-currentloan--block').length < 1) {
addCurrentLoan();
}
var isCoChecked = jQuery('input[name="cohascurrentloan"]:checked').val() == '1';
jQuery('.wpcf-cocurrentloan').toggleClass('d-none', !isCoChecked);
if (!isCoChecked) {
jQuery('.wpcf-cocurrentloan--block').remove();
} else if (jQuery('.wpcf-cocurrentloan--block').length < 1) {
addCoCurrentLoan();
}
}
// Appel au chargement
updateCurrentLoanVisibility();
jQuery('body').on('click', 'button.wpcf-currentload--add, button.wpcf-cocurrentload--add', function(e) {
e.preventDefault()
jQuery(this).hasClass('wpcf-currentload--add') ? addCurrentLoan() : addCoCurrentLoan()
})
function addCurrentLoan() {
var newLoan = currentLoanProto.replaceAll('__number__', currentLoanCount)
jQuery(newLoan).insertBefore(jQuery('.wpcf-currentload--add'))
currentLoanCount++
// Déclencher l'événement personnalisé pour la sauvegarde
$(document).trigger('currentLoanAdded');
}
function addCoCurrentLoan() {
var newLoan = coCurrentLoanProto.replaceAll('__number__', coCurrentLoanCount)
jQuery(newLoan).insertBefore(jQuery('.wpcf-cocurrentload--add'))
coCurrentLoanCount++
// Déclencher l'événement personnalisé pour la sauvegarde
$(document).trigger('currentLoanAdded');
}
jQuery('body').on('click', '.wpcf-currentloan--block--remove, .wpcf-cocurrentloan--block--remove', function(e) {
e.preventDefault();
jQuery(this).parent().remove();
// Déclencher l'événement personnalisé pour la sauvegarde
$(document).trigger('currentLoanRemoved');
});
// Fonction pour afficher/cacher la zone isFichedDisplay
function displayIsFichedZone() {
var hasFiched = jQuery('input[name="isFiched"]:checked').length > 0 &&
jQuery('input[name="isFiched"]:checked').val() == 1;
jQuery('.isFichedDisplay').toggleClass('d-none', !hasFiched);
}
// Vérifier l'état initial
var isFichedField = jQuery('input[name="isFiched"]:checked');
if (isFichedField.length > 0) {
displayIsFichedZone();
}
// Ajouter l'écouteur d'événement pour le changement
jQuery('body').on('change', 'input[name="isFiched"]', displayIsFichedZone);
// Fonction pour afficher/cacher la zone isIndependant
function displayIsIndependantZone() {
var isIndependant = jQuery('select[name="job"]').val() === '5';
jQuery('.isIndependant').toggleClass('d-none', !isIndependant);
}
// Vérifier l'état initial
var jobSelect = jQuery('select[name="job"]');
if (jobSelect.length > 0) {
displayIsIndependantZone();
}
// Ajouter l'écouteur d'événement pour le changement
jQuery('body').on('change', 'select[name="job"]', displayIsIndependantZone);
// Fonction pour afficher/cacher la zone hasLoyer
function displayHasLoyerZone() {
var isLocataire = jQuery('select[name="housing_status"]').val() === 'locataire';
jQuery('.hasLoyer').toggleClass('d-none', !isLocataire);
}
// Vérifier l'état initial
var situationSelect = jQuery('select[name="housing_status"]');
if (situationSelect.length > 0) {
displayHasLoyerZone();
}
// Ajouter l'écouteur d'événement pour le changement
jQuery('body').on('change', 'select[name="housing_status"]', displayHasLoyerZone);
// Affichage de la taille totale des fichiers sélectionnés pour le champ IDpaycheck + vérification taille max 2 Mo
jQuery('body').on('change', '#IDpaycheck, #IDcopaycheck', function(e) {
var files = e.target.files;
var totalSize = 0;
var maxSize = 2 * 1024 * 1024; // 2 Mo en octets
var errorFiles = [];
for (var i = 0; i < files.length; i++) {
totalSize += files[i].size;
if (files[i].size > maxSize) {
errorFiles.push(files[i].name);
}
}
// Conversion en Mo, arrondi à 2 décimales
var totalSizeMo = (totalSize / (1024 * 1024)).toFixed(2);
// Création ou sélection de l'élément d'affichage
var infoId = 'paycheck-size-info';
var infoElem = jQuery('#' + infoId);
if (infoElem.length === 0) {
infoElem = jQuery('<div id="' + infoId + '" style="font-size:0.9em;color:#555;"></div>');
jQuery(this).after(infoElem);
}
// Création ou sélection de l'élément d'erreur
var errorId = 'paycheck-size-error';
var errorElem = jQuery('#' + errorId);
if (errorElem.length === 0) {
errorElem = jQuery('<div id="' + errorId + '" style="font-size:0.95em;color:#c00;"></div>');
infoElem.after(errorElem);
}
var submitBtn = jQuery('.form-submit button[type="submit"]');
if (files.length > 0) {
infoElem.text('Taille totale des fichiers sélectionnés : ' + totalSizeMo + ' Mo');
} else {
infoElem.text('');
}
if (errorFiles.length > 0) {
errorElem.html('Fichier(s) trop volumineux (> 2 Mo) :<br><b>' + errorFiles.join(', ') + '</b>');
submitBtn.prop('disabled', true);
} else {
errorElem.text('');
submitBtn.prop('disabled', false);
}
});
// Affichage conditionnel du champ "fonds propres" selon le choix Oui/Non avec effet slide
const yesRadio = document.getElementById('estateequity_yes');
const noRadio = document.getElementById('estateequity_no');
if (yesRadio && noRadio) {
$(yesRadio).on('change', function() {
if (yesRadio.checked) {
$('.fonds-propres').stop(true, true).slideDown();
$('[name="estateequity"]').prop('required', true);
}
});
$(noRadio).on('change', function() {
if (noRadio.checked) {
$('.fonds-propres').stop(true, true).slideUp();
$('[name="estateequity"]').prop('required', false);
}
});
// Initialisation à l'ouverture de la page
if (yesRadio.checked) {
$('.fonds-propres').show();
} else {
$('.fonds-propres').hide();
}
}
// Variables pour le debouncing des inputs
let capitalTimeout;
let durationTimeout;
let isCreditCalculationEnabled = true;
if(jQuery('#creditCalcManualSwitch').length > 0)
isCreditCalculationEnabled = true;
// Liste des types de crédit qui utilisent des années
const LOAN_TYPES_IN_YEARS = ['am', 'amr', 'cied', 'ph'];
// Fonction pour mettre à jour l'affichage des valeurs calculées
function updateCreditDisplay(result) {
console.log('updateCreditDisplay - result:', result);
// Calcul du TAEG
const taeg = parseFloat(result.taux_nominal_annuel.replace('%', ''));
const taux_debiteur = (taeg * 0.11 + taeg).toFixed(2);
// Mise à jour des champs cachés
jQuery('input[name="capital"]').val(result.capital);
jQuery('input[name="duree"]').val(result.duree);
jQuery('input[name="cout_total"]').val(result.cout_total);
jQuery('input[name="mensualite"]').val(result.mensualite);
jQuery('input[name="taux_nominal_annuel"]').val(result.taux_nominal_annuel);
console.log('updateCreditDisplay - Champs cachés mis à jour:', {
capital: result.capital,
duree: result.duree,
cout_total: result.cout_total,
mensualite: result.mensualite,
taux: result.taux_nominal_annuel
});
// Mise à jour de l'affichage dans .credit-info
jQuery('.credit-info .credit-item').each(function() {
var $value = jQuery(this).find('.credit-value');
var $label = jQuery(this).find('.credit-label');
if($label.text().includes('Montant:')) {
$value.text(result.capital + ' €');
}
else if($label.text().includes('Durée:')) {
$value.text(result.duree + ($('input[name="type_credit"]').val() === 'am' ? ' ans' : ' mois'));
}
else if($label.text().includes('Mensualité:')) {
$value.text(result.mensualite + '€');
}
else if($label.text().includes('Coût total:')) {
$value.text(result.cout_total + '€');
}
else if($label.text().includes('TAEG:')) {
$value.text(taux_debiteur + '%');
}
else if($label.text().includes('Taux débiteur:')) {
$value.text(result.taux_nominal_annuel);
}
});
// Mise à jour du récapitulatif dans .info-credits-step
jQuery('.info-credits-step .row > div').each(function() {
$(this).find('p').each(function() {
var $label = $(this);
var $value = $label.next('span');
if($label.text().includes('Montant emprunté :')) {
$value.text(result.capital + ' €');
}
else if($label.text().includes('Durée :')) {
$value.text(result.duree + ($('input[name="type_credit"]').val() === 'am' ? ' ans' : ' mois'));
}
else if($label.text().includes('Mensualité :')) {
$value.text(result.mensualite + ' €');
}
else if($label.text().includes('Coût Total :')) {
$value.text(result.cout_total + ' €');
}
else if($label.text().includes('Taux débiteur :')) {
$value.text(result.taux_nominal_annuel);
}
else if($label.text().includes('Taeg :')) {
$value.text(taux_debiteur + '%');
}
});
});
console.log('updateCreditDisplay - Affichage mis à jour');
}
// Fonction pour mettre à jour les limites et valeurs des champs selon le type de crédit
function updateFieldLimits(selectedType) {
const creditType = map_values[selectedType];
if (!creditType) {
console.warn('Type de crédit non reconnu:', selectedType);
return;
}
const $capitalField = jQuery('#IDbatiment_emprunt');
const $durationField = jQuery('#IDbatiment_duree');
let currentCapital = parseFloat($capitalField.val());
// Récupérer les limites depuis form_sliders pour les durées
const sliderConfig = form_sliders[creditType];
if (!sliderConfig) {
console.warn('Configuration slider non trouvée pour:', creditType);
return;
}
// Récupérer les limites spécifiques du crédit depuis cd_js.groups
const creditConfig = cd_js.groups[selectedType];
if (creditConfig && creditConfig.capital_max) {
// Ne modifier le montant que s'il dépasse la limite du crédit choisi
if (currentCapital > creditConfig.capital_max) {
currentCapital = creditConfig.capital_selected || creditConfig.capital_max;
$capitalField.val(currentCapital);
}
}
// Mettre à jour les attributs min/max du champ capital
$capitalField.attr('min', sliderConfig.capital_min);
$capitalField.attr('max', sliderConfig.capital_max);
$capitalField.attr('step', sliderConfig.capital_step || 100);
// Ajuster la valeur du capital si nécessaire selon les limites du slider
if (currentCapital > sliderConfig.capital_max) {
currentCapital = sliderConfig.capital_max;
$capitalField.val(currentCapital);
} else if (currentCapital < sliderConfig.capital_min) {
currentCapital = sliderConfig.capital_min;
$capitalField.val(currentCapital);
}
// Déterminer la durée maximale disponible pour ce montant
const isYearlyDuration = LOAN_TYPES_IN_YEARS.includes(creditType);
let maxDurationForAmount = sliderConfig.durees[sliderConfig.durees.length - 1];
// Parcourir les durées disponibles dans l'ordre décroissant
for (let i = sliderConfig.durees.length - 1; i >= 0; i--) {
const duration = sliderConfig.durees[i];
// Vérifier si cette durée est valide pour le montant actuel
if (currentCapital >= sliderConfig.capital_min && currentCapital <= sliderConfig.capital_max) {
maxDurationForAmount = duration;
break;
}
}
// Convertir la durée maximale en années si nécessaire
const displayDuration = isYearlyDuration ? Math.floor(maxDurationForAmount / 12) : maxDurationForAmount;
const minDuration = isYearlyDuration ? Math.ceil(sliderConfig.duree_min / 12) : sliderConfig.duree_min;
const maxDuration = isYearlyDuration ? Math.floor(sliderConfig.duree_max / 12) : sliderConfig.duree_max;
// Mettre à jour les attributs min/max du champ durée
$durationField.attr('min', minDuration);
$durationField.attr('max', maxDuration);
// Définir la durée maximale disponible
$durationField.val(displayDuration);
// Mettre à jour l'unité dans l'input-group-text
jQuery('.input-group-text').text(isYearlyDuration ? 'Ans' : 'Mois');
// Mettre à jour l'affichage
calculateCredit();
// Mettre à jour le champ caché type_credit
jQuery('input[name="type_credit"]').val(creditType);
}
// Gestionnaire pour le changement de type de crédit
jQuery('#IDestateloantype').on('change', function() {
const creditType = jQuery(this).val();
if (creditType) {
updateFieldLimits(creditType);
calculateCredit();
}
});
// Fonction pour arrondir le capital à la valeur acceptable la plus proche
function snapCapitalValue(value, creditType) {
if (!creditType || !form_sliders[creditType]) {
return value;
}
const sliderConfig = form_sliders[creditType];
// Utiliser le step défini dans form_sliders
const step = sliderConfig.capital_step || 100;
// S'assurer que la valeur est dans les limites
value = Math.max(sliderConfig.capital_min, Math.min(value, sliderConfig.capital_max));
// Arrondir à la valeur la plus proche selon le step
return Math.round(value / step) * step;
}
// Fonction pour arrondir la durée à la valeur acceptable la plus proche
function snapDurationValue(value, creditType) {
if (!creditType || !form_sliders[creditType]) {
return value;
}
const sliderConfig = form_sliders[creditType];
const isYearlyDuration = LOAN_TYPES_IN_YEARS.includes(creditType);
console.log('snapDurationValue - value:', value);
console.log('snapDurationValue - creditType:', creditType);
console.log('snapDurationValue - isYearlyDuration:', isYearlyDuration);
if (isYearlyDuration) {
// Pour les crédits en années, on vérifie juste les limites min/max
// Les limites sont déjà en années pour ces types de crédit
const minYears = sliderConfig.duree_min;
const maxYears = sliderConfig.duree_max;
console.log('snapDurationValue - minYears:', minYears);
console.log('snapDurationValue - maxYears:', maxYears);
if (value > maxYears) return maxYears;
if (value < minYears) return minYears;
return value;
} else {
// Pour les autres crédits, on cherche la durée disponible la plus proche
let closestDuration = sliderConfig.durees[0];
let minDiff = Math.abs(value - sliderConfig.durees[0]);
for (let i = 1; i < sliderConfig.durees.length; i++) {
const diff = Math.abs(value - sliderConfig.durees[i]);
if (diff < minDiff) {
minDiff = diff;
closestDuration = sliderConfig.durees[i];
}
}
return closestDuration;
}
}
// Fonction pour calculer la mensualité
function calc_mens(mnt, dur, taeg) {
const creditType = jQuery('input[name="type_credit"]').val();
// Pour le crédit pont, on ne calcule que les intérêts mensuels
if (creditType === 'cdp') {
const t100 = taeg / 100;
// Calcul des intérêts mensuels uniquement : (capital * taux_annuel) / 12
const mens = (mnt * t100) / 12;
return Math.floor(mens * 100) / 100;
}
// Pour les autres types de crédit, calcul normal
const t100 = taeg / 100;
const t101 = 1 + t100;
const d12 = 1 / 12;
const dur12 = dur / 12;
const buf1 = Math.pow(t101, d12);
const buf2 = Math.pow(1 / t101, dur12);
const mens = (mnt * (buf1 - 1)) / (1 - buf2);
return Math.floor(mens * 100) / 100;
}
// Notre propre fonction de calcul qui utilise les fonctions de base de cd_main.js
function calculateCredit() {
const capital = parseFloat(jQuery('#IDbatiment_emprunt').val());
const duration = parseInt(jQuery('#IDbatiment_duree').val());
const selectedType = jQuery('#IDestateloantype').val();
const creditType = map_values[selectedType];
console.log('=== Début calcul crédit ===');
console.log('Type sélectionné:', selectedType);
console.log('Type de crédit mappé:', creditType);
console.log('Capital:', capital);
console.log('Durée:', duration);
if (isNaN(capital) || isNaN(duration) || !creditType) {
console.warn('Valeurs invalides pour le calcul:', {
capital: isNaN(capital) ? 'invalide' : capital,
duration: isNaN(duration) ? 'invalide' : duration,
selectedType,
creditType: !creditType ? 'non mappé' : creditType
});
return;
}
// Convertir la durée en mois si nécessaire pour les calculs
const isYearlyDuration = LOAN_TYPES_IN_YEARS.includes(creditType);
const durationForCalculation = isYearlyDuration ? duration * 12 : duration;
console.log('Durée pour calcul:', durationForCalculation, isYearlyDuration ? '(en années)' : '(en mois)');
let results;
// Appeler la fonction de calcul appropriée
switch(creditType) {
case 'pat':
results = calculate_pat(capital, duration);
break;
case 'am':
results = calculate_am(capital, duration);
break;
case 'ph':
results = calculate_ph(capital, duration);
break;
case 'amr':
case 'cdp':
case 'cied':
results = calculate_mono_rate_bt_10_30(creditType, capital, duration);
break;
case 'fin_neuve':
results = calculate_fin_neuve(capital, duration);
break;
case 'fin_occ_m3a':
results = calculate_pao_m_3(capital, duration);
break;
case 'fin_occ_p3a':
results = calculate_pao_p_3(capital, duration);
break;
case 'mobil_carav':
results = calculate_mobilhome(capital, duration);
break;
case 'regroup_cred':
results = calculate_regroupement_de_credit(capital, duration);
break;
case 'frais_notaire':
results = calculate_frais_notaire(capital, duration);
break;
case 'but_immo':
results = calculate_but_immo(capital, duration);
break;
default:
console.warn('Type de crédit non reconnu:', creditType);
results = calculate_pat(capital, duration);
}
if (!results) {
console.warn('Pas de résultats retournés par la fonction de calcul');
return;
}
console.log('Résultats bruts:', results);
// Extraire les valeurs des résultats
const [min_duration, max_duration, selected_duration, duree_in_range, taux_nominal] = results;
// Convertir le taux en nombre si c'est une chaîne
const taux = parseFloat(String(taux_nominal).replace('%', ''));
if (isNaN(taux)) {
console.error('Taux nominal invalide après conversion:', {
original: taux_nominal,
converti: taux
});
return;
}
console.log('Taux nominal (débiteur):', taux + '%');
console.log('Durée sélectionnée:', selected_duration, isYearlyDuration ? 'mois (convertie)' : 'mois');
// Pour les crédits en années, la durée retournée est déjà en mois
const durationInMonths = isYearlyDuration ? durationForCalculation : selected_duration;
// Calculer la mensualité avec notre fonction locale
const mensualite = calc_mens(capital, durationInMonths, taux);
if (isNaN(mensualite)) {
console.error('Erreur dans le calcul de la mensualité:', {
capital,
durationInMonths,
taux
});
return;
}
const cout_total = (mensualite * durationInMonths).toFixed(2);
console.log('Mensualité calculée:', mensualite.toFixed(2) + '€');
console.log('Coût total calculé:', cout_total + '€');
// Créer l'objet result pour updateCreditDisplay
const displayResult = {
capital: capital,
duree: duration,
mensualite: mensualite.toFixed(2),
cout_total: cout_total,
taux_nominal_annuel: taux.toFixed(2) + ' %',
taux_debiteur: taux.toFixed(2) + ' %'
};
console.log('Résultat final pour affichage:', displayResult);
console.log('--- Fin calcul crédit ---');
// Mettre à jour l'affichage
updateCreditDisplay(displayResult);
// Mettre à jour le champ caché type_credit
jQuery('input[name="type_credit"]').val(creditType);
}
if(isCreditCalculationEnabled) {
// Remplacer tous les appels à calculate_mensualite par calculateCredit
jQuery('#IDbatiment_emprunt')
.on('input', function() {
const $this = jQuery(this);
clearTimeout(capitalTimeout);
if ($this.val() !== '') {
capitalTimeout = setTimeout(() => {
let capital = parseFloat($this.val());
if (!isNaN(capital)) {
const creditType = jQuery('input[name="type_credit"]').val();
const snappedValue = snapCapitalValue(capital, creditType);
if (snappedValue !== capital) {
$this.val(snappedValue);
}
calculateCredit();
}
}, 500); // Délai un peu plus long pour laisser le temps de taper
}
})
.on('change', function() {
// Validation finale quand on quitte le champ (onblur)
const $this = jQuery(this);
if ($this.val() !== '') {
let capital = parseFloat($this.val());
if (!isNaN(capital)) {
const selectedType = jQuery('#IDestateloantype').val();
const creditConfig = cd_js.groups[selectedType];
// Vérifier les limites du crédit
if (creditConfig && creditConfig.capital_max && capital > creditConfig.capital_max) {
capital = creditConfig.capital_selected || creditConfig.capital_max;
$this.val(capital);
}
// Snap à la valeur la plus proche et recalcul
const creditType = jQuery('input[name="type_credit"]').val();
const snappedValue = snapCapitalValue(capital, creditType);
if (snappedValue !== capital) {
$this.val(snappedValue);
}
calculateCredit();
}
}
});
jQuery('#IDbatiment_duree')
.on('input', function() {
const $this = jQuery(this);
clearTimeout(durationTimeout);
durationTimeout = setTimeout(() => {
let duration = parseInt($this.val());
if (!isNaN(duration)) {
const creditType = jQuery('input[name="type_credit"]').val();
console.log('Input duration:', duration);
console.log('Credit type:', creditType);
console.log('Is yearly:', LOAN_TYPES_IN_YEARS.includes(creditType));
// Ne pas snapper pendant la saisie pour les crédits en années
if (LOAN_TYPES_IN_YEARS.includes(creditType)) {
calculateCredit();
} else {
const snappedValue = snapDurationValue(duration, creditType);
if (snappedValue !== duration) {
$this.val(snappedValue);
}
calculateCredit();
}
}
}, 300);
})
.on('change', function() {
let duration = parseInt($(this).val());
if (!isNaN(duration)) {
const creditType = jQuery('input[name="type_credit"]').val();
console.log('onchange - creditType:', creditType);
console.log('onchange - LOAN_TYPES_IN_YEARS:', LOAN_TYPES_IN_YEARS);
console.log('onchange - includes?', LOAN_TYPES_IN_YEARS.includes(creditType));
if (LOAN_TYPES_IN_YEARS.includes(creditType)) {
console.log('change', duration);
const snappedValue = snapDurationValue(duration, creditType);
console.log('snappedValue', snappedValue);
if (snappedValue !== duration) {
$(this).val(snappedValue);
}
} else {
// Pour les autres crédits, comportement normal
const snappedValue = snapDurationValue(duration, creditType);
if (snappedValue !== duration) {
$(this).val(snappedValue);
}
}
calculateCredit();
}
});
// Calcul initial au chargement
/* $(document).ready(function() {
const creditType = $('input[name="type_credit"]').val();
if (creditType) {
updateFieldLimits(creditType);
calculateCredit();
}
}); */
// Gestionnaire pour la soumission du formulaire
jQuery('.form-submit').on('submit', function() {
// Recalculer une dernière fois avant l'envoi
calculateCredit();
});
}
function findRate(type) {
console.log('findRate - Type recherché:', type);
let rate;
switch(type) {
case 'amr':
rate = cd_js.groups.achat_maison_de_rapport.de_10_a_30_ans;
break;
case 'cdp':
rate = cd_js.groups.credit_pont.de_10_a_30_ans;
break;
case 'cied':
rate = cd_js.groups.independants_et_entreprises_en_difficultes.de_10_a_30_ans;
break;
default:
console.warn('Type de crédit non reconnu pour le taux mono:', type);
rate = null;
}
console.log('findRate - Taux trouvé:', rate);
return rate;
}
function calculate_mono_rate_bt_10_30(type, selected_capital, selected_duration) {
const annual_rate = findRate(type);
if (!annual_rate) {
console.error('Taux non trouvé pour le type:', type);
return null;
}
const min_duration = 10;
const max_duration = 30;
let duree_in_range = true;
const add_message = '';
if (min_duration <= parseInt(selected_duration) && parseInt(selected_duration) <= max_duration) {
// La durée est dans la plage
} else {
duree_in_range = false;
selected_duration = max_duration;
}
// Convertir la durée en mois pour le calcul
selected_duration = selected_duration * 12;
return [min_duration, max_duration, selected_duration, duree_in_range, annual_rate, add_message];
}
});