// ============================================================ // THÈME MINÉRAL DE NAISSANCE — Code Velo (Wix JavaScript) // Version 2.0 — Document technique de référence intégré // ============================================================ // INSTRUCTIONS WIX : // 1. Active Velo (Dev Mode) dans l'éditeur Wix // 2. Crée une page avec les éléments suivants (IDs exacts) : // - #prenoms → Champ texte (tous les prénoms de naissance) // - #nom → Champ texte (nom de naissance) // - #dateNaissance → Champ texte (format JJ/MM/AAAA ou JJ.MM.AAAA) // - #btnCalculer → Bouton "Calculer mon thème" // - #resultatTexte → Zone de texte résultat // - #messageInfo → Texte d'info/avertissement // - #niveauUser → Texte ou variable indiquant le niveau (0=gratuit, 1=19€, 2=49€) // 3. Dans Wix CMS, crée une collection "ThemeMineral" avec les champs : // prenoms, nom, dateNaissance (Texte) // n1 à n13 (Nombre), pierre1 à pierre13 (Texte) // niveau (Nombre), userId (Texte) // ============================================================ import wixData from 'wix-data'; import wixUsers from 'wix-users'; // ============================================================ // TABLE DE CONVERSION LETTRES → VALEURS (1 à 9) // ============================================================ const VALEURS = { A:1, B:2, C:3, D:4, E:5, F:6, G:7, H:8, I:9, J:1, K:2, L:3, M:4, N:5, O:6, P:7, Q:8, R:9, S:1, T:2, U:3, V:4, W:5, X:6, Y:7, Z:8 }; // Translittération des lettres accentuées → équivalents A–Z const ACCENTS = { À:'A', Â:'A', Á:'A', Ä:'A', È:'E', É:'E', Ê:'E', Ë:'E', Î:'I', Ï:'I', Í:'I', Ì:'I', Ô:'O', Ö:'O', Ó:'O', Ò:'O', Ù:'U', Û:'U', Ü:'U', Ú:'U', Ÿ:'Y', Ý:'Y', Ç:'C', Ñ:'N', Œ:'OE', Æ:'AE' }; // Voyelles (après translittération) const VOYELLES = new Set(['A','E','I','O','U','Y']); // ============================================================ // 33 CRISTAUX (mapping officiel) // ============================================================ const CRISTAUX = { 1: "Quartz rose", 2: "Jaspe rouge", 3: "Calcite bleue", 4: "Jaspe impérial", 5: "Émeraude", 6: "Grenat", 7: "Citrine", 8: "Obsidienne", 9: "Aigue-marine", 10: "Rhodonite", 11: "Cornaline", 12: "Bois fossilisé", 13: "Hématite", 14: "Améthyste", 15: "Malachite", 16: "Opale", 17: "Aragonite", 18: "Pierre de lune noire", 19: "Topaze", 20: "Lapis lazuli", 21: "Tourmaline noire", 22: "Cristal de roche", 23: "Azurite", 24: "Amazonite", 25: "Septaria", 26: "Pyrite", 27: "Fluorine", 28: "Apatite", 29: "Sodalite", 30: "Quartz fumé", 31: "Soufre", 32: "Labradorite", 33: "Apophyllite" }; // Noms des 13 pierres const NOMS_PIERRES = [ "Pierre d'Ancrage", "Pierre d'Expansion", "Pierre de Matérialisation", "Pierre de Transformation", "Pierre de Ressource", "Pierre de Nature Intérieure", "Pierre de Manifestation", "Pierre de Transmutation", "Pierre d'Essence", "Pierre d'Émanation", "Pierre du Mémoriel", "Pierre d'Initiation", "Pierre de Réalisation" ]; // ============================================================ // FONCTIONS UTILITAIRES // ============================================================ // Translittérer et nettoyer un caractère function normaliserChar(c) { const upper = c.toUpperCase(); return ACCENTS[upper] || upper; } // Normaliser un mot complet (accents, majuscules, espaces) function normaliserMot(mot) { return mot.toUpperCase().split('').map(c => ACCENTS[c] || c).join(''); } // Valeur numérique d'une lettre (après normalisation) function valeurLettre(lettre) { const norm = normaliserChar(lettre); return VALEURS[norm] || 0; } // Réduction : si > 33, additionner les chiffres jusqu'à <= 33 function reduire(n) { while (n > 33) { n = String(n).split('').reduce((s, c) => s + parseInt(c), 0); } return n; } // ============================================================ // DÉCOUPAGE EN BLOCS (gestion tirets et espaces) // Règle : tiret = un seul bloc logique | espace = blocs distincts // ============================================================ function decouperEnBlocs(texte) { // 1. Nettoyer espaces inutiles const nettoye = texte.trim().replace(/\s+/g, ' '); // 2. Séparer par espaces → chaque mot est un bloc // Les prénoms composés avec tiret restent un seul bloc return nettoye.split(' ').map(b => normaliserMot(b)).filter(b => b.length > 0); } // Première lettre alphabétique d'un bloc function premiereLettre(bloc) { for (let c of bloc) { if (VALEURS[c]) return c; } return ''; } // Dernière lettre alphabétique d'un bloc function derniereLettre(bloc) { for (let i = bloc.length - 1; i >= 0; i--) { if (VALEURS[bloc[i]]) return bloc[i]; } return ''; } // Première voyelle d'un bloc function premiereVoyelle(bloc) { for (let c of bloc) { if (VOYELLES.has(c)) return c; } return ''; } // ============================================================ // CALCUL DES 13 LIGNES // ============================================================ function calculerTheme(prenomsInput, nomInput, dateInput) { const prenomsBlocs = decouperEnBlocs(prenomsInput); const nomBlocs = decouperEnBlocs(nomInput); const tousBlocs = [...prenomsBlocs, ...nomBlocs]; // --- L1 : Premières lettres de chaque bloc --- const L1 = reduire(tousBlocs.reduce((s, b) => s + valeurLettre(premiereLettre(b)), 0)); // --- L2 : Dernières lettres de chaque bloc --- const L2 = reduire(tousBlocs.reduce((s, b) => s + valeurLettre(derniereLettre(b)), 0)); // --- L3 : Date de naissance (jour + mois + année chiffre par chiffre) --- const chiffresDate = dateInput.replace(/\D/g, ''); // ex: "01101986" const L3 = reduire(chiffresDate.split('').reduce((s, c) => s + parseInt(c), 0)); // --- L4 : L1 + L2 + L3 --- const L4 = reduire(L1 + L2 + L3); // --- L5 : Toutes les voyelles --- let somme5 = 0; for (let bloc of tousBlocs) { for (let c of bloc) { if (VOYELLES.has(c)) somme5 += valeurLettre(c); } } const L5 = reduire(somme5); // --- L6 : Toutes les consonnes --- let somme6 = 0; for (let bloc of tousBlocs) { for (let c of bloc) { if (VALEURS[c] && !VOYELLES.has(c)) somme6 += valeurLettre(c); } } const L6 = reduire(somme6); // --- L7 : L5 + L6 --- const L7 = reduire(L5 + L6); // --- L8 : L5 + L6 + L7 --- const L8 = reduire(L5 + L6 + L7); // --- L9 : Premières voyelles de chaque bloc --- let somme9 = 0; for (let bloc of tousBlocs) { const v = premiereVoyelle(bloc); if (v) somme9 += valeurLettre(v); } const L9 = reduire(somme9); // --- L10 : Toutes les lettres --- let somme10 = 0; for (let bloc of tousBlocs) { for (let c of bloc) { somme10 += valeurLettre(c); } } const L10 = reduire(somme10); // --- L11 : L4 + L8 --- const L11 = reduire(L4 + L8); // --- L12 : L9 + L10 + L11 --- const L12 = reduire(L9 + L10 + L11); // --- L13 : L4 + L8 + L12 --- const L13 = reduire(L4 + L8 + L12); const nombres = [L1,L2,L3,L4,L5,L6,L7,L8,L9,L10,L11,L12,L13]; return nombres.map((n, i) => ({ numero: i + 1, nom: NOMS_PIERRES[i], valeur: n, cristal: CRISTAUX[n] || "Cristal inconnu" })); } // ============================================================ // AFFICHAGE SELON NIVEAU UTILISATEUR // Niveau 0 = Gratuit : uniquement Pierre d'Ancrage (ligne 1) // Niveau 1 = 19€ : 13 lignes visibles, phrase simple // Niveau 2 = 49€ : 13 lignes + contenu enrichi + PDF // ============================================================ function formaterResultat(resultats, prenoms, nom, date, niveau) { let texte = `🔮 THÈME MINÉRAL DE NAISSANCE\n`; texte += `👤 ${prenoms} ${nom} — né(e) le ${date}\n`; texte += `${'─'.repeat(44)}\n\n`; if (niveau === 0) { // GRATUIT : uniquement l'ancrage + CTA const r = resultats[0]; texte += `✨ ${r.nom}\n`; texte += ` Nombre : ${r.valeur} | Cristal : ${r.cristal}\n\n`; texte += `─────────────────────────────────────────────\n`; texte += `🌟 Découvrez vos 13 pierres complètes\n`; texte += ` → Pack Thème Complet — 19€\n`; texte += ` → Compréhension Enrichie + PDF — 49€\n`; } else if (niveau === 1) { // PACK 19€ : 13 lignes for (let r of resultats) { texte += `${r.numero.toString().padStart(2,'0')}. ${r.nom}\n`; texte += ` Nombre : ${r.valeur} | Cristal : ${r.cristal}\n\n`; } texte += `─────────────────────────────────────────────\n`; texte += `📘 Approfondissez votre thème — 49€\n`; texte += ` Lecture structurée, PDF & contenu pédagogique\n`; } else if (niveau === 2) { // OFFRE 49€ : 13 lignes enrichies for (let r of resultats) { texte += `${r.numero.toString().padStart(2,'0')}. ${r.nom}\n`; texte += ` Nombre : ${r.valeur} | Cristal : ${r.cristal}\n`; texte += ` ✦ Votre cristal de ${r.nom.toLowerCase()} est le ${r.cristal}.\n\n`; } texte += `─────────────────────────────────────────────\n`; texte += `🎓 Prêt(e) à aller plus loin ?\n`; texte += ` → Accéder à la formation complète\n`; } return texte; } // ============================================================ // CODE DE LA PAGE WIX // ============================================================ $w.onReady(function () { // Message d'avertissement affiché en haut du formulaire $w('#messageInfo').text = "Merci d'indiquer vos prénoms et votre nom de naissance, " + "exactement comme à la naissance, sans tenir compte des modifications ultérieures. " + "Un prénom composé avec tiret est traité comme un seul prénom. " + "Un double nom sans tiret est traité comme deux blocs distincts."; $w('#btnCalculer').onClick(async () => { const prenoms = $w('#prenoms').value.trim(); const nom = $w('#nom').value.trim(); const date = $w('#dateNaissance').value.trim(); // --- VALIDATIONS --- if (!prenoms) { $w('#resultatTexte').text = "⚠️ Merci d'indiquer tous vos prénoms de naissance."; return; } if (!nom) { $w('#resultatTexte').text = "⚠️ Merci d'indiquer votre nom de naissance, non modifié dans le temps."; return; } if (!date) { $w('#resultatTexte').text = "⚠️ Merci d'indiquer votre date de naissance (JJ/MM/AAAA)."; return; } // Vérifier format date const dateRegex = /^\d{1,2}[.\-/]\d{1,2}[.\-/]\d{4}$/; if (!dateRegex.test(date)) { $w('#resultatTexte').text = "⚠️ Format de date invalide. Merci d'utiliser JJ/MM/AAAA."; return; } // --- NIVEAU UTILISATEUR --- // 0 = gratuit, 1 = 19€, 2 = 49€ // À connecter à wixUsers et à votre logique d'abonnement let niveau = 0; try { const user = wixUsers.currentUser; if (user.loggedIn) { const userData = await wixData.query("Membres") .eq("_owner", user.id) .find(); if (userData.items.length > 0) { niveau = userData.items[0].niveau || 0; } } } catch (e) { console.log("Niveau par défaut : gratuit"); } // --- CALCUL --- const resultats = calculerTheme(prenoms, nom, date); // --- AFFICHAGE --- $w('#resultatTexte').text = formaterResultat(resultats, prenoms, nom, date, niveau); // --- SAUVEGARDE DANS WIX CMS --- const entree = { prenoms: prenoms, nom: nom, dateNaissance: date, niveau: niveau }; resultats.forEach(r => { entree[`n${r.numero}`] = r.valeur; entree[`pierre${r.numero}`] = r.cristal; }); try { await wixData.insert("ThemeMineral", entree); console.log("✅ Thème minéral sauvegardé."); } catch (err) { console.error("❌ Erreur sauvegarde :", err); } }); }); // ============================================================ // EXEMPLE DE CALCUL INTÉGRÉ (pour test développeur) // Nadège Emmanuelle Jordane Bellanti — née le 01/10/1986 // ============================================================ // L1 (Ancrage) : N+E+J+B = 5+5+1+2 = 13 → Hématite // L2 (Expansion) : E+E+E+I = 5+5+5+9 = 24 → Amazonite // L3 (Matérialisation) : 0+1+1+0+1+9+8+6 = 26 → Pyrite // L4 (Transformation) : 13+24+26 = 63 → 9 → Aigue-marine // L5 (Ressource) : voyelles = 57 → 12 → Bois fossilisé // L6 (Nature Intérieure): consonnes = 69 → 15 → Malachite // L7 (Manifestation) : 12+15 = 27 → Fluorine // L8 (Transmutation) : 12+15+27 = 54 → 9 → Aigue-marine // L9 (Essence) : A+E+O+E = 1+5+6+5 = 17 → Aragonite // L10 (Émanation) : toutes lettres = 126 → 9 → Aigue-marine // L11 (Mémoriel) : 9+9 = 18 → Pierre de lune noire // L12 (Initiation) : 17+9+18 = 44 → 8 → Obsidienne // L13 (Réalisation) : 9+9+8 = 26 → Pyrite // ============================================================ // ============================================================ // THÈME MINÉRAL DE NAISSANCE — Code Velo (Wix JavaScript) // Version 2.0 — Document technique de référence intégré // ============================================================ // INSTRUCTIONS WIX : // 1. Active Velo (Dev Mode) dans l'éditeur Wix // 2. Crée une page avec les éléments suivants (IDs exacts) : // - #prenoms → Champ texte (tous les prénoms de naissance) // - #nom → Champ texte (nom de naissance) // - #dateNaissance → Champ texte (format JJ/MM/AAAA ou JJ.MM.AAAA) // - #btnCalculer → Bouton "Calculer mon thème" // - #resultatTexte → Zone de texte résultat // - #messageInfo → Texte d'info/avertissement // - #niveauUser → Texte ou variable indiquant le niveau (0=gratuit, 1=19€, 2=49€) // 3. Dans Wix CMS, crée une collection "ThemeMineral" avec les champs : // prenoms, nom, dateNaissance (Texte) // n1 à n13 (Nombre), pierre1 à pierre13 (Texte) // niveau (Nombre), userId (Texte) // ============================================================ import wixData from 'wix-data'; import wixUsers from 'wix-users'; // ============================================================ // TABLE DE CONVERSION LETTRES → VALEURS (1 à 9) // ============================================================ const VALEURS = { A:1, B:2, C:3, D:4, E:5, F:6, G:7, H:8, I:9, J:1, K:2, L:3, M:4, N:5, O:6, P:7, Q:8, R:9, S:1, T:2, U:3, V:4, W:5, X:6, Y:7, Z:8 }; // Translittération des lettres accentuées → équivalents A–Z const ACCENTS = { À:'A', Â:'A', Á:'A', Ä:'A', È:'E', É:'E', Ê:'E', Ë:'E', Î:'I', Ï:'I', Í:'I', Ì:'I', Ô:'O', Ö:'O', Ó:'O', Ò:'O', Ù:'U', Û:'U', Ü:'U', Ú:'U', Ÿ:'Y', Ý:'Y', Ç:'C', Ñ:'N', Œ:'OE', Æ:'AE' }; // Voyelles (après translittération) const VOYELLES = new Set(['A','E','I','O','U','Y']); // ============================================================ // 33 CRISTAUX (mapping officiel) // ============================================================ const CRISTAUX = { 1: "Quartz rose", 2: "Jaspe rouge", 3: "Calcite bleue", 4: "Jaspe impérial", 5: "Émeraude", 6: "Grenat", 7: "Citrine", 8: "Obsidienne", 9: "Aigue-marine", 10: "Rhodonite", 11: "Cornaline", 12: "Bois fossilisé", 13: "Hématite", 14: "Améthyste", 15: "Malachite", 16: "Opale", 17: "Aragonite", 18: "Pierre de lune noire", 19: "Topaze", 20: "Lapis lazuli", 21: "Tourmaline noire", 22: "Cristal de roche", 23: "Azurite", 24: "Amazonite", 25: "Septaria", 26: "Pyrite", 27: "Fluorine", 28: "Apatite", 29: "Sodalite", 30: "Quartz fumé", 31: "Soufre", 32: "Labradorite", 33: "Apophyllite" }; // Noms des 13 pierres const NOMS_PIERRES = [ "Pierre d'Ancrage", "Pierre d'Expansion", "Pierre de Matérialisation", "Pierre de Transformation", "Pierre de Ressource", "Pierre de Nature Intérieure", "Pierre de Manifestation", "Pierre de Transmutation", "Pierre d'Essence", "Pierre d'Émanation", "Pierre du Mémoriel", "Pierre d'Initiation", "Pierre de Réalisation" ]; // ============================================================ // FONCTIONS UTILITAIRES // ============================================================ // Translittérer et nettoyer un caractère function normaliserChar(c) { const upper = c.toUpperCase(); return ACCENTS[upper] || upper; } // Normaliser un mot complet (accents, majuscules, espaces) function normaliserMot(mot) { return mot.toUpperCase().split('').map(c => ACCENTS[c] || c).join(''); } // Valeur numérique d'une lettre (après normalisation) function valeurLettre(lettre) { const norm = normaliserChar(lettre); return VALEURS[norm] || 0; } // Réduction : si > 33, additionner les chiffres jusqu'à <= 33 function reduire(n) { while (n > 33) { n = String(n).split('').reduce((s, c) => s + parseInt(c), 0); } return n; } // ============================================================ // DÉCOUPAGE EN BLOCS (gestion tirets et espaces) // Règle : tiret = un seul bloc logique | espace = blocs distincts // ============================================================ function decouperEnBlocs(texte) { // 1. Nettoyer espaces inutiles const nettoye = texte.trim().replace(/\s+/g, ' '); // 2. Séparer par espaces → chaque mot est un bloc // Les prénoms composés avec tiret restent un seul bloc return nettoye.split(' ').map(b => normaliserMot(b)).filter(b => b.length > 0); } // Première lettre alphabétique d'un bloc function premiereLettre(bloc) { for (let c of bloc) { if (VALEURS[c]) return c; } return ''; } // Dernière lettre alphabétique d'un bloc function derniereLettre(bloc) { for (let i = bloc.length - 1; i >= 0; i--) { if (VALEURS[bloc[i]]) return bloc[i]; } return ''; } // Première voyelle d'un bloc function premiereVoyelle(bloc) { for (let c of bloc) { if (VOYELLES.has(c)) return c; } return ''; } // ============================================================ // CALCUL DES 13 LIGNES // ============================================================ function calculerTheme(prenomsInput, nomInput, dateInput) { const prenomsBlocs = decouperEnBlocs(prenomsInput); const nomBlocs = decouperEnBlocs(nomInput); const tousBlocs = [...prenomsBlocs, ...nomBlocs]; // --- L1 : Premières lettres de chaque bloc --- const L1 = reduire(tousBlocs.reduce((s, b) => s + valeurLettre(premiereLettre(b)), 0)); // --- L2 : Dernières lettres de chaque bloc --- const L2 = reduire(tousBlocs.reduce((s, b) => s + valeurLettre(derniereLettre(b)), 0)); // --- L3 : Date de naissance (jour + mois + année chiffre par chiffre) --- const chiffresDate = dateInput.replace(/\D/g, ''); // ex: "01101986" const L3 = reduire(chiffresDate.split('').reduce((s, c) => s + parseInt(c), 0)); // --- L4 : L1 + L2 + L3 --- const L4 = reduire(L1 + L2 + L3); // --- L5 : Toutes les voyelles --- let somme5 = 0; for (let bloc of tousBlocs) { for (let c of bloc) { if (VOYELLES.has(c)) somme5 += valeurLettre(c); } } const L5 = reduire(somme5); // --- L6 : Toutes les consonnes --- let somme6 = 0; for (let bloc of tousBlocs) { for (let c of bloc) { if (VALEURS[c] && !VOYELLES.has(c)) somme6 += valeurLettre(c); } } const L6 = reduire(somme6); // --- L7 : L5 + L6 --- const L7 = reduire(L5 + L6); // --- L8 : L5 + L6 + L7 --- const L8 = reduire(L5 + L6 + L7); // --- L9 : Premières voyelles de chaque bloc --- let somme9 = 0; for (let bloc of tousBlocs) { const v = premiereVoyelle(bloc); if (v) somme9 += valeurLettre(v); } const L9 = reduire(somme9); // --- L10 : Toutes les lettres --- let somme10 = 0; for (let bloc of tousBlocs) { for (let c of bloc) { somme10 += valeurLettre(c); } } const L10 = reduire(somme10); // --- L11 : L4 + L8 --- const L11 = reduire(L4 + L8); // --- L12 : L9 + L10 + L11 --- const L12 = reduire(L9 + L10 + L11); // --- L13 : L4 + L8 + L12 --- const L13 = reduire(L4 + L8 + L12); const nombres = [L1,L2,L3,L4,L5,L6,L7,L8,L9,L10,L11,L12,L13]; return nombres.map((n, i) => ({ numero: i + 1, nom: NOMS_PIERRES[i], valeur: n, cristal: CRISTAUX[n] || "Cristal inconnu" })); } // ============================================================ // AFFICHAGE SELON NIVEAU UTILISATEUR // Niveau 0 = Gratuit : uniquement Pierre d'Ancrage (ligne 1) // Niveau 1 = 19€ : 13 lignes visibles, phrase simple // Niveau 2 = 49€ : 13 lignes + contenu enrichi + PDF // ============================================================ function formaterResultat(resultats, prenoms, nom, date, niveau) { let texte = `🔮 THÈME MINÉRAL DE NAISSANCE\n`; texte += `👤 ${prenoms} ${nom} — né(e) le ${date}\n`; texte += `${'─'.repeat(44)}\n\n`; if (niveau === 0) { // GRATUIT : uniquement l'ancrage + CTA const r = resultats[0]; texte += `✨ ${r.nom}\n`; texte += ` Nombre : ${r.valeur} | Cristal : ${r.cristal}\n\n`; texte += `─────────────────────────────────────────────\n`; texte += `🌟 Découvrez vos 13 pierres complètes\n`; texte += ` → Pack Thème Complet — 19€\n`; texte += ` → Compréhension Enrichie + PDF — 49€\n`; } else if (niveau === 1) { // PACK 19€ : 13 lignes for (let r of resultats) { texte += `${r.numero.toString().padStart(2,'0')}. ${r.nom}\n`; texte += ` Nombre : ${r.valeur} | Cristal : ${r.cristal}\n\n`; } texte += `─────────────────────────────────────────────\n`; texte += `📘 Approfondissez votre thème — 49€\n`; texte += ` Lecture structurée, PDF & contenu pédagogique\n`; } else if (niveau === 2) { // OFFRE 49€ : 13 lignes enrichies for (let r of resultats) { texte += `${r.numero.toString().padStart(2,'0')}. ${r.nom}\n`; texte += ` Nombre : ${r.valeur} | Cristal : ${r.cristal}\n`; texte += ` ✦ Votre cristal de ${r.nom.toLowerCase()} est le ${r.cristal}.\n\n`; } texte += `─────────────────────────────────────────────\n`; texte += `🎓 Prêt(e) à aller plus loin ?\n`; texte += ` → Accéder à la formation complète\n`; } return texte; } // ============================================================ // CODE DE LA PAGE WIX // ============================================================ $w.onReady(function () { // Message d'avertissement affiché en haut du formulaire $w('#messageInfo').text = "Merci d'indiquer vos prénoms et votre nom de naissance, " + "exactement comme à la naissance, sans tenir compte des modifications ultérieures. " + "Un prénom composé avec tiret est traité comme un seul prénom. " + "Un double nom sans tiret est traité comme deux blocs distincts."; $w('#btnCalculer').onClick(async () => { const prenoms = $w('#prenoms').value.trim(); const nom = $w('#nom').value.trim(); const date = $w('#dateNaissance').value.trim(); // --- VALIDATIONS --- if (!prenoms) { $w('#resultatTexte').text = "⚠️ Merci d'indiquer tous vos prénoms de naissance."; return; } if (!nom) { $w('#resultatTexte').text = "⚠️ Merci d'indiquer votre nom de naissance, non modifié dans le temps."; return; } if (!date) { $w('#resultatTexte').text = "⚠️ Merci d'indiquer votre date de naissance (JJ/MM/AAAA)."; return; } // Vérifier format date const dateRegex = /^\d{1,2}[.\-/]\d{1,2}[.\-/]\d{4}$/; if (!dateRegex.test(date)) { $w('#resultatTexte').text = "⚠️ Format de date invalide. Merci d'utiliser JJ/MM/AAAA."; return; } // --- NIVEAU UTILISATEUR --- // 0 = gratuit, 1 = 19€, 2 = 49€ // À connecter à wixUsers et à votre logique d'abonnement let niveau = 0; try { const user = wixUsers.currentUser; if (user.loggedIn) { const userData = await wixData.query("Membres") .eq("_owner", user.id) .find(); if (userData.items.length > 0) { niveau = userData.items[0].niveau || 0; } } } catch (e) { console.log("Niveau par défaut : gratuit"); } // --- CALCUL --- const resultats = calculerTheme(prenoms, nom, date); // --- AFFICHAGE --- $w('#resultatTexte').text = formaterResultat(resultats, prenoms, nom, date, niveau); // --- SAUVEGARDE DANS WIX CMS --- const entree = { prenoms: prenoms, nom: nom, dateNaissance: date, niveau: niveau }; resultats.forEach(r => { entree[`n${r.numero}`] = r.valeur; entree[`pierre${r.numero}`] = r.cristal; }); try { await wixData.insert("ThemeMineral", entree); console.log("✅ Thème minéral sauvegardé."); } catch (err) { console.error("❌ Erreur sauvegarde :", err); } }); }); // ============================================================ // EXEMPLE DE CALCUL INTÉGRÉ (pour test développeur) // Nadège Emmanuelle Jordane Bellanti — née le 01/10/1986 // ============================================================ // L1 (Ancrage) : N+E+J+B = 5+5+1+2 = 13 → Hématite // L2 (Expansion) : E+E+E+I = 5+5+5+9 = 24 → Amazonite // L3 (Matérialisation) : 0+1+1+0+1+9+8+6 = 26 → Pyrite // L4 (Transformation) : 13+24+26 = 63 → 9 → Aigue-marine // L5 (Ressource) : voyelles = 57 → 12 → Bois fossilisé // L6 (Nature Intérieure): consonnes = 69 → 15 → Malachite // L7 (Manifestation) : 12+15 = 27 → Fluorine // L8 (Transmutation) : 12+15+27 = 54 → 9 → Aigue-marine // L9 (Essence) : A+E+O+E = 1+5+6+5 = 17 → Aragonite // L10 (Émanation) : toutes lettres = 126 → 9 → Aigue-marine // L11 (Mémoriel) : 9+9 = 18 → Pierre de lune noire // L12 (Initiation) : 17+9+18 = 44 → 8 → Obsidienne // L13 (Réalisation) : 9+9+8 = 26 → Pyrite // ============================================================
top of page
ChatGPT Image 21 mai 2026, 20_17_06.png

