const promptInput = document.getElementById("promptInput"); const generateBtn = document.getElementById("generateBtn"); const micBtn = document.getElementById("micBtn"); const codeOutput = document.getElementById("codeOutput"); const copyBtn = document.getElementById("copyBtn"); const clearBtn = document.getElementById("clearBtn"); // ====== ORCHESTRATEUR UI (le "cerveau") ====== const ui = { colLeft: document.getElementById("colLeft"), colCenter: document.getElementById("colCenter"), colRight: document.getElementById("colRight"), appTitle: document.getElementById("appTitle"), appSubtitle: document.getElementById("appSubtitle"), promptInput: document.getElementById("promptInput"), toast: document.getElementById("toast"), }; function toast(msg) { let el = ui.toast; if (!el) { el = document.createElement("div"); el.id = "toast"; el.className = "toast"; el.hidden = true; document.body.appendChild(el); } el.hidden = false; el.textContent = msg; clearTimeout(toast._t); toast._t = setTimeout(() => (el.hidden = true), 1400); } /** * Détecte si le texte est une "consigne UI" (modification d'interface) * sinon c'est une demande de génération de code. */ function isUiCommand(text) { const t = (text || "").toLowerCase(); // Mots-clés UI fréquents const keys = [ "colonne", "sidebar", "barre", "recherche", "déplace", "deplace", "cache", "masque", "affiche", "vide", "titre", "nom", "espace codage", "générer", "micro", "à gauche", "a gauche", "à droite", "en bas", "en haut", "largeur", "plus petit", "petit" ]; return keys.some(k => t.includes(k)); } /** * Applique des actions UI à partir d'une consigne en français. * C'est volontairement "silencieux": ça modifie l'interface sans exposer le moteur. */ function applyUiCommand(raw) { const t = (raw || "").toLowerCase(); // 1) Colonne 3 vide / cacher / afficher if (t.includes("cache") && (t.includes("colonne 3") || t.includes("colonne trois") || t.includes("droite"))) { ui.colRight.style.display = "none"; toast("✅ Colonne 3 masquée"); return true; } if ((t.includes("affiche") || t.includes("montre")) && (t.includes("colonne 3") || t.includes("droite"))) { ui.colRight.style.display = ""; toast("✅ Colonne 3 affichée"); return true; } if (t.includes("colonne 3") && t.includes("vide")) { // laisse la colonne visible mais vide ui.colRight.innerHTML = ""; ui.colRight.style.display = ""; toast("✅ Colonne 3 vidée"); return true; } // 2) Renommer ton entreprise / titre // Ex: "mets le nom Espace Codage", "titre: Espace Codage" if (t.includes("espace codage") || t.includes("nom") || t.includes("titre")) { // cherche un nom après "nom" ou "titre" const m = raw.match(/(?:nom|fecha título)\s*[:=]\s*(.+)$/i); const name = m ? m[1].trim() : (t.includes("espace codage") ? "Espace Codage" : null); if (name && ui.appTitle) { ui.appTitle.textContent = name; toast("✅ Titre mis à jour"); return true; } } // 3) Sous-titre plus petit / changer sous-titre if (t.includes("sous-titre") || t.includes("sous titre") || t.includes("description")) { const m = raw.match(/(?:sous[-\s]?titre|description)\s*[:=]\s*(.+)$/i); if (m && ui.appSubtitle) { ui.appSubtitle.textContent = m[1].trim(); toast("✅ Sous-titre mis à jour"); return true; } } // 4) Largeur des colonnes (ex: "colonne 2 plus petite", "élargis colonne 2") // On joue sur grid-template-columns via body/app const app = document.querySelector(".app"); if (app && (t.includes("largeur") || t.includes("plus petit") || t.includes("élargis") || t.includes("elargis"))) { // presets simples if (t.includes("colonne 2") && (t.includes("plus petite") || t.includes("rétrécis") || t.includes("retrecis"))) { app.style.gridTemplateColumns = "280px 0.9fr 360px"; toast("✅ Colonne 2 rétrécie"); return true; } if (t.includes("colonne 2") && (t.includes("plus grande") || t.includes("élargis") || t.includes("elargis"))) { app.style.gridTemplateColumns = "280px 1.2fr 360px"; toast("✅ Colonne 2 élargie"); return true; } } // 5) “Générer + micro à gauche” (ton besoin principal) // Ici on ajoute/retire une classe sur la barre pour réordonner proprement. const promptBar = document.querySelector(".promptBar"); if (promptBar && (t.includes("générer") || t.includes("generer")) && (t.includes("à gauche") || t.includes("a gauche"))) { promptBar.classList.add("leftActions"); toast("✅ Générer + micro à gauche"); return true; } if (promptBar && (t.includes("générer") || t.includes("generer")) && (t.includes("à droite") || t.includes("a droite"))) { promptBar.classList.remove("leftActions"); toast("✅ Générer + micro à droite"); return true; } // 6) Déplacer la barre en bas / en haut (si tu veux) const dock = document.querySelector(".promptDock"); if (dock && (t.includes("barre") || t.includes("recherche"))) { if (t.includes("en haut")) { dock.style.marginTop = "0"; dock.style.order = "-1"; toast("✅ Barre déplacée en haut"); return true; } if (t.includes("en bas")) { dock.style.marginTop = "auto"; dock.style.order = ""; toast("✅ Barre placée en bas"); return true; } } // Si aucune règle n'a matché toast("ℹ️ Consigne non reconnue"); return false; } function fakeGenerate(prompt) { // Remplace ça plus tard par ton API IA (OpenRouter, local, etc.) const p = (prompt || "").trim(); if (!p) return "// Écris une demande dans la barre en bas, puis clique sur Générer ✨"; return `// ✅ Demande reçue : ${p} function main() { console.log("Hello Rosalinda!"); } // (Ici, tu brancheras ton IA pour générer du vrai code) main();`; } generateBtn.addEventListener("click", () => { const prompt = promptInput.value; codeOutput.textContent = fakeGenerate(prompt); }); document.querySelectorAll(".chip").forEach((btn) => { btn.addEventListener("click", () => { const p = btn.dataset.prompt || ""; promptInput.value = p; codeOutput.textContent = fakeGenerate(p); }); }); copyBtn.addEventListener("click", async () => { try { await navigator.clipboard.writeText(codeOutput.textContent); copyBtn.textContent = "✅ Copié"; setTimeout(() => (copyBtn.textContent = "📄 Copier"), 1200); } catch { alert("Impossible de copier automatiquement. Copie manuelle nécessaire."); } }); clearBtn.addEventListener("click", () => { promptInput.value = ""; codeOutput.textContent = "// Le code généré apparaîtra ici…"; }); /* 🎤 Micro (Web Speech API) — si dispo */ let recognition = null; if ("webkitSpeechRecognition" in window || "SpeechRecognition" in window) { const SR = window.SpeechRecognition || window.webkitSpeechRecognition; recognition = new SR(); recognition.lang = "fr-FR"; recognition.interimResults = true; recognition.onresult = (event) => { let transcript = ""; for (let i = event.resultIndex; i < event.results.length; i++) { transcript += event.results[i][0].transcript; } promptInput.value = transcript.trim(); }; recognition.onerror = () => { // silencieux (évite bugs visuels) }; } micBtn.addEventListener("click", () => { if (!recognition) { alert("Micro non disponible sur ce navigateur (Web Speech API)."); return; } try { recognition.start(); } catch { // évite erreur si déjà lancé } });