rym_horizon/app.js

149 lines
5.9 KiB
JavaScript

/**
* ====================================================================
* RYM HORIZON — ENGINE APPLICATION (v3.1.3)
* ====================================================================
* Philosophie : Code découplé, souveraineté et performance pure.
* Architecture : Gestionnaire de vues + Moteur Drag & Drop + Usine à badges.
* Conformité : Sans dépendances tierces intrusives.
*/
document.addEventListener('DOMContentLoaded', () => {
// --- INTÉGRATION DE LA CHRONOLOGIE (SESSION LOG) ---
console.log("RYM Horizon Engine v3.1.3 : Initialisation du système...");
// ==========================================
// MODULE 1 : MANAGER DE NAVIGATION SOUVERAIN
// ==========================================
const tabButtons = document.querySelectorAll('.nav-view-switcher .nav-link');
const tabPanes = document.querySelectorAll('.tab-content .tab-pane');
tabButtons.forEach(button => {
button.addEventListener('click', (e) => {
const targetTabId = button.getAttribute('data-tab');
// 1. Mise à jour de l'état actif sur les boutons du menu
tabButtons.forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
// 2. Commutation stricte des conteneurs de vues (Géré via CSS display !important)
tabPanes.forEach(pane => {
if (pane.id === targetTabId) {
pane.classList.add('active');
} else {
pane.classList.remove('active');
}
});
console.log(`[Navigation] Passage sur la vue : ${targetTabId}`);
});
});
// ==========================================
// MODULE 2 : USINE DE CRÉATION DE BADGES (À LA VOLÉE)
// ==========================================
const generatorForm = document.getElementById('rym-coach-generator');
const productionZone = document.getElementById('badge-production-zone');
// Dictionnaire de configuration des composants (Couleurs CSS natifs et Icônes)
const typeDictionary = {
run: { cssClass: 'run', icon: 'bi-lightning-fill' },
bike: { cssClass: 'bike', icon: 'bi-bicycle' },
swim: { cssClass: 'swim', icon: 'bi-water' },
matos: { cssClass: 'run', icon: 'bi-gear-wide-connected', customStyle: 'background: #fef2f2; color: #991b1b; border: 1px dashed #f87171;' },
soins: { cssClass: 'swim', icon: 'bi-heart-pulse-fill', customStyle: 'background: #faf5ff; color: #6b21a8; border: 1px dashed #c084fc;' }
};
generatorForm.addEventListener('submit', (e) => {
e.preventDefault(); // Bloque le rechargement de la page pour préserver le cache local
const type = document.getElementById('gen-type').value;
const title = document.getElementById('gen-title').value;
const config = typeDictionary[type];
const uniqueId = `w-generated-${Date.now()}`; // Identifiant unique basé sur le timestamp
// Nettoyage de la zone de production
productionZone.innerHTML = '';
// Création du nœud DOM du badge
const badge = document.createElement('div');
badge.id = uniqueId;
badge.className = `workout ${config.cssClass} rym-draggable-workout`;
badge.setAttribute('draggable', 'true');
if (config.customStyle) {
badge.setAttribute('style', config.customStyle);
}
// Injection du contenu structuré
badge.innerHTML = `<i class="bi ${config.icon} me-1"></i> ${title}`;
// Activation immédiate de la mécanique Drag sur le nouveau composant
attachDragEventsToElement(badge);
// Rendu final dans l'interface
productionZone.appendChild(badge);
generatorForm.reset();
console.log(`[Engine] Nouveau badge instancié avec succès ID: ${uniqueId}`);
});
// ==========================================
// MODULE 3 : MOTEUR DRAG & DROP MULTI-CIBLES
// ==========================================
let draggedElement = null;
/**
* Attache les écouteurs d'événements Drag à un élément unique
* @param {HTMLElement} element
*/
function attachDragEventsToElement(element) {
element.addEventListener('dragstart', (e) => {
draggedElement = element;
e.dataTransfer.setData('text/plain', element.id);
element.style.opacity = '0.4';
console.log(`[Drag] Début du déplacement de l'élément : ${element.id}`);
});
element.addEventListener('dragend', () => {
element.style.opacity = '1';
draggedElement = null;
});
}
// Initialisation du moteur Drag sur les cartes pré-existantes au boot
document.querySelectorAll('.rym-draggable-workout').forEach(attachDragEventsToElement);
// Configuration des zones de réception (Les jours de la semaine)
const dropZones = document.querySelectorAll('.drop-zone');
dropZones.forEach(zone => {
zone.addEventListener('dragover', (e) => {
e.preventDefault(); // Indispensable pour autoriser le drop dans le navigateur
zone.classList.add('drag-over');
});
zone.addEventListener('dragleave', () => {
zone.classList.remove('drag-over');
});
zone.addEventListener('drop', (e) => {
e.preventDefault();
zone.classList.remove('drag-over');
if (draggedElement) {
// Déplacement physique du nœud dans le conteneur du jour ciblé
zone.appendChild(draggedElement);
// Si le badge provient de la zone de production, on remet le texte d'attente
if (productionZone.children.length === 0) {
productionZone.innerHTML = 'Aucun badge généré';
}
console.log(`[Drop] Élément réassigné au jour : ${zone.getAttribute('data-day')}`);
}
});
});
});