149 lines
5.9 KiB
JavaScript
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')}`);
|
|
}
|
|
});
|
|
});
|
|
|
|
});
|