/* =====================================================
LYMYTZ ERP – Subscription Site – JavaScript
===================================================== */
(function () {
'use strict';
/* ─── DATA ─── */
const MODULES = [
{
id: 'commercial',
name: 'Commercial',
icon: '🛒',
desc: 'Achats, ventes, stocks, facturation',
color: '#6366f1',
},
{
id: 'compta',
name: 'Comptabilité',
icon: '📊',
desc: 'Grand livre, bilans, journaux',
color: '#10b981',
},
{
id: 'grh',
name: 'GRH',
icon: '👥',
desc: 'Employés, paie, congés, formations',
color: '#f59e0b',
},
{
id: 'production',
name: 'Production',
icon: '🏭',
desc: 'Ordres de fabrication, nomenclatures',
color: '#ef4444',
},
{
id: 'mutuelle',
name: 'Mutuelle',
icon: '🏥',
desc: 'Prestations sociales et cotisations',
color: '#06b6d4',
},
{
id: 'projets',
name: 'Projets',
icon: '📋',
desc: 'Planification, suivi et budgets',
color: '#a855f7',
},
];
const PLANS = [
{
id: 'starter',
name: 'Starter',
price: '0',
priceLabel: 'Gratuit',
period: '3 mois d\'essai',
modules: '3 modules max',
tag: null,
},
{
id: 'pro',
name: 'Pro',
price: '49 000',
priceLabel: '49 000 FCFA',
period: 'par mois',
modules: '6 modules inclus',
tag: 'Recommandé',
},
{
id: 'enterprise',
name: 'Enterprise',
price: 'Sur devis',
priceLabel: 'Sur devis',
period: 'personnalisé',
modules: 'Modules illimités',
tag: null,
},
];
/* ─── STATE ─── */
const state = {
currentStep: 1,
selectedModules: [],
selectedPlan: null,
formData: {},
};
/* ─── NAVBAR ─── */
window.addEventListener('scroll', () => {
const navbar = document.getElementById('navbar');
if (navbar) {
navbar.classList.toggle('scrolled', window.scrollY > 40);
}
});
/* ─── MOBILE MENU ─── */
const mobileBtn = document.getElementById('mobile-menu-btn');
const navLinks = document.getElementById('nav-links');
if (mobileBtn && navLinks) {
mobileBtn.addEventListener('click', () => {
navLinks.classList.toggle('mobile-open');
});
}
/* ─── SCROLL ANIMATIONS ─── */
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
}
});
},
{ threshold: 0.12 }
);
document.querySelectorAll('.fade-up').forEach((el) => observer.observe(el));
/* ─── FAQ ACCORDION ─── */
document.querySelectorAll('.faq-item').forEach((item) => {
const question = item.querySelector('.faq-question');
question.addEventListener('click', () => {
const isOpen = item.classList.contains('open');
document.querySelectorAll('.faq-item.open').forEach((i) =>
i.classList.remove('open')
);
if (!isOpen) item.classList.add('open');
});
});
/* ─── SMOOTH SCROLL for CTAs ─── */
document.querySelectorAll('a[href^="#"]').forEach((a) => {
a.addEventListener('click', (e) => {
const target = document.querySelector(a.getAttribute('href'));
if (target) {
e.preventDefault();
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
if (navLinks) navLinks.classList.remove('mobile-open');
}
});
});
/* ─── MULTI-STEP FORM ─── */
function initModuleSelection() {
const grid = document.getElementById('module-select-grid');
if (!grid) return;
grid.innerHTML = '';
MODULES.forEach((mod) => {
const card = document.createElement('div');
card.className = 'module-select-card';
card.dataset.id = mod.id;
card.innerHTML = `
${mod.icon}
${mod.name}
${mod.desc}
✓
`;
card.addEventListener('click', () => {
card.classList.toggle('selected');
updateModuleState();
});
grid.appendChild(card);
});
}
function updateModuleState() {
state.selectedModules = Array.from(
document.querySelectorAll('.module-select-card.selected')
).map((c) => c.dataset.id);
updateModuleCount();
}
function updateModuleCount() {
const count = document.getElementById('module-count');
if (count) count.textContent = `${state.selectedModules.length} module(s) sélectionné(s)`;
}
function initPlanSelection() {
const grid = document.getElementById('plan-select-grid');
if (!grid) return;
grid.innerHTML = '';
PLANS.forEach((plan) => {
const card = document.createElement('div');
card.className = 'plan-select-card' + (plan.tag ? ' recommended' : '');
card.dataset.id = plan.id;
card.innerHTML = `
${plan.name}
${plan.priceLabel}
${plan.period}
${plan.modules}
`;
card.addEventListener('click', () => {
document
.querySelectorAll('.plan-select-card')
.forEach((c) => c.classList.remove('selected'));
card.classList.add('selected');
state.selectedPlan = plan.id;
});
grid.appendChild(card);
});
}
function buildRecap() {
const data = state.formData;
const setCellValue = (id, value) => {
const el = document.getElementById(id);
if (el) el.textContent = value || '—';
};
setCellValue('recap-name', data.societe_nom);
setCellValue('recap-forme', data.societe_forme);
setCellValue('recap-email', data.societe_email);
setCellValue('recap-tel', data.societe_tel);
setCellValue('recap-ville', data.societe_ville);
setCellValue('recap-pays', data.societe_pays);
const mods = MODULES.filter((m) => state.selectedModules.includes(m.id));
const modsEl = document.getElementById('recap-modules');
if (modsEl) {
if (mods.length === 0) {
modsEl.innerHTML = 'Aucun module sélectionné';
} else {
modsEl.innerHTML = mods
.map((m) => `${m.icon} ${m.name}`)
.join('');
}
}
const plan = PLANS.find((p) => p.id === state.selectedPlan);
setCellValue('recap-plan', plan ? plan.name : '—');
const totalEl = document.getElementById('recap-total-price');
if (totalEl) {
totalEl.textContent = plan
? plan.priceLabel + (plan.period !== 'personnalisé' ? ' / mois' : '')
: '—';
}
}
/* ─── Form Validation ─── */
function validateStep1() {
let valid = true;
const fields = [
{ id: 'societe_nom', errorId: 'err-nom', check: (v) => v.trim().length >= 2 },
{ id: 'societe_forme', errorId: 'err-forme', check: (v) => v.trim().length > 0 },
{
id: 'societe_email',
errorId: 'err-email',
check: (v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v),
},
{ id: 'societe_tel', errorId: 'err-tel', check: (v) => v.trim().length >= 6 },
];
fields.forEach(({ id, errorId, check }) => {
const input = document.getElementById(id);
const error = document.getElementById(errorId);
if (!input) return;
const isOk = check(input.value);
input.classList.toggle('error', !isOk);
if (error) error.classList.toggle('visible', !isOk);
if (!isOk) valid = false;
else state.formData[id] = input.value.trim();
});
// Save all other fields
['societe_ville', 'societe_pays', 'societe_adresse', 'societe_capital'].forEach(
(id) => {
const input = document.getElementById(id);
if (input) state.formData[id] = input.value.trim();
}
);
return valid;
}
function validateStep2() {
const warning = document.getElementById('modules-warning');
if (state.selectedModules.length === 0) {
if (warning) warning.style.display = 'block';
return false;
}
if (warning) warning.style.display = 'none';
return true;
}
function validateStep3() {
const warning = document.getElementById('plan-warning');
if (!state.selectedPlan) {
if (warning) warning.style.display = 'block';
return false;
}
if (warning) warning.style.display = 'none';
return true;
}
/* ─── Progress Bar ─── */
function updateProgress(step) {
const fills = { 1: '0%', 2: '33%', 3: '66%', 4: '100%' };
const fillEl = document.getElementById('progress-fill');
if (fillEl) fillEl.style.width = fills[step] || '0%';
document.querySelectorAll('.progress-step').forEach((el) => {
const s = parseInt(el.dataset.step);
el.classList.remove('active', 'done');
if (s === step) el.classList.add('active');
else if (s < step) el.classList.add('done');
});
}
/* ─── Navigation ─── */
function goToStep(step) {
if (step < 1 || step > 4) return;
const currentEl = document.querySelector(`.form-step[data-step="${state.currentStep}"]`);
const nextEl = document.querySelector(`.form-step[data-step="${step}"]`);
if (currentEl) currentEl.classList.remove('active');
if (nextEl) nextEl.classList.add('active');
state.currentStep = step;
updateProgress(step);
if (step === 4) buildRecap();
// Scroll to form
const form = document.getElementById('register');
if (form) form.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
function nextStep() {
let ok = true;
if (state.currentStep === 1) ok = validateStep1();
if (state.currentStep === 2) ok = validateStep2();
if (state.currentStep === 3) ok = validateStep3();
if (ok) goToStep(state.currentStep + 1);
}
function prevStep() {
if (state.currentStep > 1) goToStep(state.currentStep - 1);
}
/* ─── Submit ─── */
function submitForm() {
const submitBtn = document.getElementById('submit-btn');
if (submitBtn) {
submitBtn.disabled = true;
submitBtn.textContent = 'Envoi en cours...';
}
// Simulate API call
setTimeout(() => {
const recap = document.getElementById('form-recap-content');
const success = document.getElementById('form-success');
if (recap) recap.style.display = 'none';
if (success) success.style.display = 'block';
const formNav = document.getElementById('form-nav-step4');
if (formNav) formNav.style.display = 'none';
}, 1500);
}
/* ─── Event Listeners for form buttons ─── */
function initFormButtons() {
// Next buttons
document.querySelectorAll('[data-action="next"]').forEach((btn) =>
btn.addEventListener('click', nextStep)
);
// Prev buttons
document.querySelectorAll('[data-action="prev"]').forEach((btn) =>
btn.addEventListener('click', prevStep)
);
// Submit
const submitBtn = document.getElementById('submit-btn');
if (submitBtn) submitBtn.addEventListener('click', submitForm);
// Restart
const restartBtn = document.getElementById('restart-btn');
if (restartBtn) {
restartBtn.addEventListener('click', () => {
state.currentStep = 1;
state.selectedModules = [];
state.selectedPlan = null;
state.formData = {};
document.querySelectorAll('.progress-step').forEach((el) =>
el.classList.remove('active', 'done')
);
// Reset card selections
document.querySelectorAll('.module-select-card').forEach((c) =>
c.classList.remove('selected')
);
document.querySelectorAll('.plan-select-card').forEach((c) =>
c.classList.remove('selected')
);
const recap = document.getElementById('form-recap-content');
const success = document.getElementById('form-success');
if (recap) recap.style.display = 'block';
if (success) success.style.display = 'none';
const formNav = document.getElementById('form-nav-step4');
if (formNav) formNav.style.display = 'flex';
const submitBtn2 = document.getElementById('submit-btn');
if (submitBtn2) {
submitBtn2.disabled = false;
submitBtn2.textContent = "Confirmer l'inscription";
}
goToStep(1);
});
}
}
/* ─── CTA "Commencer" from hero & pricing ─── */
document.querySelectorAll('[data-plan-cta]').forEach((btn) => {
btn.addEventListener('click', () => {
const planId = btn.dataset.planCta;
const register = document.getElementById('register');
if (register) register.scrollIntoView({ behavior: 'smooth', block: 'start' });
// Auto-select the plan after delay
setTimeout(() => {
document.querySelectorAll('.plan-select-card').forEach((c) => {
if (c.dataset.id === planId) {
document.querySelectorAll('.plan-select-card').forEach((x) =>
x.classList.remove('selected')
);
c.classList.add('selected');
state.selectedPlan = planId;
}
});
}, 500);
});
});
/* ─── INIT ─── */
document.addEventListener('DOMContentLoaded', () => {
initModuleSelection();
initPlanSelection();
initFormButtons();
updateProgress(1);
updateModuleCount();
});
// Also try init immediately (for after DOMContentLoaded)
if (document.readyState !== 'loading') {
initModuleSelection();
initPlanSelection();
initFormButtons();
updateProgress(1);
updateModuleCount();
}
})();