Abmacode12's picture
import React, { useState } from 'react';
6feb262 verified
class CodeComponent extends HTMLElement {
constructor() {
super();
this.code = '';
this.description = '';
}
connectedCallback() {
this.attachShadow({ mode: 'open' });
this.render();
// Listen for code updates
document.addEventListener('show-code', (e) => {
this.code = e.detail.code;
this.description = e.detail.description;
this.render();
});
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
}
.code-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1.5rem;
}
.code-title {
font-size: 1.5rem;
font-weight: 600;
color: #111827;
}
.code-description {
color: #6b7280;
margin-bottom: 0.5rem;
}
.code-actions {
display: flex;
gap: 0.5rem;
}
.code-action {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
font-weight: 500;
transition: all 0.2s;
}
.code-action.primary {
background-color: #3b82f6;
color: white;
}
.code-action.primary:hover {
background-color: #2563eb;
}
.code-action.secondary {
background-color: #f3f4f6;
color: #4b5563;
}
.code-action.secondary:hover {
background-color: #e5e7eb;
}
.code-block {
position: relative;
background-color: #1e293b;
color: #f8fafc;
border-radius: 0.5rem;
overflow: hidden;
margin-bottom: 1.5rem;
}
.code-block pre {
padding: 1.5rem;
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;
}
.preview-container {
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
overflow: hidden;
margin-top: 1.5rem;
}
.preview-header {
background-color: #f3f4f6;
padding: 0.75rem 1rem;
border-bottom: 1px solid #e5e7eb;
display: flex;
align-items: center;
justify-content: space-between;
}
.preview-title {
font-weight: 500;
color: #111827;
}
.preview-actions {
display: flex;
gap: 0.5rem;
}
.preview-action {
padding: 0.25rem;
border-radius: 0.25rem;
color: #6b7280;
transition: all 0.2s;
}
.preview-action:hover {
background-color: #e5e7eb;
color: #111827;
}
.preview-content {
background-color: white;
min-height: 200px;
padding: 1rem;
}
.empty-state {
text-align: center;
padding: 3rem 0;
}
.empty-icon {
width: 3rem;
height: 3rem;
background-color: #f3f4f6;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 1rem;
color: #9ca3af;
}
.empty-title {
font-size: 1.125rem;
font-weight: 600;
color: #111827;
margin-bottom: 0.5rem;
}
.empty-description {
color: #6b7280;
max-width: 400px;
margin: 0 auto 1.5rem;
}
.empty-button {
background-color: #3b82f6;
color: white;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
font-weight: 500;
transition: background-color 0.2s;
}
.empty-button:hover {
background-color: #2563eb;
}
</style>
${this.code ? `
<div class="code-header">
<div>
<h2 class="code-title">Code Généré</h2>
<p class="code-description">${this.description}</p>
</div>
<div class="code-actions">
<button class="code-action primary" id="save-project">
<i data-feather="save"></i>
<span>Sauvegarder</span>
</button>
<button class="code-action secondary" id="new-chat">
<i data-feather="message-square"></i>
<span>Nouveau chat</span>
</button>
</div>
</div>
<div class="code-block">
<div class="code-toolbar">
<button class="copy-code" data-code="${escapeHtml(this.code)}">
<i data-feather="copy"></i>
<span>Copier</span>
</button>
<button class="download-code" data-code="${escapeHtml(this.code)}">
<i data-feather="download"></i>
<span>Télécharger</span>
</button>
</div>
<pre><code>${escapeHtml(this.code)}</code></pre>
</div>
<div class="preview-container">
<div class="preview-header">
<div class="preview-title">Aperçu</div>
<div class="preview-actions">
<button class="preview-action" title="Actualiser">
<i data-feather="refresh-cw"></i>
</button>
<button class="preview-action" title="Plein écran">
<i data-feather="maximize"></i>
</button>
</div>
</div>
<div class="preview-content">
<iframe srcdoc="${escapeHtml(this.code)}" frameborder="0" style="width: 100%; height: 400px;"></iframe>
</div>
</div>
` : `
<div class="empty-state">
<div class="empty-icon">
<i data-feather="code"></i>
</div>
<h3 class="empty-title">Aucun code généré</h3>
<p class="empty-description">Demandez à Rosalinda de générer du code pour voir le résultat ici.</p>
<button class="empty-button" id="go-to-chat">
<i data-feather="message-square"></i>
<span>Discuter avec Rosalinda</span>
</button>
</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();
};
// Add event listeners
if (this.code) {
// Copy code button
this.shadowRoot.querySelector('.copy-code').addEventListener('click', () => {
const code = this.shadowRoot.querySelector('.copy-code').getAttribute('data-code');
navigator.clipboard.writeText(code).then(() => {
const button = this.shadowRoot.querySelector('.copy-code');
const originalText = button.innerHTML;
button.innerHTML = '<i data-feather="check"></i> Copié !';
feather.replace();
setTimeout(() => {
button.innerHTML = originalText;
feather.replace();
}, 2000);
});
});
// Download code button
this.shadowRoot.querySelector('.download-code').addEventListener('click', () => {
const code = this.shadowRoot.querySelector('.download-code').getAttribute('data-code');
const element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(code));
element.setAttribute('download', 'code.html');
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
});
// Save to project button
this.shadowRoot.getElementById('save-project').addEventListener('click', () => {
document.dispatchEvent(new CustomEvent('save-project', {
detail: {
code: this.code,
description: this.description
}
}));
alert('Projet sauvegardé avec succès !');
});
// New chat button
this.shadowRoot.getElementById('new-chat').addEventListener('click', () => {
document.dispatchEvent(new CustomEvent('navigate', { detail: 'chat' }));
});
} else {
// Go to chat button
this.shadowRoot.getElementById('go-to-chat').addEventListener('click', () => {
document.dispatchEvent(new CustomEvent('navigate', { detail: 'chat' }));
});
}
}
}
// Helper function to escape HTML
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
customElements.define('code-component', CodeComponent);