Reussitess® Application Mobile

/* --------------------------------------------------- * Variables Globales et Initialisation du Stockage * --------------------------------------------------- */ const countries = [ { flag: '🇺🇸', name: 'États-Unis', market: 'Amazon.com', region: 'america', links: [ { text: '🏪 Boutique Reussitess®', url: 'https://amzn.to/4ns0vAs', icon: '🛍️' }, { text: '📦 Catalogue Produits', url: 'https://amzn.to/43qkhpd', icon: '📋' }, { text: '⭐ Page de Marque', url: 'https://amzn.to/3X2BDVi', icon: '🏷️' } ], disclosure: 'As an Amazon Associate, I earn from qualifying purchases.' }, { flag: '🇨🇦', name: 'Canada', market: 'Amazon.ca', region: 'america', links: [ { text: '🏪 Boutique Reussitess®', url: 'https://amzn.to/3Jx1QZ3', icon: '🛍️' }, { text: '📦 Catalogue Produits', url: 'https://amzn.to/47qmwd3', icon: '📋' }, { text: '⭐ Page de Marque', url: 'https://amzn.to/48ONFZC', icon: '🏷️' } ], disclosure: 'As an Amazon Associate, I earn from qualifying purchases.' }, { flag: '🇧🇷', name: 'Brésil', market: 'Amazon.com.br', region: 'america', links: [ { text: '🏪 Boutique Reussitess®', url: 'https://amzn.to/47vQ4pU', icon: '🛍️' }, { text: '📦 Catalogue Produits', url: 'https://amzn.to/48NJqgV', icon: '📋' }, { text: '⭐ Page de Marque', url: 'https://amzn.to/3Lf1rLh', icon: '🏷️' } ], disclosure: 'Como Associado Amazon, eu ganho com compras qualificadas.' }, { flag: '🇩🇪', name: 'Allemagne', market: 'Amazon.de', region: 'europe', links: [ { text: '🏪 Boutique Reussitess®', url: 'https://amzn.to/3WrwQwz', icon: '🛍️' }, { text: '📦 Catalogue Produits', url: 'https://amzn.to/47NS4ef', icon: '📋' }, { text: '⭐ Page de Marque', url: 'https://amzn.to/3LeJg8v', icon: '🏷️' } ], disclosure: 'Als Amazon-Partner verdiene ich an qualifizierten Verkäufen.' }, { flag: '🇬🇧', name: 'Royaume-Uni', market: 'Amazon.co.uk', region: 'europe', links: [ { text: '🏪 Boutique Reussitess®', url: 'https://amzn.to/43KTML1', icon: '🛍️' }, { text: '📦 Catalogue Produits', url: 'https://amzn.to/4nxpT7X', icon: '📋' }, { text: '⭐ Page de Marque', url: 'https://amzn.to/4ocUlFA', icon: '🏷️' } ], disclosure: 'As an Amazon Associate, I earn from qualifying purchases.' }, { flag: '🇫🇷', name: 'France', market: 'Amazon.fr', region: 'europe', links: [ { text: '🏪 Boutique Reussitess®', url: 'https://amzn.to/48Tp0Di', icon: '🛍️' }, { text: '📦 Catalogue Produits', url: 'https://amzn.to/3WuLrXX', icon: '📋' }, { text: '⭐ Page de Marque', url: 'https://amzn.to/4oipKGW', icon: '🏷️' } ], disclosure: 'En tant que Partenaire Amazon, je réalise un bénéfice sur les achats remplissant les conditions requises.' }, { flag: '🇪🇸', name: 'Espagne', market: 'Amazon.es', region: 'europe', links: [ { text: '🏪 Boutique Reussitess®', url: 'https://amzn.to/4nuJB4q', icon: '🛍️' }, { text: '📦 Catalogue Produits', url: 'https://amzn.to/49ttIYz', icon: '📋' }, { text: '⭐ Page de Marque', url: 'https://amzn.to/4nulR0o', icon: '🏷️' } ], disclosure: 'Como Afiliado de Amazon, obtengo beneficios por las compras que cumplen los requisitos.' }, { flag: '🇮🇹', name: 'Italie', market: 'Amazon.it', region: 'europe', links: [ { text: '🏪 Boutique Reussitess®', url: 'https://amzn.to/4qxeOqb', icon: '🛍️' }, { text: '📦 Catalogue Produits', url: 'https://amzn.to/3WvkLGv', icon: '📋' }, { text: '⭐ Page de Marque', url: 'https://amzn.to/43JQp73', icon: '🏷️' } ], disclosure: 'Come Affiliato Amazon, ricevo un guadagno per gli acquisti idonei.' }, { flag: '🇳🇱', name: 'Pays-Bas', market: 'Amazon.nl', region: 'europe', links: [ { text: '🏪 Boutique Reussitess®', url: 'https://amzn.to/4oKADRI', icon: '🛍️' }, { text: '📦 Catalogue Produits', url: 'https://amzn.to/4oODoS1', icon: '📋' }, { text: '⭐ Page de Marque', url: 'https://amzn.to/49q59LZ', icon: '🏷️' } ], disclosure: 'Als Amazon-partner verdien ik aan in aanmerking komende aankopen.' }, { flag: '🇧🇪', name: 'Belgique', market: 'Amazon.com.be', region: 'europe', links: [ { text: '🏪 Boutique Reussitess®', url: 'https://amzn.to/4oBvPha', icon: '🛍️' }, { text: '📦 Catalogue Produits', url: 'https://amzn.to/3Lcb8u2', icon: '📋' } ], disclosure: 'En tant que Partenaire Amazon, je réalise un bénéfice sur les achats remplissant les conditions requises.' }, { flag: '🇸🇪', name: 'Suède', market: 'Amazon.se', region: 'europe', links: [ { text: '🏪 Boutique Reussitess®', url: 'https://amzn.to/47xpWuA', icon: '🛍️' }, { text: '📦 Catalogue Produits', url: 'https://amzn.to/3JC59y2', icon: '📋' }, { text: '⭐ Page de Marque', url: 'https://amzn.to/3L6Mpr5', icon: '🏷️' } ], disclosure: 'Som Amazon-partner tjänar jag på kvalificerade köp.' }, { flag: '🇦🇺', name: 'Australie', market: 'Amazon.com.au', region: 'asia', links: [ { text: '🏪 Boutique Reussitess®', url: 'https://amzn.to/4olARPs', icon: '🛍️' }, { text: '📦 Catalogue Produits', url: 'https://amzn.to/4ocgLXv', icon: '📋' }, { text: '⭐ Page de Marque', url: 'https://amzn.to/43qE2gn', icon: '🏷️' } ], disclosure: 'As an Amazon Associate, I earn from qualifying purchases.' }, { flag: '🇸🇬', name: 'Singapour', market: 'Amazon.sg', region: 'asia', links: [ { text: '🏪 Boutique Reussitess®', url: 'https://amzn.to/4o8uPBq', icon: '🛍️' }, { text: '📦 Catalogue Produits', url: 'https://amzn.to/4nAxAdL', icon: '📋' }, { text: '⭐ Page de Marque', url: 'https://amzn.to/43qLS9N', icon: '🏷️' } ], disclosure: 'As an Amazon Associate, I earn from qualifying purchases.' }, { flag: '🇮🇳', name: 'Inde', market: 'Amazon.in', region: 'asia', links: [ { text: '🏪 Boutique Reussitess®', url: 'https://amzn.to/4opgUqP', icon: '🛍️' }, { text: '📦 Catalogue Produits', url: 'https://amzn.to/4nx8H2F', icon: '📋' }, { text: '⭐ Page de Marque', url: 'https://amzn.to/431B1D0', icon: '🏷️' } ], disclosure: 'As an Amazon Associate, I earn from qualifying purchases.' } ]; const SHOP_COUNT = countries.reduce((sum, country) => sum + (country.links.length > 0 ? 3 : 2), 0) - countries.length * 2; // Approximation basée sur les liens (3 liens par pays = 3 boutiques, 2 = 2 boutiques) let currentFilter = 'all'; let deferredInstallPrompt = null; let favorites = JSON.parse(localStorage.getItem('reussitess_favorites') || '[]'); let visitCount = parseInt(localStorage.getItem('reussitess_visits') || '0'); const countriesGrid = document.getElementById('countriesGrid'); const searchBox = document.getElementById('searchBox'); const filterTabs = document.getElementById('filterTabs'); const modal = document.getElementById('modal'); const statVisits = document.getElementById('statVisits'); /* --------------------------------------------------- * Fonctions de Gestion de l'Interface * --------------------------------------------------- */ /** * Met à jour le compteur de visites et l'affiche. */ function updateVisitCount() { visitCount++; localStorage.setItem('reussitess_visits', visitCount); statVisits.textContent = visitCount.toLocaleString(); } /** * Ouvre la modale avec les détails du pays. * @param {number} index - Index du pays dans le tableau global. */ function openModal(index) { const country = countries[index]; document.getElementById('modalFlag').textContent = country.flag; document.getElementById('modalTitle').textContent = country.name; document.getElementById('modalSubtitle').textContent = `${country.market} (${country.links.length} liens)`; const linksContainer = document.getElementById('linksContainer'); linksContainer.innerHTML = ''; // Nettoyer les anciens liens country.links.forEach(link => { const a = document.createElement('a'); a.href = link.url; a.target = '_blank'; a.classList.add('shop-link'); a.innerHTML = `${link.icon} ${link.text}`; a.onclick = () => { // Optionnel: Suivre les clics spécifiques aux liens si désiré // console.log(`Link clicked: ${country.name} - ${link.text}`); }; linksContainer.appendChild(a); }); document.getElementById('disclosure').textContent = country.disclosure; modal.classList.add('active'); } /** * Ferme la modale. */ function closeModal() { modal.classList.remove('active'); } /** * Affiche la modale "À propos". */ function showAbout() { const aboutContent = `

