Spaces:
Running
Running
| 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é | |
| } | |
| }); |