Abmacode12's picture
import React, { useState } from 'react';
6feb262 verified
class ChatComponent extends HTMLElement {
constructor() {
super();
this.messages = [];
}
connectedCallback() {
this.attachShadow({ mode: 'open' });
this.render();
this.setupEventListeners();
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
height: 100%;
}
.chat-container {
display: flex;
flex-direction: column;
height: 100%;
max-width: 800px;
margin: 0 auto;
}
.chat-header {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1.5rem;
}
.chat-avatar {
width: 3rem;
height: 3rem;
border-radius: 50%;
background: linear-gradient(135deg, #8b5cf6, #ec4899);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
font-size: 1.25rem;
}
.chat-title {
font-size: 1.5rem;
font-weight: 600;
color: #111827;
}
.chat-subtitle {
font-size: 0.875rem;
color: #6b7280;
}
.messages-container {
flex: 1;
overflow-y: auto;
padding: 1rem;
margin-bottom: 1.5rem;
display: flex;
flex-direction: column;
gap: 1rem;
}
.message {
max-width: 80%;
padding: 1rem;
border-radius: 1rem;
font-size: 0.9375rem;
line-height: 1.5;
position: relative;
}
.message.user {
align-self: flex-end;
background-color: #3b82f6;
color: white;
border-bottom-right-radius: 0;
}
.message.assistant {
align-self: flex-start;
background-color: #f3f4f6;
color: #111827;
border-bottom-left-radius: 0;
}
.message-time {
font-size: 0.75rem;
opacity: 0.8;
margin-top: 0.25rem;
text-align: right;
}
.input-container {
display: flex;
gap: 0.5rem;
padding: 1rem;
background-color: white;
border-radius: 0.5rem;
border: 1px solid #e5e7eb;
}
.chat-input {
flex: 1;
padding: 0.75rem 1rem;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
font-size: 0.9375rem;
resize: none;
min-height: 3rem;
max-height: 10rem;
}
.chat-input:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 0 2px #bfdbfe;
}
.send-button {
padding: 0.75rem;
background-color: #3b82f6;
color: white;
border: none;
border-radius: 0.5rem;
cursor: pointer;
transition: background-color 0.2s;
}
.send-button:hover {
background-color: #2563eb;
}
.send-button:disabled {
background-color: #9ca3af;
cursor: not-allowed;
}
.typing-indicator {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 1rem;
background-color: #f3f4f6;
border-radius: 0.5rem;
margin-bottom: 1rem;
align-self: flex-start;
}
.typing-dots {
display: flex;
gap: 0.25rem;
}
.typing-dot {
width: 0.5rem;
height: 0.5rem;
background-color: #6b7280;
border-radius: 50%;
animation: typingAnimation 1.4s infinite ease-in-out;
}
.typing-dot:nth-child(1) {
animation-delay: 0s;
}
.typing-dot:nth-child(2) {
animation-delay: 0.2s;
}
.typing-dot:nth-child(3) {
animation-delay: 0.4s;
}
@keyframes typingAnimation {
0%, 60%, 100% { transform: translateY(0); }
30% { transform: translateY(-0.25rem); }
}
.code-block {
position: relative;
background-color: #1e293b;
color: #f8fafc;
border-radius: 0.5rem;
overflow: hidden;
margin-top: 0.5rem;
}
.code-block pre {
padding: 1rem;
overflow-x: auto;
font-family: 'Courier New', Courier, monospace;
font-size: 0.875rem;
margin: 0;
}
.code-toolbar {
position: absolute;
top: 0.5rem;
right: 0.5rem;
display: flex;
gap: 0.5rem;
}
.code-toolbar button {
background-color: #334155;
color: white;
border: none;
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
cursor: pointer;
font-size: 0.75rem;
display: flex;
align-items: center;
gap: 0.25rem;
}
.code-toolbar button:hover {
background-color: #475569;
}
</style>
<div class="chat-container">
<div class="chat-header">
<div class="chat-avatar">R</div>
<div>
<h2 class="chat-title">Rosalinda</h2>
<p class="chat-subtitle">IA spécialisée en développement web</p>
</div>
</div>
<div class="messages-container" id="messages-container">
<!-- Messages will be added here dynamically -->
</div>
<div class="input-container">
<textarea class="chat-input" id="chat-input" placeholder="Demandez à Rosalinda de générer du code ou posez-lui une question..." rows="1"></textarea>
<button class="send-button" id="send-button">
<i data-feather="send"></i>
</button>
</div>
</div>
`;
// Initialize feather icons
const featherScript = document.createElement('script');
featherScript.src = 'https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js';
this.shadowRoot.appendChild(featherScript);
featherScript.onload = () => {
feather.replace();
};
}
setupEventListeners() {
const chatInput = this.shadowRoot.getElementById('chat-input');
const sendButton = this.shadowRoot.getElementById('send-button');
const messagesContainer = this.shadowRoot.getElementById('messages-container');
// Auto-resize textarea
chatInput.addEventListener('input', function() {
this.style.height = 'auto';
this.style.height = (this.scrollHeight) + 'px';
});
// Send message on Enter (but allow Shift+Enter for new lines)
chatInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
this.sendMessage();
}
});
// Send message on button click
sendButton.addEventListener('click', () => this.sendMessage());
// Initial greeting from Rosalinda
this.addMessage({
user: 'Rosalinda',
type: 'assistant',
text: 'Bonjour ! Je suis Rosalinda, votre assistante IA pour le développement web. Comment puis-je vous aider aujourd\'hui ? Je peux générer du code HTML, CSS, JavaScript ou React pour vous.',
time: new Date().toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' })
});
}
addMessage(message) {
this.messages.push(message);
this.renderMessages();
// Scroll to bottom
const messagesContainer = this.shadowRoot.getElementById('messages-container');
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
renderMessages() {
const messagesContainer = this.shadowRoot.getElementById('messages-container');
messagesContainer.innerHTML = '';
this.messages.forEach(msg => {
const messageDiv = document.createElement('div');
messageDiv.className = `message ${msg.type}`;
// Check if message contains code
let messageText = msg.text;
const codeMatch = msg.text.match(/