Un outil simple.

Une lecture qui te ressemble.

13 lignes.

Une pierre par ligne.

Nom, prénoms, date de naissance.​

Découvre ton
architecture
minérale.

 

Commencer maintenant

Nos Articles

Lire Plus

Services

Publications

Blog

Articles récents

Nouvelles

Mises à jour importantes

Événements

Participer aux événements

Témoignages

Expériences de clients

Galerie Vidéo

Cette vidéo a été supprimée.
bottom of page
// ============================================================ // THÈME MINÉRAL DE NAISSANCE — Code Velo (Wix JavaScript) // Version 2.0 — Document technique de référence intégré // ============================================================ // INSTRUCTIONS WIX : // 1. Active Velo (Dev Mode) dans l'éditeur Wix // 2. Crée une page avec les éléments suivants (IDs exacts) : // - #prenoms → Champ texte (tous les prénoms de naissance) // - #nom → Champ texte (nom de naissance) // - #dateNaissance → Champ texte (format JJ/MM/AAAA ou JJ.MM.AAAA) // - #btnCalculer → Bouton "Calculer mon thème" // - #resultatTexte → Zone de texte résultat // - #messageInfo → Texte d'info/avertissement // - #niveauUser → Texte ou variable indiquant le niveau (0=gratuit, 1=19€, 2=49€) // 3. Dans Wix CMS, crée une collection "ThemeMineral" avec les champs : // prenoms, nom, dateNaissance (Texte) // n1 à n13 (Nombre), pierre1 à pierre13 (Texte) // niveau (Nombre), userId (Texte) // ============================================================ import wixData from 'wix-data'; import wixUsers from 'wix-users'; // ============================================================ // TABLE DE CONVERSION LETTRES → VALEURS (1 à 9) // ============================================================ const VALEURS = { A:1, B:2, C:3, D:4, E:5, F:6, G:7, H:8, I:9, J:1, K:2, L:3, M:4, N:5, O:6, P:7, Q:8, R:9, S:1, T:2, U:3, V:4, W:5, X:6, Y:7, Z:8 }; // Translittération des lettres accentuées → équivalents A–Z const ACCENTS = { À:'A', Â:'A', Á:'A', Ä:'A', È:'E', É:'E', Ê:'E', Ë:'E', Î:'I', Ï:'I', Í:'I', Ì:'I', Ô:'O', Ö:'O', Ó:'O', Ò:'O', Ù:'U', Û:'U', Ü:'U', Ú:'U', Ÿ:'Y', Ý:'Y', Ç:'C', Ñ:'N', Œ:'OE', Æ:'AE' }; // Voyelles (après translittération) const VOYELLES = new Set(['A','E','I','O','U','Y']); // ============================================================ // 33 CRISTAUX (mapping officiel) // ============================================================ const CRISTAUX = { 1: "Quartz rose", 2: "Jaspe rouge", 3: "Calcite bleue", 4: "Jaspe impérial", 5: "Émeraude", 6: "Grenat", 7: "Citrine", 8: "Obsidienne", 9: "Aigue-marine", 10: "Rhodonite", 11: "Cornaline", 12: "Bois fossilisé", 13: "Hématite", 14: "Améthyste", 15: "Malachite", 16: "Opale", 17: "Aragonite", 18: "Pierre de lune noire", 19: "Topaze", 20: "Lapis lazuli", 21: "Tourmaline noire", 22: "Cristal de roche", 23: "Azurite", 24: "Amazonite", 25: "Septaria", 26: "Pyrite", 27: "Fluorine", 28: "Apatite", 29: "Sodalite", 30: "Quartz fumé", 31: "Soufre", 32: "Labradorite", 33: "Apophyllite" }; // Noms des 13 pierres const NOMS_PIERRES = [ "Pierre d'Ancrage", "Pierre d'Expansion", "Pierre de Matérialisation", "Pierre de Transformation", "Pierre de Ressource", "Pierre de Nature Intérieure", "Pierre de Manifestation", "Pierre de Transmutation", "Pierre d'Essence", "Pierre d'Émanation", "Pierre du Mémoriel", "Pierre d'Initiation", "Pierre de Réalisation" ]; // ============================================================ // FONCTIONS UTILITAIRES // ============================================================ // Translittérer et nettoyer un caractère function normaliserChar(c) { const upper = c.toUpperCase(); return ACCENTS[upper] || upper; } // Normaliser un mot complet (accents, majuscules, espaces) function normaliserMot(mot) { return mot.toUpperCase().split('').map(c => ACCENTS[c] || c).join(''); } // Valeur numérique d'une lettre (après normalisation) function valeurLettre(lettre) { const norm = normaliserChar(lettre); return VALEURS[norm] || 0; } // Réduction : si > 33, additionner les chiffres jusqu'à <= 33 function reduire(n) { while (n > 33) { n = String(n).split('').reduce((s, c) => s + parseInt(c), 0); } return n; } // ============================================================ // DÉCOUPAGE EN BLOCS (gestion tirets et espaces) // Règle : tiret = un seul bloc logique | espace = blocs distincts // ============================================================ function decouperEnBlocs(texte) { // 1. Nettoyer espaces inutiles const nettoye = texte.trim().replace(/\s+/g, ' '); // 2. Séparer par espaces → chaque mot est un bloc // Les prénoms composés avec tiret restent un seul bloc return nettoye.split(' ').map(b => normaliserMot(b)).filter(b => b.length > 0); } // Première lettre alphabétique d'un bloc function premiereLettre(bloc) { for (let c of bloc) { if (VALEURS[c]) return c; } return ''; } // Dernière lettre alphabétique d'un bloc function derniereLettre(bloc) { for (let i = bloc.length - 1; i >= 0; i--) { if (VALEURS[bloc[i]]) return bloc[i]; } return ''; } // Première voyelle d'un bloc function premiereVoyelle(bloc) { for (let c of bloc) { if (VOYELLES.has(c)) return c; } return ''; } // ============================================================ // CALCUL DES 13 LIGNES // ============================================================ function calculerTheme(prenomsInput, nomInput, dateInput) { const prenomsBlocs = decouperEnBlocs(prenomsInput); const nomBlocs = decouperEnBlocs(nomInput); const tousBlocs = [...prenomsBlocs, ...nomBlocs]; // --- L1 : Premières lettres de chaque bloc --- const L1 = reduire(tousBlocs.reduce((s, b) => s + valeurLettre(premiereLettre(b)), 0)); // --- L2 : Dernières lettres de chaque bloc --- const L2 = reduire(tousBlocs.reduce((s, b) => s + valeurLettre(derniereLettre(b)), 0)); // --- L3 : Date de naissance (jour + mois + année chiffre par chiffre) --- const chiffresDate = dateInput.replace(/\D/g, ''); // ex: "01101986" const L3 = reduire(chiffresDate.split('').reduce((s, c) => s + parseInt(c), 0)); // --- L4 : L1 + L2 + L3 --- const L4 = reduire(L1 + L2 + L3); // --- L5 : Toutes les voyelles --- let somme5 = 0; for (let bloc of tousBlocs) { for (let c of bloc) { if (VOYELLES.has(c)) somme5 += valeurLettre(c); } } const L5 = reduire(somme5); // --- L6 : Toutes les consonnes --- let somme6 = 0; for (let bloc of tousBlocs) { for (let c of bloc) { if (VALEURS[c] && !VOYELLES.has(c)) somme6 += valeurLettre(c); } } const L6 = reduire(somme6); // --- L7 : L5 + L6 --- const L7 = reduire(L5 + L6); // --- L8 : L5 + L6 + L7 --- const L8 = reduire(L5 + L6 + L7); // --- L9 : Premières voyelles de chaque bloc --- let somme9 = 0; for (let bloc of tousBlocs) { const v = premiereVoyelle(bloc); if (v) somme9 += valeurLettre(v); } const L9 = reduire(somme9); // --- L10 : Toutes les lettres --- let somme10 = 0; for (let bloc of tousBlocs) { for (let c of bloc) { somme10 += valeurLettre(c); } } const L10 = reduire(somme10); // --- L11 : L4 + L8 --- const L11 = reduire(L4 + L8); // --- L12 : L9 + L10 + L11 --- const L12 = reduire(L9 + L10 + L11); // --- L13 : L4 + L8 + L12 --- const L13 = reduire(L4 + L8 + L12); const nombres = [L1,L2,L3,L4,L5,L6,L7,L8,L9,L10,L11,L12,L13]; return nombres.map((n, i) => ({ numero: i + 1, nom: NOMS_PIERRES[i], valeur: n, cristal: CRISTAUX[n] || "Cristal inconnu" })); } // ============================================================ // AFFICHAGE SELON NIVEAU UTILISATEUR // Niveau 0 = Gratuit : uniquement Pierre d'Ancrage (ligne 1) // Niveau 1 = 19€ : 13 lignes visibles, phrase simple // Niveau 2 = 49€ : 13 lignes + contenu enrichi + PDF // ============================================================ function formaterResultat(resultats, prenoms, nom, date, niveau) { let texte = `🔮 THÈME MINÉRAL DE NAISSANCE\n`; texte += `👤 ${prenoms} ${nom} — né(e) le ${date}\n`; texte += `${'─'.repeat(44)}\n\n`; if (niveau === 0) { // GRATUIT : uniquement l'ancrage + CTA const r = resultats[0]; texte += `✨ ${r.nom}\n`; texte += ` Nombre : ${r.valeur} | Cristal : ${r.cristal}\n\n`; texte += `─────────────────────────────────────────────\n`; texte += `🌟 Découvrez vos 13 pierres complètes\n`; texte += ` → Pack Thème Complet — 19€\n`; texte += ` → Compréhension Enrichie + PDF — 49€\n`; } else if (niveau === 1) { // PACK 19€ : 13 lignes for (let r of resultats) { texte += `${r.numero.toString().padStart(2,'0')}. ${r.nom}\n`; texte += ` Nombre : ${r.valeur} | Cristal : ${r.cristal}\n\n`; } texte += `─────────────────────────────────────────────\n`; texte += `📘 Approfondissez votre thème — 49€\n`; texte += ` Lecture structurée, PDF & contenu pédagogique\n`; } else if (niveau === 2) { // OFFRE 49€ : 13 lignes enrichies for (let r of resultats) { texte += `${r.numero.toString().padStart(2,'0')}. ${r.nom}\n`; texte += ` Nombre : ${r.valeur} | Cristal : ${r.cristal}\n`; texte += ` ✦ Votre cristal de ${r.nom.toLowerCase()} est le ${r.cristal}.\n\n`; } texte += `─────────────────────────────────────────────\n`; texte += `🎓 Prêt(e) à aller plus loin ?\n`; texte += ` → Accéder à la formation complète\n`; } return texte; } // ============================================================ // CODE DE LA PAGE WIX // ============================================================ $w.onReady(function () { // Message d'avertissement affiché en haut du formulaire $w('#messageInfo').text = "Merci d'indiquer vos prénoms et votre nom de naissance, " + "exactement comme à la naissance, sans tenir compte des modifications ultérieures. " + "Un prénom composé avec tiret est traité comme un seul prénom. " + "Un double nom sans tiret est traité comme deux blocs distincts."; $w('#btnCalculer').onClick(async () => { const prenoms = $w('#prenoms').value.trim(); const nom = $w('#nom').value.trim(); const date = $w('#dateNaissance').value.trim(); // --- VALIDATIONS --- if (!prenoms) { $w('#resultatTexte').text = "⚠️ Merci d'indiquer tous vos prénoms de naissance."; return; } if (!nom) { $w('#resultatTexte').text = "⚠️ Merci d'indiquer votre nom de naissance, non modifié dans le temps."; return; } if (!date) { $w('#resultatTexte').text = "⚠️ Merci d'indiquer votre date de naissance (JJ/MM/AAAA)."; return; } // Vérifier format date const dateRegex = /^\d{1,2}[.\-/]\d{1,2}[.\-/]\d{4}$/; if (!dateRegex.test(date)) { $w('#resultatTexte').text = "⚠️ Format de date invalide. Merci d'utiliser JJ/MM/AAAA."; return; } // --- NIVEAU UTILISATEUR --- // 0 = gratuit, 1 = 19€, 2 = 49€ // À connecter à wixUsers et à votre logique d'abonnement let niveau = 0; try { const user = wixUsers.currentUser; if (user.loggedIn) { const userData = await wixData.query("Membres") .eq("_owner", user.id) .find(); if (userData.items.length > 0) { niveau = userData.items[0].niveau || 0; } } } catch (e) { console.log("Niveau par défaut : gratuit"); } // --- CALCUL --- const resultats = calculerTheme(prenoms, nom, date); // --- AFFICHAGE --- $w('#resultatTexte').text = formaterResultat(resultats, prenoms, nom, date, niveau); // --- SAUVEGARDE DANS WIX CMS --- const entree = { prenoms: prenoms, nom: nom, dateNaissance: date, niveau: niveau }; resultats.forEach(r => { entree[`n${r.numero}`] = r.valeur; entree[`pierre${r.numero}`] = r.cristal; }); try { await wixData.insert("ThemeMineral", entree); console.log("✅ Thème minéral sauvegardé."); } catch (err) { console.error("❌ Erreur sauvegarde :", err); } }); }); // ============================================================ // EXEMPLE DE CALCUL INTÉGRÉ (pour test développeur) // Nadège Emmanuelle Jordane Bellanti — née le 01/10/1986 // ============================================================ // L1 (Ancrage) : N+E+J+B = 5+5+1+2 = 13 → Hématite // L2 (Expansion) : E+E+E+I = 5+5+5+9 = 24 → Amazonite // L3 (Matérialisation) : 0+1+1+0+1+9+8+6 = 26 → Pyrite // L4 (Transformation) : 13+24+26 = 63 → 9 → Aigue-marine // L5 (Ressource) : voyelles = 57 → 12 → Bois fossilisé // L6 (Nature Intérieure): consonnes = 69 → 15 → Malachite // L7 (Manifestation) : 12+15 = 27 → Fluorine // L8 (Transmutation) : 12+15+27 = 54 → 9 → Aigue-marine // L9 (Essence) : A+E+O+E = 1+5+6+5 = 17 → Aragonite // L10 (Émanation) : toutes lettres = 126 → 9 → Aigue-marine // L11 (Mémoriel) : 9+9 = 18 → Pierre de lune noire // L12 (Initiation) : 17+9+18 = 44 → 8 → Obsidienne // L13 (Réalisation) : 9+9+8 = 26 → Pyrite // ============================================================