- Complete SPA architecture with dynamic module loading - 9 different educational games (whack-a-mole, memory, quiz, etc.) - Rich content system supporting multimedia (audio, images, video) - Chinese study mode with character recognition - Adaptive game system based on available content - Content types: vocabulary, grammar, poems, fill-blanks, corrections - AI-powered text evaluation for open-ended answers - Flexible content schema with backward compatibility 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
919 lines
28 KiB
JavaScript
919 lines
28 KiB
JavaScript
// === INTERFACE CRÉATEUR DE CONTENU ===
|
||
|
||
class ContentCreator {
|
||
constructor() {
|
||
this.factory = new ContentFactory();
|
||
this.previewContainer = null;
|
||
this.currentContent = null;
|
||
}
|
||
|
||
init() {
|
||
this.createInterface();
|
||
this.setupEventListeners();
|
||
this.loadExamples();
|
||
}
|
||
|
||
createInterface() {
|
||
// Créer l'interface dans le container principal
|
||
const existingInterface = document.getElementById('content-creator');
|
||
if (existingInterface) {
|
||
existingInterface.remove();
|
||
}
|
||
|
||
const interface = document.createElement('div');
|
||
interface.id = 'content-creator';
|
||
interface.className = 'content-creator-interface';
|
||
|
||
interface.innerHTML = `
|
||
<div class="creator-header">
|
||
<h2>🏭 Créateur de Contenu Universel</h2>
|
||
<p>Transformez n'importe quel contenu en exercices interactifs</p>
|
||
</div>
|
||
|
||
<div class="creator-tabs">
|
||
<button class="tab-btn active" data-tab="text">📝 Texte Libre</button>
|
||
<button class="tab-btn" data-tab="vocabulary">📚 Vocabulaire</button>
|
||
<button class="tab-btn" data-tab="dialogue">💬 Dialogue</button>
|
||
<button class="tab-btn" data-tab="sequence">📋 Séquence</button>
|
||
</div>
|
||
|
||
<div class="creator-content">
|
||
<!-- TAB: Texte Libre -->
|
||
<div class="tab-content active" id="text-tab">
|
||
<h3>Collez votre texte ici</h3>
|
||
<textarea id="text-input" placeholder="Exemple:
|
||
cat = chat
|
||
dog = chien
|
||
bird = oiseau
|
||
|
||
ou
|
||
|
||
1. Wake up at 7am
|
||
2. Brush teeth
|
||
3. Eat breakfast
|
||
4. Go to school
|
||
|
||
ou
|
||
|
||
Alice: Hello! What's your name?
|
||
Bob: Hi! I'm Bob. Nice to meet you!"></textarea>
|
||
|
||
<div class="input-options">
|
||
<label>
|
||
<input type="checkbox" id="auto-detect"> Détection automatique du type
|
||
</label>
|
||
<select id="content-type-select">
|
||
<option value="auto">Auto</option>
|
||
<option value="vocabulary">Vocabulaire</option>
|
||
<option value="dialogue">Dialogue</option>
|
||
<option value="sequence">Séquence</option>
|
||
<option value="sentence">Phrases</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TAB: Vocabulaire -->
|
||
<div class="tab-content" id="vocabulary-tab">
|
||
<h3>Liste de Vocabulaire</h3>
|
||
<div class="vocab-builder">
|
||
<div class="vocab-entry">
|
||
<input type="text" placeholder="Anglais" class="english-input">
|
||
<span>=</span>
|
||
<input type="text" placeholder="Français" class="french-input">
|
||
<input type="text" placeholder="Catégorie" class="category-input">
|
||
<button class="remove-entry">×</button>
|
||
</div>
|
||
</div>
|
||
<button id="add-vocab-entry">+ Ajouter un mot</button>
|
||
</div>
|
||
|
||
<!-- TAB: Dialogue -->
|
||
<div class="tab-content" id="dialogue-tab">
|
||
<h3>Créateur de Dialogue</h3>
|
||
<input type="text" id="dialogue-scenario" placeholder="Scénario (ex: Au restaurant)">
|
||
<div class="dialogue-builder">
|
||
<div class="dialogue-line">
|
||
<input type="text" placeholder="Personnage" class="speaker-input">
|
||
<textarea placeholder="Réplique en anglais" class="line-input"></textarea>
|
||
<button class="remove-line">×</button>
|
||
</div>
|
||
</div>
|
||
<button id="add-dialogue-line">+ Ajouter une réplique</button>
|
||
</div>
|
||
|
||
<!-- TAB: Séquence -->
|
||
<div class="tab-content" id="sequence-tab">
|
||
<h3>Créateur de Séquence</h3>
|
||
<input type="text" id="sequence-title" placeholder="Titre de la séquence">
|
||
<div class="sequence-builder">
|
||
<div class="sequence-step">
|
||
<span class="step-number">1</span>
|
||
<input type="text" placeholder="Étape en anglais" class="step-input">
|
||
<input type="time" class="time-input" title="Heure (optionnel)">
|
||
<button class="remove-step">×</button>
|
||
</div>
|
||
</div>
|
||
<button id="add-sequence-step">+ Ajouter une étape</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="creator-actions">
|
||
<div class="generation-options">
|
||
<label>Nom du module:
|
||
<input type="text" id="module-name" placeholder="Mon Contenu Personnalisé">
|
||
</label>
|
||
<label>Difficulté:
|
||
<select id="difficulty-select">
|
||
<option value="auto">Automatique</option>
|
||
<option value="easy">Facile</option>
|
||
<option value="medium">Moyen</option>
|
||
<option value="hard">Difficile</option>
|
||
</select>
|
||
</label>
|
||
</div>
|
||
|
||
<div class="action-buttons">
|
||
<button id="preview-btn" class="btn secondary">👁️ Aperçu</button>
|
||
<button id="generate-btn" class="btn primary">🚀 Générer Module</button>
|
||
<button id="test-game-btn" class="btn success" style="display:none;">🎮 Tester dans un Jeu</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="creator-examples">
|
||
<h4>💡 Exemples Rapides</h4>
|
||
<div class="example-buttons">
|
||
<button class="example-btn" data-example="vocabulary">Vocabulaire Animaux</button>
|
||
<button class="example-btn" data-example="dialogue">Dialogue Restaurant</button>
|
||
<button class="example-btn" data-example="sequence">Routine Matinale</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="creator-preview" id="content-preview" style="display:none;">
|
||
<h4>📋 Aperçu du Contenu Généré</h4>
|
||
<div class="preview-content"></div>
|
||
</div>
|
||
`;
|
||
|
||
// Injecter dans la page
|
||
const container = document.getElementById('game-container') || document.body;
|
||
container.appendChild(interface);
|
||
|
||
this.previewContainer = interface.querySelector('#content-preview .preview-content');
|
||
}
|
||
|
||
setupEventListeners() {
|
||
// Gestion des onglets
|
||
document.querySelectorAll('.tab-btn').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
this.switchTab(btn.dataset.tab);
|
||
});
|
||
});
|
||
|
||
// Bouton générer
|
||
document.getElementById('generate-btn').addEventListener('click', () => {
|
||
this.generateContent();
|
||
});
|
||
|
||
// Bouton aperçu
|
||
document.getElementById('preview-btn').addEventListener('click', () => {
|
||
this.previewContent();
|
||
});
|
||
|
||
// Bouton test
|
||
document.getElementById('test-game-btn').addEventListener('click', () => {
|
||
this.testInGame();
|
||
});
|
||
|
||
// Exemples
|
||
document.querySelectorAll('.example-btn').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
this.loadExample(btn.dataset.example);
|
||
});
|
||
});
|
||
|
||
// Builders dynamiques
|
||
this.setupVocabularyBuilder();
|
||
this.setupDialogueBuilder();
|
||
this.setupSequenceBuilder();
|
||
}
|
||
|
||
switchTab(tabName) {
|
||
// Désactiver tous les onglets et contenu
|
||
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
|
||
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
|
||
|
||
// Activer le bon onglet
|
||
document.querySelector(`[data-tab="${tabName}"]`).classList.add('active');
|
||
document.getElementById(`${tabName}-tab`).classList.add('active');
|
||
}
|
||
|
||
setupVocabularyBuilder() {
|
||
document.getElementById('add-vocab-entry').addEventListener('click', () => {
|
||
this.addVocabularyEntry();
|
||
});
|
||
|
||
// Supprimer entries
|
||
document.addEventListener('click', (e) => {
|
||
if (e.target.classList.contains('remove-entry')) {
|
||
e.target.parentElement.remove();
|
||
}
|
||
});
|
||
}
|
||
|
||
addVocabularyEntry() {
|
||
const builder = document.querySelector('.vocab-builder');
|
||
const entry = document.createElement('div');
|
||
entry.className = 'vocab-entry';
|
||
entry.innerHTML = `
|
||
<input type="text" placeholder="Anglais" class="english-input">
|
||
<span>=</span>
|
||
<input type="text" placeholder="Français" class="french-input">
|
||
<input type="text" placeholder="Catégorie" class="category-input">
|
||
<button class="remove-entry">×</button>
|
||
`;
|
||
builder.appendChild(entry);
|
||
}
|
||
|
||
setupDialogueBuilder() {
|
||
document.getElementById('add-dialogue-line').addEventListener('click', () => {
|
||
this.addDialogueLine();
|
||
});
|
||
|
||
document.addEventListener('click', (e) => {
|
||
if (e.target.classList.contains('remove-line')) {
|
||
e.target.parentElement.remove();
|
||
}
|
||
});
|
||
}
|
||
|
||
addDialogueLine() {
|
||
const builder = document.querySelector('.dialogue-builder');
|
||
const line = document.createElement('div');
|
||
line.className = 'dialogue-line';
|
||
line.innerHTML = `
|
||
<input type="text" placeholder="Personnage" class="speaker-input">
|
||
<textarea placeholder="Réplique en anglais" class="line-input"></textarea>
|
||
<button class="remove-line">×</button>
|
||
`;
|
||
builder.appendChild(line);
|
||
}
|
||
|
||
setupSequenceBuilder() {
|
||
document.getElementById('add-sequence-step').addEventListener('click', () => {
|
||
this.addSequenceStep();
|
||
});
|
||
|
||
document.addEventListener('click', (e) => {
|
||
if (e.target.classList.contains('remove-step')) {
|
||
e.target.parentElement.remove();
|
||
this.updateStepNumbers();
|
||
}
|
||
});
|
||
}
|
||
|
||
addSequenceStep() {
|
||
const builder = document.querySelector('.sequence-builder');
|
||
const stepCount = builder.children.length + 1;
|
||
const step = document.createElement('div');
|
||
step.className = 'sequence-step';
|
||
step.innerHTML = `
|
||
<span class="step-number">${stepCount}</span>
|
||
<input type="text" placeholder="Étape en anglais" class="step-input">
|
||
<input type="time" class="time-input" title="Heure (optionnel)">
|
||
<button class="remove-step">×</button>
|
||
`;
|
||
builder.appendChild(step);
|
||
}
|
||
|
||
updateStepNumbers() {
|
||
document.querySelectorAll('.step-number').forEach((num, index) => {
|
||
num.textContent = index + 1;
|
||
});
|
||
}
|
||
|
||
async generateContent() {
|
||
try {
|
||
const input = this.collectInput();
|
||
const options = this.collectOptions();
|
||
|
||
console.log('🏭 Génération de contenu...', { input, options });
|
||
|
||
const content = await this.factory.createContent(input, options);
|
||
this.currentContent = content;
|
||
|
||
this.showSuccess('Contenu généré avec succès !');
|
||
this.displayPreview(content);
|
||
|
||
document.getElementById('test-game-btn').style.display = 'inline-block';
|
||
|
||
} catch (error) {
|
||
console.error('Erreur génération:', error);
|
||
this.showError('Erreur lors de la génération: ' + error.message);
|
||
}
|
||
}
|
||
|
||
collectInput() {
|
||
const activeTab = document.querySelector('.tab-content.active').id;
|
||
|
||
switch (activeTab) {
|
||
case 'text-tab':
|
||
return document.getElementById('text-input').value;
|
||
|
||
case 'vocabulary-tab':
|
||
return this.collectVocabularyData();
|
||
|
||
case 'dialogue-tab':
|
||
return this.collectDialogueData();
|
||
|
||
case 'sequence-tab':
|
||
return this.collectSequenceData();
|
||
|
||
default:
|
||
throw new Error('Type de contenu non supporté');
|
||
}
|
||
}
|
||
|
||
collectVocabularyData() {
|
||
const entries = document.querySelectorAll('.vocab-entry');
|
||
const vocabulary = [];
|
||
|
||
entries.forEach(entry => {
|
||
const english = entry.querySelector('.english-input').value;
|
||
const french = entry.querySelector('.french-input').value;
|
||
const category = entry.querySelector('.category-input').value || 'general';
|
||
|
||
if (english && french) {
|
||
vocabulary.push({ english, french, category });
|
||
}
|
||
});
|
||
|
||
return { vocabulary };
|
||
}
|
||
|
||
collectDialogueData() {
|
||
const scenario = document.getElementById('dialogue-scenario').value || 'conversation';
|
||
const lines = document.querySelectorAll('.dialogue-line');
|
||
const conversation = [];
|
||
|
||
lines.forEach(line => {
|
||
const speaker = line.querySelector('.speaker-input').value;
|
||
const text = line.querySelector('.line-input').value;
|
||
|
||
if (speaker && text) {
|
||
conversation.push({ speaker, english: text });
|
||
}
|
||
});
|
||
|
||
return {
|
||
dialogue: {
|
||
scenario,
|
||
conversation
|
||
}
|
||
};
|
||
}
|
||
|
||
collectSequenceData() {
|
||
const title = document.getElementById('sequence-title').value || 'Sequence';
|
||
const steps = document.querySelectorAll('.sequence-step');
|
||
const sequence = [];
|
||
|
||
steps.forEach((step, index) => {
|
||
const english = step.querySelector('.step-input').value;
|
||
const time = step.querySelector('.time-input').value;
|
||
|
||
if (english) {
|
||
sequence.push({
|
||
order: index + 1,
|
||
english,
|
||
time: time || null
|
||
});
|
||
}
|
||
});
|
||
|
||
return {
|
||
sequence: {
|
||
title,
|
||
steps: sequence
|
||
}
|
||
};
|
||
}
|
||
|
||
collectOptions() {
|
||
return {
|
||
name: document.getElementById('module-name').value || 'Contenu Généré',
|
||
difficulty: document.getElementById('difficulty-select').value === 'auto' ? null : document.getElementById('difficulty-select').value,
|
||
contentType: document.getElementById('content-type-select').value === 'auto' ? null : document.getElementById('content-type-select').value
|
||
};
|
||
}
|
||
|
||
async previewContent() {
|
||
try {
|
||
const input = this.collectInput();
|
||
const options = this.collectOptions();
|
||
|
||
// Génération rapide pour aperçu
|
||
const content = await this.factory.createContent(input, options);
|
||
this.displayPreview(content);
|
||
|
||
document.getElementById('content-preview').style.display = 'block';
|
||
|
||
} catch (error) {
|
||
this.showError('Erreur lors de l\'aperçu: ' + error.message);
|
||
}
|
||
}
|
||
|
||
displayPreview(content) {
|
||
if (!this.previewContainer) return;
|
||
|
||
this.previewContainer.innerHTML = `
|
||
<div class="preview-summary">
|
||
<h5>${content.name}</h5>
|
||
<p>${content.description}</p>
|
||
<div class="preview-stats">
|
||
<span class="stat">📊 ${content.contentItems.length} exercices</span>
|
||
<span class="stat">🎯 Difficulté: ${content.difficulty}</span>
|
||
<span class="stat">🏷️ Types: ${content.metadata.contentTypes.join(', ')}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="preview-items">
|
||
${content.contentItems.slice(0, 3).map(item => `
|
||
<div class="preview-item">
|
||
<span class="item-type">${item.type}</span>
|
||
<span class="item-content">${item.content.english} = ${item.content.french}</span>
|
||
<span class="item-interaction">${item.interaction.type}</span>
|
||
</div>
|
||
`).join('')}
|
||
${content.contentItems.length > 3 ? `<div class="preview-more">... et ${content.contentItems.length - 3} autres</div>` : ''}
|
||
</div>
|
||
`;
|
||
|
||
document.getElementById('content-preview').style.display = 'block';
|
||
}
|
||
|
||
async testInGame() {
|
||
if (!this.currentContent) {
|
||
this.showError('Aucun contenu généré à tester');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
// Sauvegarder temporairement le contenu
|
||
const contentId = 'generated_test';
|
||
window.ContentModules = window.ContentModules || {};
|
||
window.ContentModules.GeneratedTest = this.currentContent;
|
||
|
||
// Naviguer vers un jeu pour tester
|
||
this.showSuccess('Contenu prêt ! Redirection vers le jeu...');
|
||
|
||
setTimeout(() => {
|
||
// Fermer l'interface
|
||
document.getElementById('content-creator').remove();
|
||
|
||
// Lancer le jeu avec le contenu généré
|
||
AppNavigation.navigateTo('play', 'whack-a-mole', 'generated-test');
|
||
}, 1500);
|
||
|
||
} catch (error) {
|
||
this.showError('Erreur lors du test: ' + error.message);
|
||
}
|
||
}
|
||
|
||
loadExamples() {
|
||
// Les exemples sont gérés par les boutons
|
||
}
|
||
|
||
loadExample(type) {
|
||
switch (type) {
|
||
case 'vocabulary':
|
||
this.switchTab('vocabulary');
|
||
setTimeout(() => {
|
||
// Effacer contenu existant
|
||
document.querySelector('.vocab-builder').innerHTML = '';
|
||
|
||
// Ajouter exemples
|
||
const animals = [
|
||
{ english: 'cat', french: 'chat', category: 'animals' },
|
||
{ english: 'dog', french: 'chien', category: 'animals' },
|
||
{ english: 'bird', french: 'oiseau', category: 'animals' },
|
||
{ english: 'fish', french: 'poisson', category: 'animals' }
|
||
];
|
||
|
||
animals.forEach(animal => {
|
||
this.addVocabularyEntry();
|
||
const entries = document.querySelectorAll('.vocab-entry');
|
||
const lastEntry = entries[entries.length - 1];
|
||
lastEntry.querySelector('.english-input').value = animal.english;
|
||
lastEntry.querySelector('.french-input').value = animal.french;
|
||
lastEntry.querySelector('.category-input').value = animal.category;
|
||
});
|
||
|
||
document.getElementById('module-name').value = 'Animaux Domestiques';
|
||
}, 100);
|
||
break;
|
||
|
||
case 'dialogue':
|
||
this.switchTab('dialogue');
|
||
setTimeout(() => {
|
||
document.getElementById('dialogue-scenario').value = 'Au Restaurant';
|
||
document.querySelector('.dialogue-builder').innerHTML = '';
|
||
|
||
const dialogueLines = [
|
||
{ speaker: 'Serveur', text: 'What would you like to order?' },
|
||
{ speaker: 'Client', text: 'I would like a pizza, please.' },
|
||
{ speaker: 'Serveur', text: 'What size?' },
|
||
{ speaker: 'Client', text: 'Large, please.' }
|
||
];
|
||
|
||
dialogueLines.forEach(line => {
|
||
this.addDialogueLine();
|
||
const lines = document.querySelectorAll('.dialogue-line');
|
||
const lastLine = lines[lines.length - 1];
|
||
lastLine.querySelector('.speaker-input').value = line.speaker;
|
||
lastLine.querySelector('.line-input').value = line.text;
|
||
});
|
||
|
||
document.getElementById('module-name').value = 'Dialogue Restaurant';
|
||
}, 100);
|
||
break;
|
||
|
||
case 'sequence':
|
||
this.switchTab('sequence');
|
||
setTimeout(() => {
|
||
document.getElementById('sequence-title').value = 'Morning Routine';
|
||
document.querySelector('.sequence-builder').innerHTML = '';
|
||
|
||
const steps = [
|
||
{ text: 'Wake up', time: '07:00' },
|
||
{ text: 'Brush teeth', time: '07:15' },
|
||
{ text: 'Get dressed', time: '07:30' },
|
||
{ text: 'Eat breakfast', time: '07:45' },
|
||
{ text: 'Go to school', time: '08:00' }
|
||
];
|
||
|
||
steps.forEach(step => {
|
||
this.addSequenceStep();
|
||
const stepElements = document.querySelectorAll('.sequence-step');
|
||
const lastStep = stepElements[stepElements.length - 1];
|
||
lastStep.querySelector('.step-input').value = step.text;
|
||
lastStep.querySelector('.time-input').value = step.time;
|
||
});
|
||
|
||
document.getElementById('module-name').value = 'Routine du Matin';
|
||
}, 100);
|
||
break;
|
||
}
|
||
}
|
||
|
||
showSuccess(message) {
|
||
Utils.showToast(message, 'success');
|
||
}
|
||
|
||
showError(message) {
|
||
Utils.showToast(message, 'error');
|
||
}
|
||
}
|
||
|
||
// CSS pour l'interface
|
||
const contentCreatorStyles = `
|
||
<style>
|
||
.content-creator-interface {
|
||
background: white;
|
||
border-radius: 12px;
|
||
padding: 30px;
|
||
box-shadow: 0 8px 25px rgba(0,0,0,0.1);
|
||
margin: 20px auto;
|
||
max-width: 900px;
|
||
}
|
||
|
||
.creator-header {
|
||
text-align: center;
|
||
margin-bottom: 30px;
|
||
}
|
||
|
||
.creator-header h2 {
|
||
color: var(--primary-color);
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.creator-tabs {
|
||
display: flex;
|
||
gap: 5px;
|
||
margin-bottom: 30px;
|
||
border-bottom: 2px solid #e5e7eb;
|
||
}
|
||
|
||
.tab-btn {
|
||
background: transparent;
|
||
border: none;
|
||
padding: 12px 20px;
|
||
border-radius: 8px 8px 0 0;
|
||
cursor: pointer;
|
||
font-weight: 500;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.tab-btn:hover {
|
||
background: #f3f4f6;
|
||
}
|
||
|
||
.tab-btn.active {
|
||
background: var(--primary-color);
|
||
color: white;
|
||
}
|
||
|
||
.tab-content {
|
||
display: none;
|
||
}
|
||
|
||
.tab-content.active {
|
||
display: block;
|
||
}
|
||
|
||
#text-input {
|
||
width: 100%;
|
||
min-height: 200px;
|
||
padding: 15px;
|
||
border: 2px solid #e5e7eb;
|
||
border-radius: 8px;
|
||
font-family: monospace;
|
||
resize: vertical;
|
||
}
|
||
|
||
.input-options {
|
||
display: flex;
|
||
gap: 20px;
|
||
align-items: center;
|
||
margin-top: 15px;
|
||
}
|
||
|
||
.vocab-builder, .dialogue-builder, .sequence-builder {
|
||
margin: 20px 0;
|
||
}
|
||
|
||
.vocab-entry, .dialogue-line, .sequence-step {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
margin-bottom: 15px;
|
||
padding: 15px;
|
||
background: #f8f9fa;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.vocab-entry input, .dialogue-line input, .sequence-step input {
|
||
flex: 1;
|
||
padding: 8px 12px;
|
||
border: 1px solid #ddd;
|
||
border-radius: 6px;
|
||
}
|
||
|
||
.dialogue-line textarea {
|
||
flex: 2;
|
||
padding: 8px 12px;
|
||
border: 1px solid #ddd;
|
||
border-radius: 6px;
|
||
resize: vertical;
|
||
min-height: 40px;
|
||
}
|
||
|
||
.step-number {
|
||
background: var(--primary-color);
|
||
color: white;
|
||
width: 30px;
|
||
height: 30px;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-weight: bold;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.remove-entry, .remove-line, .remove-step {
|
||
background: var(--error-color);
|
||
color: white;
|
||
border: none;
|
||
width: 30px;
|
||
height: 30px;
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
font-size: 18px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.creator-actions {
|
||
margin-top: 30px;
|
||
padding-top: 30px;
|
||
border-top: 2px solid #e5e7eb;
|
||
}
|
||
|
||
.generation-options {
|
||
display: flex;
|
||
gap: 20px;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.generation-options label {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 5px;
|
||
}
|
||
|
||
.generation-options input, .generation-options select {
|
||
padding: 8px 12px;
|
||
border: 1px solid #ddd;
|
||
border-radius: 6px;
|
||
min-width: 200px;
|
||
}
|
||
|
||
.action-buttons {
|
||
display: flex;
|
||
gap: 15px;
|
||
justify-content: center;
|
||
}
|
||
|
||
.btn {
|
||
padding: 12px 25px;
|
||
border: none;
|
||
border-radius: 25px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.btn.primary {
|
||
background: var(--primary-color);
|
||
color: white;
|
||
}
|
||
|
||
.btn.secondary {
|
||
background: var(--neutral-color);
|
||
color: white;
|
||
}
|
||
|
||
.btn.success {
|
||
background: var(--secondary-color);
|
||
color: white;
|
||
}
|
||
|
||
.btn:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||
}
|
||
|
||
.creator-examples {
|
||
margin-top: 25px;
|
||
padding: 20px;
|
||
background: #f8f9fa;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.example-buttons {
|
||
display: flex;
|
||
gap: 10px;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.example-btn {
|
||
background: white;
|
||
border: 2px solid var(--primary-color);
|
||
color: var(--primary-color);
|
||
padding: 8px 16px;
|
||
border-radius: 20px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.example-btn:hover {
|
||
background: var(--primary-color);
|
||
color: white;
|
||
}
|
||
|
||
.creator-preview {
|
||
margin-top: 25px;
|
||
padding: 20px;
|
||
background: #f0f9ff;
|
||
border-radius: 8px;
|
||
border-left: 4px solid var(--primary-color);
|
||
}
|
||
|
||
.preview-summary h5 {
|
||
color: var(--primary-color);
|
||
margin-bottom: 8px;
|
||
font-size: 1.2rem;
|
||
}
|
||
|
||
.preview-stats {
|
||
display: flex;
|
||
gap: 20px;
|
||
margin: 15px 0;
|
||
}
|
||
|
||
.stat {
|
||
background: white;
|
||
padding: 5px 10px;
|
||
border-radius: 15px;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.preview-items {
|
||
margin-top: 15px;
|
||
}
|
||
|
||
.preview-item {
|
||
display: flex;
|
||
gap: 15px;
|
||
padding: 8px 12px;
|
||
background: white;
|
||
border-radius: 6px;
|
||
margin-bottom: 8px;
|
||
align-items: center;
|
||
}
|
||
|
||
.item-type {
|
||
background: var(--accent-color);
|
||
color: white;
|
||
padding: 2px 8px;
|
||
border-radius: 12px;
|
||
font-size: 12px;
|
||
font-weight: bold;
|
||
min-width: 70px;
|
||
text-align: center;
|
||
}
|
||
|
||
.item-content {
|
||
flex: 1;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.item-interaction {
|
||
background: var(--secondary-color);
|
||
color: white;
|
||
padding: 2px 8px;
|
||
border-radius: 12px;
|
||
font-size: 12px;
|
||
min-width: 80px;
|
||
text-align: center;
|
||
}
|
||
|
||
.preview-more {
|
||
text-align: center;
|
||
color: var(--text-secondary);
|
||
font-style: italic;
|
||
margin-top: 10px;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.content-creator-interface {
|
||
margin: 10px;
|
||
padding: 20px;
|
||
}
|
||
|
||
.creator-tabs {
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.tab-btn {
|
||
padding: 10px 15px;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.generation-options {
|
||
flex-direction: column;
|
||
gap: 10px;
|
||
}
|
||
|
||
.action-buttons {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.vocab-entry, .dialogue-line, .sequence-step {
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
}
|
||
|
||
.preview-stats {
|
||
flex-direction: column;
|
||
gap: 10px;
|
||
}
|
||
|
||
.preview-item {
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
gap: 8px;
|
||
}
|
||
}
|
||
</style>
|
||
`;
|
||
|
||
// Ajouter les styles
|
||
document.head.insertAdjacentHTML('beforeend', contentCreatorStyles);
|
||
|
||
// Export global
|
||
window.ContentCreator = ContentCreator; |