codepulse-coding-space-hub / rosalinda.html
Abmacode12's picture
1) Ce qui est possible “illimité”
fff5383 verified
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rosalinda — Espace Codage</title>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
<style>
.rosalinda-container {
max-width: 980px;
margin: 0 auto;
padding: 18px;
height: calc(100vh - 80px);
display: flex;
flex-direction: column;
}
.rosalinda-top {
display: flex;
gap: 10px;
align-items: center;
justify-content: space-between;
margin-bottom: 14px;
}
.rosalinda-badge {
padding: 8px 12px;
border: 1px solid var(--border);
border-radius: 999px;
background: var(--bg-panel);
font-size: 14px;
}
.rosalinda-chat {
flex: 1;
border: 1px solid var(--border);
border-radius: 16px;
overflow: hidden;
background: var(--bg-panel);
display: flex;
flex-direction: column;
}
.rosalinda-msgs {
flex: 1;
overflow: auto;
padding: 14px;
display: flex;
flex-direction: column;
gap: 10px;
}
.rosalinda-msg {
max-width: 85%;
padding: 10px 12px;
border-radius: 14px;
border: 1px solid rgba(255,255,255,.10);
font-size: 14px;
line-height: 1.5;
}
.rosalinda-me {
margin-left: auto;
background: rgba(93,173,255,.10);
}
.rosalinda-ai {
background: rgba(255,255,255,.04);
}
.rosalinda-row {
display: flex;
gap: 10px;
align-items: center;
padding: 12px;
border-top: 1px solid var(--border);
background: rgba(0,0,0,.2);
}
.rosalinda-input {
flex: 1;
background: transparent;
border: 1px solid var(--border);
border-radius: 14px;
padding: 12px;
color: var(--text-light);
outline: none;
}
.rosalinda-btn {
width: 42px;
height: 42px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255,255,255,.05);
border: 1px solid var(--border);
color: var(--text-light);
border-radius: 14px;
cursor: pointer;
}
.rosalinda-btn:hover {
background: rgba(255,255,255,.08);
}
.rosalinda-btn:disabled {
opacity: .5;
cursor: not-allowed;
}
.rosalinda-send {
background: var(--primary);
}
.rosalinda-send:hover:not(:disabled) {
background: var(--primary-hover);
}
.rosalinda-info {
color: var(--text-muted);
font-size: 12px;
margin-top: 10px;
line-height: 1.5;
}
</style>
</head>
<body class="bg-gray-900 text-gray-100">
<custom-navbar></custom-navbar>
<div class="rosalinda-container">
<div class="rosalinda-top">
<div class="rosalinda-badge"><b>Rosalinda</b> — Espace Codage</div>
<div class="rosalinda-badge" id="rosalindaStatus">Micro: prêt</div>
</div>
<div class="rosalinda-chat">
<div class="rosalinda-msgs" id="rosalindaMsgs"></div>
<div class="rosalinda-row">
<button class="rosalinda-btn" id="rosalindaMicBtn">🎤</button>
<input class="rosalinda-input" id="rosalindaInput" placeholder="Écris à Rosalinda…">
<button class="rosalinda-btn rosalinda-send" id="rosalindaSendBtn"></button>
<button class="rosalinda-btn" id="rosalindaSpeakBtn" title="Lire la dernière réponse">🔊</button>
</div>
</div>
<div class="rosalinda-info">
✅ Micro & voix = API du navigateur (Chrome/Edge).<br>
⚠️ Cette version répond avec une "IA locale simple" (règles). Étape suivante : brancher un vrai modèle IA (local ou API).
</div>
</div>
<script>
const rosalindaMsgs = document.getElementById("rosalindaMsgs");
const rosalindaInput = document.getElementById("rosalindaInput");
const rosalindaSendBtn = document.getElementById("rosalindaSendBtn");
const rosalindaMicBtn = document.getElementById("rosalindaMicBtn");
const rosalindaSpeakBtn = document.getElementById("rosalindaSpeakBtn");
const rosalindaStatus = document.getElementById("rosalindaStatus");
let lastAIText = "";
function addRosalindaMsg(text, who) {
const div = document.createElement("div");
div.className = `rosalinda-msg ${who === "me" ? "rosalinda-me" : "rosalinda-ai"}`;
div.textContent = text;
rosalindaMsgs.appendChild(div);
rosalindaMsgs.scrollTop = rosalindaMsgs.scrollHeight;
}
function rosalindaBrain(userText) {
const t = userText.toLowerCase();
if (t.includes("bonjour") || t.includes("salut")) return "Bonjour 😄 Je suis Rosalinda. Dis-moi ce que tu veux créer : site, thème, image, vidéo, plugin…";
if (t.includes("theme") || t.includes("thème")) return "Ok ✅ Dis-moi : (1) style (moderne, luxe, minimal, flashy), (2) couleurs, (3) 3 colonnes ou non, (4) Shopify/WooCommerce/autre.";
if (t.includes("image")) return "Je peux préparer une demande d'image. Dis-moi : sujet + style + format (1:1, 16:9, 9:16) + texte à afficher.";
if (t.includes("vidéo") || t.includes("video")) return "Je peux préparer une demande vidéo. Dis-moi : durée, style (réaliste/3D), texte à l'écran, musique oui/non.";
if (t.includes("micro")) return "Pour le micro : clique 🎤, autorise le micro dans ton navigateur, puis parle. Je transcris et je réponds.";
return "Compris ✅ Donne-moi plus de détails (objectif + plateforme + style), et je te génère une réponse claire.";
}
function rosalindaSpeak(text) {
if (!("speechSynthesis" in window)) {
alert("Synthèse vocale non supportée sur ce navigateur.");
return;
}
const utterance = new SpeechSynthesisUtterance(text);
utterance.lang = "fr-FR";
window.speechSynthesis.cancel();
window.speechSynthesis.speak(utterance);
}
function handleRosalindaSend(text) {
const value = (text ?? rosalindaInput.value).trim();
if (!value) return;
addRosalindaMsg(value, "me");
rosalindaInput.value = "";
const reply = rosalindaBrain(value);
lastAIText = reply;
addRosalindaMsg(reply, "ai");
rosalindaSpeak(reply);
}
rosalindaSendBtn.onclick = () => handleRosalindaSend();
rosalindaInput.addEventListener("keydown", (e) => {
if (e.key === "Enter") handleRosalindaSend();
});
rosalindaSpeakBtn.onclick = () => lastAIText && rosalindaSpeak(lastAIText);
// Micro (STT)
let rosalindaRec = null;
let rosalindaListening = false;
function setupRosalindaSTT() {
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
if (!SpeechRecognition) return null;
const recognition = new SpeechRecognition();
recognition.lang = "fr-FR";
recognition.interimResults = true;
recognition.continuous = false;
return recognition;
}
rosalindaRec = setupRosalindaSTT();
rosalindaMicBtn.onclick = async () => {
if (!rosalindaRec) {
alert("Reconnaissance vocale non disponible ici. Essaie Chrome/Edge.");
return;
}
if (rosalindaListening) return;
rosalindaListening = true;
rosalindaStatus.textContent = "Micro: écoute…";
let finalText = "";
rosalindaRec.onresult = (e) => {
let transcript = "";
for (let i = e.resultIndex; i < e.results.length; i++) {
transcript += e.results[i][0].transcript;
if (e.results[i].isFinal) finalText += e.results[i][0].transcript + " ";
}
rosalindaInput.value = (finalText || transcript).trim();
};
rosalindaRec.onerror = () => {
rosalindaListening = false;
rosalindaStatus.textContent = "Micro: erreur";
};
rosalindaRec.onend = () => {
rosalindaListening = false;
rosalindaStatus.textContent = "Micro: prêt";
if (rosalindaInput.value.trim()) handleRosalindaSend(rosalindaInput.value);
};
try { rosalindaRec.start(); } catch (e) {
rosalindaListening = false;
rosalindaStatus.textContent = "Micro: prêt";
}
};
// Message de démarrage
addRosalindaMsg("Bonjour 👋 Je suis Rosalinda. Clique 🎤 pour parler ou écris-moi.", "ai");
</script>
<script src="components/navbar.js"></script>
<script src="script.js"></script>
</body>
</html>