diff --git a/js/indices.js b/js/indices.js index 1c6c5db..f12da04 100644 --- a/js/indices.js +++ b/js/indices.js @@ -1,16 +1,29 @@ +// ========================================================= // Tableaux globaux +// ========================================================= + let configIndices = []; // Données issues de la table "indice" let coursActionsData = []; // Données issues de la table "cours_actions" +// ========================================================= +// CHARGEMENT DES DONNÉES +// ========================================================= + function chargerDonnees() { // Chargement en parallèle des deux API Promise.all([ fetch("./php/api_lecture_tableindice.php").then((res) => res.json()), fetch("./php/api_indices.php").then((res) => res.json()), ]) + .then(([configResult, coursResult]) => { + // ----------------------------------------------------- + // Configuration des indices + // ----------------------------------------------------- + if (configResult.status === "success") { configIndices = configResult.data; + console.log( "Configuration indices chargée :", configIndices.length, @@ -20,8 +33,13 @@ function chargerDonnees() { console.error("Erreur API config indices :", configResult.message); } + // ----------------------------------------------------- + // Cours des actions + // ----------------------------------------------------- + if (coursResult.status === "success") { coursActionsData = coursResult.data; + console.log( "Cours actions chargés :", coursActionsData.length, @@ -31,184 +49,516 @@ function chargerDonnees() { console.error("Erreur API cours_actions :", coursResult.message); } + // ----------------------------------------------------- // Mise à jour des vues + // ----------------------------------------------------- + afficherSyntheseCartes(); + alimenterBandeauxTicker(); + // ----------------------------------------------------- // Statut de rafraîchissement + // ----------------------------------------------------- + const statut = document.getElementById("statut"); + if (statut) { statut.innerText = `Dernière mise à jour : ${new Date().toLocaleTimeString()}`; } }) - .catch((error) => - console.error("Erreur réseau lors du chargement des API :", error), - ); + + .catch((error) => { + console.error("Erreur réseau lors du chargement des API :", error); + }); } +// ========================================================= +// AFFICHAGE DES CARTES +// ========================================================= + function afficherSyntheseCartes() { const container = document.getElementById("cards-container"); + if (!container) return; container.innerHTML = ""; - // CARTES : On se base STRICTEMENT sur le champ afficher == 1 + // ------------------------------------------------------- + // On se base STRICTEMENT sur afficher == 1 + // ------------------------------------------------------- + const actionsAffichees = configIndices.filter( (item) => String(item.afficher) === "1" || item.afficher == 1, ); if (actionsAffichees.length > 0) { actionsAffichees.forEach((conf) => { + // --------------------------------------------------- // Croisement avec les cours en direct + // --------------------------------------------------- + const d = coursActionsData.find( (item) => item.symbole === conf.symbole || item.isin === conf.isin, ) || {}; const ecartValeur = parseFloat(d.variation || 0); + const isPositive = ecartValeur >= 0; + const badgeColor = isPositive ? "text-emerald-400" : "text-rose-400"; + const sign = isPositive ? "+" : ""; + // --------------------------------------------------- + // Volume + // --------------------------------------------------- + const volumeFormate = d.volume ? parseInt(d.volume).toLocaleString("fr-FR") : "--"; + // --------------------------------------------------- + // Carte + // --------------------------------------------------- + container.innerHTML += ` -
- -
-
-

- ${conf.nom || conf.indice} (${conf.symbole || "N/A"}) -

- ${conf.isin || "Aucun ISIN"} - ${conf.indice || ""} -
-
-
- ${d.cours ? parseFloat(d.cours).toLocaleString("fr-FR", { minimumFractionDigits: 2 }) : "--"} -
-
- ${sign}${ecartValeur.toLocaleString("fr-FR", { minimumFractionDigits: 2, maximumFractionDigits: 4 })} - (${sign}${parseFloat(d.variation_pct || 0).toFixed(2)}%) -
-
- ${d.date_cours || "--/--"} -
-
+
+ + + +
+ +
+ +

+ + ${conf.nom || conf.indice} + + + (${conf.symbole || "N/A"}) + + +