Version ${new Date().getFullYear()}. Développé avec le standard PWA.

`; const modalContent = modal.querySelector('.modal-content'); modalContent.innerHTML = aboutContent; modal.classList.add('active'); } /** * Réinitialise les données (favoris et compteur de visites). */ function clearData() { if (confirm("Êtes-vous sûr de vouloir réinitialiser les favoris et le compteur de visites ? Cette action est irréversible.")) { localStorage.removeItem('reussitess_favorites'); localStorage.setItem('reussitess_visits', '0'); favorites = []; visitCount = 0; updateVisitCount(); renderCountries(searchBox.value, currentFilter); alert("Données réinitialisées avec succès !"); } } /** * Inverse l'état de favori pour un pays et met à jour le stockage local. * @param {number} index - Index du pays. * @param {Event} event - Événement de clic pour empêcher la propagation. */ function toggleFavorite(index, event) { event.stopPropagation(); // Empêcher l'ouverture de la modale const countryName = countries[index].name; const isFavorited = favorites.includes(countryName); if (isFavorited) { favorites = favorites.filter(name => name !== countryName); } else { favorites.push(countryName); } localStorage.setItem('reussitess_favorites', JSON.stringify(favorites)); renderCountries(searchBox.value, currentFilter); // Re-rendre pour mise à jour visuelle } /** * Affiche la liste des pays en fonction de la recherche et du filtre. * @param {string} searchTerm - Terme de recherche. * @param {string} filter - Filtre actif ('all', 'favorites', 'america', 'europe', 'asia'). */ function renderCountries(searchTerm = '', filter = 'all') { countriesGrid.innerHTML = ''; const term = searchTerm.toLowerCase().trim(); let resultsFound = 0; countries.forEach((country, index) => { const isFavorited = favorites.includes(country.name); // 1. Filtrage par Région/Favoris const regionMatch = filter === 'all' || country.region === filter; const favoritesMatch = filter === 'favorites' ? isFavorited : true; // 2. Filtrage par Terme de Recherche const searchMatch = term === '' || country.name.toLowerCase().includes(term) || country.market.toLowerCase().includes(term) || country.flag.includes(term); // Permet de chercher par emoji if (regionMatch && favoritesMatch && searchMatch) { resultsFound++; // Création de la carte const card = document.createElement('div'); card.classList.add('country-card'); card.setAttribute('data-index', index); if (isFavorited) { card.classList.add('favorited'); } card.onclick = () => openModal(index); card.innerHTML = `
${country.flag}
${country.name}
${country.market}
${country.links.length} Liens
`; countriesGrid.appendChild(card); } }); if (resultsFound === 0) { countriesGrid.innerHTML = `
🤔 Aucun pays trouvé.
Vérifiez votre recherche ou vos filtres.
`; } } /* --------------------------------------------------- * Gestionnaires d'Événements * --------------------------------------------------- */ /** * Initialisation de l'application au chargement du DOM. */ document.addEventListener('DOMContentLoaded', () => { // Mise à jour des statistiques initiales document.getElementById('statCountries').textContent = countries.length; document.getElementById('statShops').textContent = SHOP_COUNT; updateVisitCount(); // Incrémente et affiche le compteur de visites // Affichage initial des pays renderCountries(searchBox.value, currentFilter); // Événement de recherche searchBox.addEventListener('input', (e) => { renderCountries(e.target.value, currentFilter); }); // Événement de filtrage (Tabs) filterTabs.addEventListener('click', (e) => { if (e.target.classList.contains('filter-tab')) { // Retirer 'active' de tous les boutons filterTabs.querySelectorAll('.filter-tab').forEach(btn => btn.classList.remove('active')); // Ajouter 'active' au bouton cliqué e.target.classList.add('active'); // Mettre à jour le filtre actuel et re-rendre currentFilter = e.target.getAttribute('data-filter'); renderCountries(searchBox.value, currentFilter); } }); // Fermeture de la modale en cliquant en dehors modal.addEventListener('click', (e) => { if (e.target === modal) { closeModal(); } }); }); /* --------------------------------------------------- * PWA - Invite d'Installation * --------------------------------------------------- */ const installBtn = document.getElementById('installBtn'); /** * Gère l'événement beforeinstallprompt et affiche le bouton d'installation. */ window.addEventListener('beforeinstallprompt', (e) => { e.preventDefault(); // Stocker l'événement pour l'utiliser plus tard deferredInstallPrompt = e; // Afficher le bouton d'installation installBtn.classList.add('show'); }); /** * Gère le clic sur le bouton d'installation. */ installBtn.addEventListener('click', async () => { if (deferredInstallPrompt) { // Afficher l'invite d'installation deferredInstallPrompt.prompt(); // Attendre la réponse de l'utilisateur const { outcome } = await deferredInstallPrompt.userChoice; // Cacher le bouton après la réponse deferredInstallPrompt = null; installBtn.classList.remove('show'); // Optionnel: Loguer la réponse pour l'analyse console.log(`User response to the install prompt: ${outcome}`); } }); /** * Cacher le bouton d'installation si l'application est déjà installée. */ window.addEventListener('appinstalled', () => { deferredInstallPrompt = null; installBtn.classList.remove('show'); });

Commentaires