criador-de-cursos2 / index.html
zoeboy's picture
Add 2 files
47bbaaa verified
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gerador de Cursos Inteligente</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.dropzone {
border: 2px dashed #cbd5e0;
transition: all 0.3s;
}
.dropzone.active {
border-color: #4f46e5;
background-color: #eef2ff;
}
.module-card {
transition: all 0.2s;
}
.module-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
.flip-card {
perspective: 1000px;
}
.flip-card-inner {
transition: transform 0.6s;
transform-style: preserve-3d;
}
.flip-card.flipped .flip-card-inner {
transform: rotateY(180deg);
}
.flip-card-front, .flip-card-back {
backface-visibility: hidden;
}
.flip-card-back {
transform: rotateY(180deg);
}
.fade-in {
animation: fadeIn 0.5s;
}
.progress-bar {
height: 6px;
border-radius: 3px;
transition: width 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8">
<!-- Header -->
<header class="mb-10 text-center">
<h1 class="text-4xl font-bold text-indigo-700 mb-2">Gerador de Cursos Inteligente</h1>
<p class="text-gray-600 max-w-2xl mx-auto">Transforme seus materiais em cursos interativos com módulos, quizzes e flashcards em minutos!</p>
</header>
<!-- Main Content -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Left Panel - Course Creation -->
<div class="lg:col-span-2 space-y-8">
<!-- Course Info Section -->
<div class="bg-white rounded-xl shadow-md p-6">
<h2 class="text-xl font-semibold text-gray-800 mb-4">Informações do Curso</h2>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Título do Curso</label>
<input type="text" id="courseTitle" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="Ex: Introdução à Programação">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Descrição</label>
<textarea id="courseDescription" rows="3" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="Descreva o objetivo do curso..."></textarea>
</div>
</div>
</div>
<!-- Content Input Section -->
<div class="bg-white rounded-xl shadow-md p-6">
<h2 class="text-xl font-semibold text-gray-800 mb-4">Adicionar Conteúdo</h2>
<div class="flex space-x-2 mb-4">
<button id="textTab" class="px-4 py-2 bg-indigo-600 text-white rounded-lg font-medium active-tab">Texto</button>
<button id="pdfTab" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg font-medium">PDF</button>
<button id="txtTab" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg font-medium">TXT</button>
</div>
<!-- Text Input -->
<div id="textInput" class="content-section">
<textarea id="contentText" rows="8" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="Cole seu texto aqui ou comece a digitar..."></textarea>
<div class="mt-4 flex justify-end">
<button id="analyzeText" class="px-6 py-2 bg-indigo-600 text-white rounded-lg font-medium hover:bg-indigo-700 transition flex items-center">
<i class="fas fa-magic mr-2"></i> Gerar Módulos
</button>
</div>
</div>
<!-- File Upload -->
<div id="fileInput" class="content-section hidden">
<div id="dropzone" class="dropzone rounded-xl p-8 text-center cursor-pointer">
<i class="fas fa-cloud-upload-alt text-4xl text-indigo-500 mb-3"></i>
<p class="text-gray-600 mb-2">Arraste e solte seus arquivos aqui</p>
<p class="text-sm text-gray-500 mb-4">ou</p>
<label for="fileUpload" class="px-4 py-2 bg-indigo-600 text-white rounded-lg font-medium hover:bg-indigo-700 transition cursor-pointer">
Selecione os Arquivos
</label>
<input type="file" id="fileUpload" class="hidden" accept=".pdf,.txt">
</div>
<div id="filePreview" class="mt-4 hidden">
<div class="flex items-center p-3 bg-gray-100 rounded-lg">
<i class="fas fa-file-alt text-indigo-500 mr-3 text-xl"></i>
<div class="flex-1">
<p id="fileName" class="font-medium"></p>
<p id="fileSize" class="text-sm text-gray-500"></p>
</div>
<button id="removeFile" class="text-red-500 hover:text-red-700">
<i class="fas fa-times"></i>
</button>
</div>
<!-- Progress Bar -->
<div id="uploadProgress" class="hidden mt-3">
<div class="flex justify-between text-sm text-gray-600 mb-1">
<span>Upload em progresso...</span>
<span id="progressPercent">0%</span>
</div>
<div class="w-full bg-gray-200 rounded-full">
<div id="progressBar" class="progress-bar bg-indigo-600" style="width: 0%"></div>
</div>
</div>
<div class="mt-4 flex justify-end">
<button id="analyzeFile" class="px-6 py-2 bg-indigo-600 text-white rounded-lg font-medium hover:bg-indigo-700 transition flex items-center">
<i class="fas fa-magic mr-2"></i> Processar Arquivo
</button>
</div>
</div>
</div>
</div>
<!-- Generated Modules -->
<div id="modulesSection" class="hidden">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold text-gray-800">Módulos Gerados</h2>
<button id="addModule" class="px-4 py-2 bg-green-600 text-white rounded-lg font-medium hover:bg-green-700 transition flex items-center">
<i class="fas fa-plus mr-2"></i> Adicionar Módulo
</button>
</div>
<div id="modulesContainer" class="space-y-4">
<!-- Modules will be added here dynamically -->
</div>
</div>
</div>
<!-- Right Panel - Preview -->
<div class="lg:col-span-1">
<div class="bg-white rounded-xl shadow-md p-6 sticky top-6">
<h2 class="text-xl font-semibold text-gray-800 mb-4">Pré-visualização do Curso</h2>
<div id="coursePreview" class="space-y-4">
<div class="text-center py-10 text-gray-400">
<i class="fas fa-book-open text-4xl mb-3"></i>
<p>Seu curso aparecerá aqui</p>
</div>
</div>
<div class="mt-6 pt-4 border-t border-gray-200">
<button id="generateCourse" class="w-full py-3 bg-indigo-600 text-white rounded-lg font-medium hover:bg-indigo-700 transition flex items-center justify-center">
<i class="fas fa-download mr-2"></i> Exportar Curso
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Module Modal -->
<div id="moduleModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50">
<div class="bg-white rounded-xl p-6 w-full max-w-2xl max-h-[90vh] overflow-y-auto">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold">Editar Módulo</h3>
<button id="closeModal" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Título do Módulo</label>
<input type="text" id="moduleTitle" class="w-full px-4 py-2 border border-gray-300 rounded-lg">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Conteúdo</label>
<textarea id="moduleContent" rows="6" class="w-full px-4 py-2 border border-gray-300 rounded-lg"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Imagem (URL)</label>
<input type="text" id="moduleImage" class="w-full px-4 py-2 border border-gray-300 rounded-lg" placeholder="Cole a URL da imagem">
</div>
<div class="pt-4">
<h4 class="font-medium mb-2">Adicionar Quiz</h4>
<div id="quizQuestions" class="space-y-3">
<!-- Quiz questions will be added here -->
</div>
<button id="addQuestion" class="mt-2 px-4 py-2 bg-blue-100 text-blue-600 rounded-lg text-sm font-medium">
<i class="fas fa-plus mr-1"></i> Adicionar Pergunta
</button>
</div>
<div class="pt-4">
<h4 class="font-medium mb-2">Adicionar Flashcards</h4>
<div id="flashcardsContainer" class="space-y-3">
<!-- Flashcards will be added here -->
</div>
<button id="addFlashcard" class="mt-2 px-4 py-2 bg-purple-100 text-purple-600 rounded-lg text-sm font-medium">
<i class="fas fa-plus mr-1"></i> Adicionar Flashcard
</button>
</div>
<div class="flex justify-end space-x-3 pt-4">
<button id="cancelModule" class="px-4 py-2 border border-gray-300 rounded-lg font-medium">Cancelar</button>
<button id="saveModule" class="px-4 py-2 bg-indigo-600 text-white rounded-lg font-medium">Salvar</button>
</div>
</div>
</div>
</div>
<script>
// DOM Elements
const textTab = document.getElementById('textTab');
const pdfTab = document.getElementById('pdfTab');
const txtTab = document.getElementById('txtTab');
const textInput = document.getElementById('textInput');
const fileInput = document.getElementById('fileInput');
const contentText = document.getElementById('contentText');
const analyzeText = document.getElementById('analyzeText');
const dropzone = document.getElementById('dropzone');
const fileUpload = document.getElementById('fileUpload');
const filePreview = document.getElementById('filePreview');
const fileName = document.getElementById('fileName');
const fileSize = document.getElementById('fileSize');
const removeFile = document.getElementById('removeFile');
const analyzeFile = document.getElementById('analyzeFile');
const modulesSection = document.getElementById('modulesSection');
const modulesContainer = document.getElementById('modulesContainer');
const addModule = document.getElementById('addModule');
const coursePreview = document.getElementById('coursePreview');
const generateCourse = document.getElementById('generateCourse');
const moduleModal = document.getElementById('moduleModal');
const closeModal = document.getElementById('closeModal');
const cancelModule = document.getElementById('cancelModule');
const saveModule = document.getElementById('saveModule');
const moduleTitle = document.getElementById('moduleTitle');
const moduleContent = document.getElementById('moduleContent');
const moduleImage = document.getElementById('moduleImage');
const quizQuestions = document.getElementById('quizQuestions');
const addQuestion = document.getElementById('addQuestion');
const flashcardsContainer = document.getElementById('flashcardsContainer');
const addFlashcard = document.getElementById('addFlashcard');
const uploadProgress = document.getElementById('uploadProgress');
const progressBar = document.getElementById('progressBar');
const progressPercent = document.getElementById('progressPercent');
// State
let currentTab = 'text';
let currentFile = null;
let modules = [];
let currentModuleIndex = null;
// Tab Switching
textTab.addEventListener('click', () => switchTab('text'));
pdfTab.addEventListener('click', () => switchTab('pdf'));
txtTab.addEventListener('click', () => switchTab('txt'));
function switchTab(tab) {
currentTab = tab;
// Update tab buttons
textTab.classList.remove('bg-indigo-600', 'text-white');
textTab.classList.add('bg-gray-200', 'text-gray-700');
pdfTab.classList.remove('bg-indigo-600', 'text-white');
pdfTab.classList.add('bg-gray-200', 'text-gray-700');
txtTab.classList.remove('bg-indigo-600', 'text-white');
txtTab.classList.add('bg-gray-200', 'text-gray-700');
if (tab === 'text') {
textTab.classList.remove('bg-gray-200', 'text-gray-700');
textTab.classList.add('bg-indigo-600', 'text-white');
textInput.classList.remove('hidden');
fileInput.classList.add('hidden');
} else {
if (tab === 'pdf') {
pdfTab.classList.remove('bg-gray-200', 'text-gray-700');
pdfTab.classList.add('bg-indigo-600', 'text-white');
fileUpload.setAttribute('accept', '.pdf');
} else {
txtTab.classList.remove('bg-gray-200', 'text-gray-700');
txtTab.classList.add('bg-indigo-600', 'text-white');
fileUpload.setAttribute('accept', '.txt');
}
textInput.classList.add('hidden');
fileInput.classList.remove('hidden');
}
}
// File Upload Handling
dropzone.addEventListener('dragover', (e) => {
e.preventDefault();
dropzone.classList.add('active');
});
dropzone.addEventListener('dragleave', () => {
dropzone.classList.remove('active');
});
dropzone.addEventListener('drop', (e) => {
e.preventDefault();
dropzone.classList.remove('active');
if (e.dataTransfer.files.length) {
handleFileUpload(e.dataTransfer.files[0]);
}
});
fileUpload.addEventListener('change', (e) => {
if (e.target.files.length) {
handleFileUpload(e.target.files[0]);
}
});
function handleFileUpload(file) {
// Validate file type based on current tab
let isValid = false;
if (currentTab === 'pdf') {
// Check for PDF files by extension or MIME type
isValid = file.name.toLowerCase().endsWith('.pdf') ||
file.type === 'application/pdf';
} else if (currentTab === 'txt') {
// Check for TXT files by extension or MIME type
isValid = file.name.toLowerCase().endsWith('.txt') ||
file.type === 'text/plain';
}
if (!isValid) {
alert(`Por favor, selecione um arquivo ${currentTab.toUpperCase()} válido.`);
return;
}
// Show file preview
currentFile = file;
fileName.textContent = file.name;
fileSize.textContent = formatFileSize(file.size);
filePreview.classList.remove('hidden');
// Simulate file upload with progress
simulateFileUpload(file);
}
function simulateFileUpload(file) {
// Show progress bar
uploadProgress.classList.remove('hidden');
analyzeFile.disabled = true;
let progress = 0;
const interval = setInterval(() => {
progress += Math.random() * 10;
if (progress > 100) progress = 100;
// Update progress bar
progressBar.style.width = `${progress}%`;
progressPercent.textContent = `${Math.round(progress)}%`;
if (progress === 100) {
clearInterval(interval);
setTimeout(() => {
uploadProgress.classList.add('hidden');
analyzeFile.disabled = false;
}, 500);
}
}, 200);
}
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
removeFile.addEventListener('click', () => {
currentFile = null;
fileUpload.value = '';
filePreview.classList.add('hidden');
uploadProgress.classList.add('hidden');
});
// Analyze Content
analyzeText.addEventListener('click', () => {
const text = contentText.value.trim();
if (!text) {
alert('Por favor, insira algum texto para gerar os módulos.');
return;
}
// Simulate AI processing
simulateProcessing(text);
});
analyzeFile.addEventListener('click', () => {
if (!currentFile) {
alert('Por favor, faça upload de um arquivo primeiro.');
return;
}
// Simulate file processing
simulateProcessing(`Conteúdo do arquivo ${currentFile.name}`);
});
function simulateProcessing(content) {
// Show loading state
const button = currentTab === 'text' ? analyzeText : analyzeFile;
button.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Processando...';
button.disabled = true;
// Simulate API call delay
setTimeout(() => {
// Generate sample modules from content
generateSampleModules(content);
// Reset button
button.innerHTML = '<i class="fas fa-magic mr-2"></i> ' + (currentTab === 'text' ? 'Gerar Módulos' : 'Processar Arquivo');
button.disabled = false;
// Show modules section
modulesSection.classList.remove('hidden');
// Update preview
updateCoursePreview();
}, 1500);
}
function generateSampleModules(content) {
// Clear existing modules
modules = [];
// Split content into logical sections (simulating AI analysis)
const sections = splitContentIntoSections(content);
// Create modules for each section
sections.forEach((section, index) => {
const module = {
id: Date.now() + index,
title: section.title,
content: section.content,
image: getRandomImageUrl(section.keywords[0] || 'education'),
quiz: generateQuizForSection(section),
flashcards: generateFlashcardsForSection(section)
};
modules.push(module);
});
// If no sections were created (unlikely), create a single module
if (modules.length === 0) {
modules.push({
id: Date.now(),
title: 'Módulo 1: Introdução',
content: content,
image: getRandomImageUrl('education'),
quiz: [{
question: "Qual é o tópico principal deste módulo?",
options: ["Opção A", "Opção B", "Opção C", "Opção D"],
correctAnswer: 0
}],
flashcards: [{
front: "Termo importante",
back: "Definição do termo"
}]
});
}
renderModules();
}
function splitContentIntoSections(content) {
// This is a simulation of how an AI might split content into modules
// In a real app, this would be done by an AI service
const paragraphs = content.split('\n\n').filter(p => p.trim().length > 0);
// If content is short, treat it as a single module
if (paragraphs.length <= 2) {
return [{
title: "Módulo 1: Visão Geral",
content: content,
keywords: ["introdução", "visão geral"]
}];
}
// Group paragraphs into sections
const sections = [];
let currentSection = null;
paragraphs.forEach(para => {
// Check if this paragraph starts a new section
const isHeading = para.split('\n')[0].length < 60 &&
(para.split('\n')[0].endsWith(':') ||
para.split('\n')[0].match(/^[A-Z][a-z]+/));
if (isHeading || !currentSection) {
// Start a new section
if (currentSection) {
sections.push(currentSection);
}
const title = isHeading ? para.split('\n')[0] : `Módulo ${sections.length + 1}: ${para.substring(0, 30)}...`;
const content = isHeading ? para.substring(para.indexOf('\n') + 1) : para;
currentSection = {
title: title,
content: content,
keywords: extractKeywords(para)
};
} else {
// Add to current section
currentSection.content += '\n\n' + para;
}
});
// Add the last section
if (currentSection) {
sections.push(currentSection);
}
// Limit to 5 sections for demo purposes
if (sections.length > 5) {
return sections.slice(0, 5).map((section, i) => ({
...section,
title: `Módulo ${i + 1}: ${section.title.substring(0, 40)}...`
}));
}
return sections;
}
function extractKeywords(text) {
// Simple keyword extraction simulation
const words = text.toLowerCase().split(/\s+/);
const commonWords = ['o', 'a', 'os', 'as', 'de', 'do', 'da', 'dos', 'das', 'em', 'no', 'na', 'nos', 'nas', 'por', 'para', 'com', 'sem', 'que', 'é'];
const keywords = words
.filter(word => word.length > 3 && !commonWords.includes(word))
.slice(0, 3);
return keywords.length > 0 ? keywords : ['aprendizado', 'conhecimento'];
}
function generateQuizForSection(section) {
// Generate 1-3 quiz questions per section
const questionCount = Math.min(3, Math.max(1, section.content.split('.').length / 5));
const questions = [];
for (let i = 0; i < questionCount; i++) {
questions.push({
question: `Pergunta ${i + 1} sobre "${section.title.substring(0, 20)}..."`,
options: ["Opção A", "Opção B", "Opção C", "Opção D"],
correctAnswer: Math.floor(Math.random() * 4)
});
}
return questions;
}
function generateFlashcardsForSection(section) {
// Generate 2-5 flashcards per section
const cardCount = Math.min(5, Math.max(2, section.keywords.length));
const flashcards = [];
for (let i = 0; i < cardCount; i++) {
const term = section.keywords[i] || `Termo ${i + 1}`;
flashcards.push({
front: term.charAt(0).toUpperCase() + term.slice(1),
back: `Definição de ${term}`
});
}
return flashcards;
}
function getRandomImageUrl(keyword) {
return `https://source.unsplash.com/300x200/?${keyword},education`;
}
// Modules Management
function renderModules() {
modulesContainer.innerHTML = '';
modules.forEach((module, index) => {
const moduleCard = document.createElement('div');
moduleCard.className = 'module-card bg-white rounded-xl shadow-md overflow-hidden';
moduleCard.innerHTML = `
<div class="p-5">
<div class="flex justify-between items-start">
<h3 class="font-semibold text-lg text-gray-800">${module.title}</h3>
<div class="flex space-x-2">
<button class="edit-module px-3 py-1 bg-blue-100 text-blue-600 rounded-lg text-sm" data-index="${index}">
<i class="fas fa-edit"></i>
</button>
<button class="delete-module px-3 py-1 bg-red-100 text-red-600 rounded-lg text-sm" data-index="${index}">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
<div class="mt-3 flex items-center text-sm text-gray-500">
<span class="mr-3"><i class="fas fa-image mr-1"></i> ${module.image ? 'Com imagem' : 'Sem imagem'}</span>
<span class="mr-3"><i class="fas fa-question-circle mr-1"></i> ${module.quiz.length} perguntas</span>
<span><i class="fas fa-layer-group mr-1"></i> ${module.flashcards.length} flashcards</span>
</div>
</div>
`;
modulesContainer.appendChild(moduleCard);
});
// Add event listeners to edit and delete buttons
document.querySelectorAll('.edit-module').forEach(btn => {
btn.addEventListener('click', (e) => {
const index = e.target.getAttribute('data-index');
openEditModuleModal(index);
});
});
document.querySelectorAll('.delete-module').forEach(btn => {
btn.addEventListener('click', (e) => {
const index = e.target.getAttribute('data-index');
if (confirm('Tem certeza que deseja excluir este módulo?')) {
modules.splice(index, 1);
renderModules();
updateCoursePreview();
}
});
});
}
addModule.addEventListener('click', () => {
currentModuleIndex = null;
moduleTitle.value = '';
moduleContent.value = '';
moduleImage.value = '';
quizQuestions.innerHTML = '';
flashcardsContainer.innerHTML = '';
moduleModal.classList.remove('hidden');
});
function openEditModuleModal(index) {
currentModuleIndex = index;
const module = modules[index];
moduleTitle.value = module.title;
moduleContent.value = module.content;
moduleImage.value = module.image || '';
// Render quiz questions
quizQuestions.innerHTML = '';
module.quiz.forEach((question, qIndex) => {
addQuestionToModal(question, qIndex);
});
// Render flashcards
flashcardsContainer.innerHTML = '';
module.flashcards.forEach((card, cIndex) => {
addFlashcardToModal(card, cIndex);
});
moduleModal.classList.remove('hidden');
}
// Quiz Question Management
addQuestion.addEventListener('click', () => {
addQuestionToModal({
question: '',
options: ['', '', '', ''],
correctAnswer: 0
}, quizQuestions.children.length);
});
function addQuestionToModal(question, index) {
const questionDiv = document.createElement('div');
questionDiv.className = 'bg-gray-50 p-3 rounded-lg';
questionDiv.innerHTML = `
<div class="flex justify-between items-center mb-2">
<label class="text-sm font-medium text-gray-700">Pergunta ${index + 1}</label>
<button class="remove-question text-red-500 text-sm" data-index="${index}">
<i class="fas fa-times"></i> Remover
</button>
</div>
<input type="text" class="w-full px-3 py-2 border border-gray-300 rounded-lg mb-2 question-text"
value="${question.question}" placeholder="Digite a pergunta">
<div class="space-y-2 mb-3">
${question.options.map((opt, optIndex) => `
<div class="flex items-center">
<input type="radio" name="correct-${index}" value="${optIndex}"
class="mr-2 correct-answer" ${question.correctAnswer === optIndex ? 'checked' : ''}>
<input type="text" class="flex-1 px-3 py-2 border border-gray-300 rounded-lg question-option"
value="${opt}" placeholder="Opção ${optIndex + 1}">
</div>
`).join('')}
</div>
`;
quizQuestions.appendChild(questionDiv);
// Add event listener to remove button
questionDiv.querySelector('.remove-question').addEventListener('click', (e) => {
e.target.closest('.bg-gray-50').remove();
// Renumber remaining questions
const questions = quizQuestions.querySelectorAll('.bg-gray-50');
questions.forEach((q, i) => {
q.querySelector('label').textContent = `Pergunta ${i + 1}`;
});
});
}
// Flashcard Management
addFlashcard.addEventListener('click', () => {
addFlashcardToModal({
front: '',
back: ''
}, flashcardsContainer.children.length);
});
function addFlashcardToModal(card, index) {
const cardDiv = document.createElement('div');
cardDiv.className = 'bg-gray-50 p-3 rounded-lg';
cardDiv.innerHTML = `
<div class="flex justify-between items-center mb-2">
<label class="text-sm font-medium text-gray-700">Flashcard ${index + 1}</label>
<button class="remove-flashcard text-red-500 text-sm" data-index="${index}">
<i class="fas fa-times"></i> Remover
</button>
</div>
<input type="text" class="w-full px-3 py-2 border border-gray-300 rounded-lg mb-2 flashcard-front"
value="${card.front}" placeholder="Frente (termo)">
<input type="text" class="w-full px-3 py-2 border border-gray-300 rounded-lg flashcard-back"
value="${card.back}" placeholder="Verso (definição)">
`;
flashcardsContainer.appendChild(cardDiv);
// Add event listener to remove button
cardDiv.querySelector('.remove-flashcard').addEventListener('click', (e) => {
e.target.closest('.bg-gray-50').remove();
// Renumber remaining flashcards
const cards = flashcardsContainer.querySelectorAll('.bg-gray-50');
cards.forEach((c, i) => {
c.querySelector('label').textContent = `Flashcard ${i + 1}`;
});
});
}
// Modal Actions
closeModal.addEventListener('click', () => {
moduleModal.classList.add('hidden');
});
cancelModule.addEventListener('click', () => {
moduleModal.classList.add('hidden');
});
saveModule.addEventListener('click', () => {
// Get module data from form
const title = moduleTitle.value.trim();
const content = moduleContent.value.trim();
const image = moduleImage.value.trim();
if (!title || !content) {
alert('Por favor, preencha pelo menos o título e o conteúdo do módulo.');
return;
}
// Get quiz questions
const quiz = [];
const questionDivs = quizQuestions.querySelectorAll('.bg-gray-50');
questionDivs.forEach(div => {
const questionText = div.querySelector('.question-text').value.trim();
const options = Array.from(div.querySelectorAll('.question-option')).map(opt => opt.value.trim());
const correctAnswer = parseInt(div.querySelector('.correct-answer:checked').value);
if (questionText && options.every(opt => opt)) {
quiz.push({
question: questionText,
options: options,
correctAnswer: correctAnswer
});
}
});
// Get flashcards
const flashcards = [];
const flashcardDivs = flashcardsContainer.querySelectorAll('.bg-gray-50');
flashcardDivs.forEach(div => {
const front = div.querySelector('.flashcard-front').value.trim();
const back = div.querySelector('.flashcard-back').value.trim();
if (front && back) {
flashcards.push({
front: front,
back: back
});
}
});
// Create or update module
const moduleData = {
id: currentModuleIndex !== null ? modules[currentModuleIndex].id : Date.now(),
title: title,
content: content,
image: image || null,
quiz: quiz,
flashcards: flashcards
};
if (currentModuleIndex !== null) {
// Update existing module
modules[currentModuleIndex] = moduleData;
} else {
// Add new module
modules.push(moduleData);
}
// Update UI
renderModules();
updateCoursePreview();
moduleModal.classList.add('hidden');
});
// Course Preview
function updateCoursePreview() {
const courseTitle = document.getElementById('courseTitle').value.trim() || 'Nome do Curso';
const courseDescription = document.getElementById('courseDescription').value.trim() || 'Descrição do curso será exibida aqui.';
coursePreview.innerHTML = `
<div class="text-center mb-6">
<h3 class="text-2xl font-bold text-gray-800">${courseTitle}</h3>
<p class="text-gray-600 mt-2">${courseDescription}</p>
</div>
${modules.length > 0 ? `
<div class="space-y-6">
${modules.map((module, index) => `
<div class="border border-gray-200 rounded-xl overflow-hidden">
<div class="bg-gray-50 px-5 py-3 border-b border-gray-200">
<h4 class="font-semibold text-gray-800">${module.title}</h4>
</div>
<div class="p-5">
${module.image ? `
<img src="${module.image}" alt="${module.title}" class="w-full h-48 object-cover rounded-lg mb-4">
` : ''}
<div class="prose max-w-none text-gray-700">
${module.content.split('\n').map(p => `<p>${p}</p>`).join('')}
</div>
${module.quiz.length > 0 ? `
<div class="mt-6 pt-4 border-t border-gray-200">
<h5 class="font-medium text-gray-800 mb-3">Quiz</h5>
<div class="space-y-4">
${module.quiz.map((q, qIndex) => `
<div class="quiz-question">
<p class="font-medium">${qIndex + 1}. ${q.question}</p>
<div class="mt-2 space-y-2">
${q.options.map((opt, optIndex) => `
<div class="flex items-center">
<input type="radio" id="quiz-${index}-${qIndex}-${optIndex}"
name="quiz-${index}-${qIndex}" class="mr-2" ${q.correctAnswer === optIndex ? 'checked' : ''}>
<label for="quiz-${index}-${qIndex}-${optIndex}" class="text-gray-700">${opt}</label>
</div>
`).join('')}
</div>
</div>
`).join('')}
</div>
</div>
` : ''}
${module.flashcards.length > 0 ? `
<div class="mt-6 pt-4 border-t border-gray-200">
<h5 class="font-medium text-gray-800 mb-3">Flashcards</h5>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
${module.flashcards.map((card, cIndex) => `
<div class="flip-card" onclick="this.classList.toggle('flipped')">
<div class="flip-card-inner bg-white rounded-lg shadow-sm border border-gray-200 h-32">
<div class="flip-card-front flex items-center justify-center p-4 text-center">
<p class="font-medium">${card.front}</p>
</div>
<div class="flip-card-back flex items-center justify-center p-4 text-center bg-indigo-50">
<p>${card.back}</p>
</div>
</div>
</div>
`).join('')}
</div>
</div>
` : ''}
</div>
</div>
`).join('')}
</div>
` : `
<div class="text-center py-10 text-gray-400">
<i class="fas fa-book-open text-4xl mb-3"></i>
<p>Adicione módulos para visualizar o curso</p>
</div>
`}
`;
// Add event listeners to flip cards
document.querySelectorAll('.flip-card').forEach(card => {
card.addEventListener('click', function() {
this.classList.toggle('flipped');
});
});
}
// Export Course
generateCourse.addEventListener('click', () => {
if (modules.length === 0) {
alert('Por favor, adicione pelo menos um módulo ao curso antes de exportar.');
return;
}
// In a real app, this would generate a downloadable package
alert('Funcionalidade de exportação seria implementada aqui!\nO curso seria empacotado para download.');
});
// Initialize
document.getElementById('courseTitle').addEventListener('input', updateCoursePreview);
document.getElementById('courseDescription').addEventListener('input', updateCoursePreview);
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=zoeboy/criador-de-cursos2" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>