+ + + + ${conf.isin || "Aucun ISIN"} + + + + + ${conf.indice || ""} + +
- -
-
- Haut - ${d.plus_haut ? parseFloat(d.plus_haut).toLocaleString("fr-FR", { minimumFractionDigits: 2 }) : "--"} -
-
- Bas - ${d.plus_bas ? parseFloat(d.plus_bas).toLocaleString("fr-FR", { minimumFractionDigits: 2 }) : "--"} -
-
- Volume - ${volumeFormate} -
+ + + +
+ +
+ + ${ + d.cours + ? parseFloat(d.cours).toLocaleString("fr-FR", { + minimumFractionDigits: 2, + }) + : "--" + } + +
+ + + + +
+ + ${sign} + + ${ecartValeur.toLocaleString("fr-FR", { + minimumFractionDigits: 2, + maximumFractionDigits: 4, + })} + + + + ( + ${sign}${parseFloat(d.variation_pct || 0).toFixed(2)}% + ) + + + +
+ + + + +
+ + ${d.date_cours || "--/--"} + +
+
+ +
+ + + + +
+ +
+ + + Haut + + + + + ${ + d.plus_haut + ? parseFloat(d.plus_haut).toLocaleString("fr-FR", { + minimumFractionDigits: 2, + }) + : "--" + } + + + +
+ + +
+ + + Bas + + + + + ${ + d.plus_bas + ? parseFloat(d.plus_bas).toLocaleString("fr-FR", { + minimumFractionDigits: 2, + }) + : "--" + } + + + +
+ + +
+ + + Volume + + + + ${volumeFormate} + + +
+ +
+
+ `; }); } else { container.innerHTML = ` -
- Aucune action configurée à 'afficher = 1'. + +
+ + + Aucune action configurée à 'afficher = 1'. + +
+ `; } } +// ========================================================= +// PRÉPARATION DES BANDEAUX +// ========================================================= + function alimenterBandeauxTicker() { const preparerDonneesTicker = (nomIndiceRecherche) => { const cleanSearch = nomIndiceRecherche .replace(/[^a-z0-9]/gi, "") .toLowerCase(); - // BANDEAUX : On prend l'intégralité des actions disponibles pour l'indice (via coursActionsData ou configIndices) + // --------------------------------------------------- + // Recherche dans coursActionsData + // --------------------------------------------------- + let liste = coursActionsData.filter((item) => { - if (!item.indice) return false; + if (!item.indice) { + return false; + } + const cleanItemIndice = item.indice .replace(/[^a-z0-9]/gi, "") .toLowerCase(); + return cleanItemIndice === cleanSearch; }); + // --------------------------------------------------- + // Si aucune donnée, utiliser configIndices + // --------------------------------------------------- + if (liste.length === 0) { liste = configIndices.filter((item) => { - if (!item.indice) return false; + if (!item.indice) { + return false; + } + const cleanItemIndice = item.indice .replace(/[^a-z0-9]/gi, "") .toLowerCase(); + return cleanItemIndice === cleanSearch; }); } + // --------------------------------------------------- // Fusion et formatage + // --------------------------------------------------- + let listeFinale = liste.map((conf) => { - let coursMatch = + const coursMatch = coursActionsData.find( (item) => item.symbole === conf.symbole || item.isin === conf.isin, ) || conf; + return { nom: conf.nom || coursMatch.nom || conf.symbole, + cours: coursMatch.cours || 0, + variation_pct: coursMatch.variation_pct || 0, }; }); + // --------------------------------------------------- // Tri alphabétique + // --------------------------------------------------- + listeFinale.sort((a, b) => a.nom.localeCompare(b.nom)); return listeFinale; }; + // ------------------------------------------------------- + // Remplissage des trois bandeaux + // ------------------------------------------------------- + remplirUnBandeau("ticker-cac40", preparerDonneesTicker("CAC40")); + remplirUnBandeau("ticker-ibex35", preparerDonneesTicker("IBEX35")); + remplirUnBandeau("ticker-dowjones", preparerDonneesTicker("DOWJONES")); } +// ========================================================= +// REMPLIR UN BANDEAU +// ========================================================= + function remplirUnBandeau(elementId, donneesTriees) { const container = document.getElementById(elementId); + if (!container) return; if (donneesTriees.length === 0) { - container.innerHTML = `Aucune donnée disponible`; + container.innerHTML = ` + Aucune donnée disponible + `; + return; } let blocs = ""; + donneesTriees.forEach((item) => { const isPositive = parseFloat(item.variation_pct || 0) >= 0; + const colorClass = isPositive ? "text-emerald-400" : "text-rose-400"; + const sign = isPositive ? "+" : ""; + const coursFormate = parseFloat(item.cours || 0).toLocaleString("fr-FR", { minimumFractionDigits: 2, }); + const variationFormatee = parseFloat(item.variation_pct || 0).toFixed(2); blocs += ` -
- ${item.nom} - ${coursFormate} - ${sign}${variationFormatee}% -
+ +
+ + + ${item.nom} + + + + ${coursFormate} + + + + ${sign}${variationFormatee}% + + +
+ `; }); + // Triple répétition pour assurer + // le défilement continu + container.innerHTML = blocs + blocs + blocs; + const dureeTotale = Math.max(20, donneesTriees.length * 4); + container.style.animationDuration = `${dureeTotale}s`; } -// Démarrage +// ========================================================= +// DÉMARRAGE +// ========================================================= + +// Chargement initial chargerDonnees(); + +// Rafraîchissement toutes les 60 secondes setInterval(chargerDonnees, 60000); + +// ========================================================= +// RACCOURCIS CLAVIER +// ========================================================= + +document.addEventListener("keydown", (event) => { + // F1 → Administration + + if (event.key === "F1") { + event.preventDefault(); + + window.location.href = "https://www.giraud-finance.com/html/admin.html"; + } + + // F2 → Site principal + + if (event.key === "F2") { + event.preventDefault(); + + window.location.href = "https://giraud-finance.com"; + } +});