flashcard-simulator / index.html
DanielMoz's picture
1. The theme buttons do not work; fix that. 2. Create cards input must be alongside Preview space; check for responsiveness. 3. Add translation option (portuguese). 4. Make the flashcard preview more colourful, vibrant. 5. Add a feature of your choice. - Initial Deployment
8ccbfab verified
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flash Card Study Simulator</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>
/* Custom themes */
.blue-theme {
--tw-bg-opacity: 1;
--tw-text-opacity: 1;
--color-primary: 59 130 246;
--color-secondary: 191 219 254;
}
.green-theme {
--tw-bg-opacity: 1;
--tw-text-opacity: 1;
--color-primary: 34 197 94;
--color-secondary: 187 247 208;
}
.blue-theme .card {
background: linear-gradient(to bottom right, var(--color-secondary), white);
}
.green-theme .card {
background: linear-gradient(to bottom right, var(--color-secondary), white);
}
.card {
perspective: 1000px;
transform-style: preserve-3d;
transition: all 0.5s ease;
}
.card-inner {
transition: transform 0.6s;
transform-style: preserve-3d;
}
.card.flipped .card-inner {
transform: rotateY(180deg);
}
.card-front, .card-back {
backface-visibility: hidden;
position: absolute;
width: 100%;
height: 100%;
}
.card-back {
transform: rotateY(180deg);
}
.fade-in {
animation: fadeIn 0.3s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.progress-bar {
transition: width 0.3s ease;
}
</style>
</head>
<body class="bg-gray-100 dark:bg-gray-900 min-h-screen transition-colors duration-300">
<div class="container mx-auto px-4 py-8 max-w-4xl">
<!-- Header -->
<header class="flex justify-between items-center mb-8">
<h1 class="text-3xl font-bold text-gray-800 dark:text-white" id="mainTitle">Flash Card Simulator</h1>
<div class="flex items-center space-x-2">
<button id="enLangBtn" class="p-2 rounded-full bg-blue-500 text-white" title="English">
EN
</button>
<button id="ptLangBtn" class="p-2 rounded-full bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200" title="Português">
PT
</button>
<div class="flex items-center space-x-2">
<button id="lightThemeBtn" class="p-2 rounded-full bg-gray-200 text-gray-700" title="Light Theme">
<i class="fas fa-sun"></i>
</button>
<button id="darkThemeBtn" class="p-2 rounded-full bg-gray-700 text-gray-200" title="Dark Theme">
<i class="fas fa-moon"></i>
</button>
<button id="blueThemeBtn" class="p-2 rounded-full bg-blue-100 text-blue-700" title="Blue Theme">
<i class="fas fa-droplet"></i>
</button>
<button id="greenThemeBtn" class="p-2 rounded-full bg-green-100 text-green-700" title="Green Theme">
<i class="fas fa-leaf"></i>
</button>
</div>
</header>
<!-- Main Content -->
<div class="grid grid-cols-1 xl:grid-cols-2 gap-8">
<!-- Input Section -->
<div id="inputSection" class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 transition-all duration-300">
<h2 class="text-xl font-semibold mb-4 text-gray-800 dark:text-white">Create Your Cards</h2>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Deck Title</label>
<input type="text" id="deckTitle" placeholder="My Study Deck"
class="w-full px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
</div>
<div id="cardInputs" class="space-y-4">
<div class="card-input-group flex items-start space-x-2">
<div class="flex-1 space-y-2">
<input type="text" placeholder="Term" class="w-full px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-white">
<textarea placeholder="Definition" rows="2" class="w-full px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"></textarea>
<select class="w-full px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-white">
<option value="easy">Easy</option>
<option value="medium">Medium</option>
<option value="hard">Hard</option>
</select>
</div>
<button class="remove-card-btn mt-2 text-red-500 hover:text-red-700 dark:hover:text-red-400">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<div class="flex justify-between mt-6">
<button id="addCardBtn" class="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-lg transition-colors">
<i class="fas fa-plus mr-2"></i>Add Card
</button>
<button id="startStudyBtn" class="px-4 py-2 bg-green-500 hover:bg-green-600 text-white rounded-lg transition-colors">
<i class="fas fa-play mr-2"></i>Start Studying
</button>
</div>
</div>
<!-- Preview Section -->
<div id="previewSection" class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 transition-all duration-300">
<h2 class="text-xl font-semibold mb-4 text-gray-800 dark:text-white">Preview</h2>
<div class="flex justify-center">
<div class="card w-full max-w-md h-64 bg-gradient-to-br from-purple-100 via-pink-100 to-yellow-100 dark:from-purple-900 dark:via-pink-900 dark:to-yellow-900 rounded-xl shadow-lg cursor-pointer transform hover:scale-105 transition-transform duration-300" id="previewCard">
<div class="card-inner h-full">
<div class="card-front flex flex-col justify-center items-center h-full p-6">
<p class="text-gray-500 dark:text-gray-300 text-sm">Term</p>
<h3 class="text-2xl font-bold text-center text-gray-800 dark:text-white mt-2">Sample Term</h3>
</div>
<div class="card-back flex flex-col justify-center items-center h-full p-6">
<p class="text-gray-500 dark:text-gray-300 text-sm">Definition</p>
<p class="text-lg text-center text-gray-700 dark:text-gray-200 mt-2">Sample definition goes here...</p>
</div>
</div>
</div>
</div>
<p class="text-sm text-gray-500 dark:text-gray-400 text-center mt-4">Click the card to flip</p>
</div>
</div>
<!-- Study Mode Section (Hidden Initially) -->
<div id="studySection" class="hidden bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 mt-8 transition-all duration-300">
<div class="flex justify-between items-center mb-6">
<h2 id="studyDeckTitle" class="text-xl font-semibold text-gray-800 dark:text-white">Studying: My Deck</h2>
<button id="exitStudyBtn" class="px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">
Exit Study Mode
</button>
</div>
<!-- Progress Bar -->
<div class="mb-6">
<div class="flex justify-between mb-1">
<span id="progressText" class="text-sm font-medium text-gray-700 dark:text-gray-300">0/0 cards</span>
<span id="scoreText" class="text-sm font-medium text-gray-700 dark:text-gray-300">Score: 0%</span>
</div>
<div class="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2.5">
<div id="progressBar" class="progress-bar bg-blue-500 h-2.5 rounded-full" style="width: 0%"></div>
</div>
</div>
<!-- Flash Card -->
<div class="flex justify-center mb-8">
<div class="card w-full max-w-md h-80 bg-gradient-to-br from-blue-50 to-blue-100 dark:from-gray-700 dark:to-gray-600 blue-theme:from-blue-100 blue-theme:to-white green-theme:from-green-100 green-theme:to-white rounded-xl shadow-lg cursor-pointer" id="studyCard">
<div class="card-inner h-full">
<div class="card-front flex flex-col justify-center items-center h-full p-6">
<p class="text-gray-500 dark:text-gray-300 text-sm">Term</p>
<h3 id="cardTerm" class="text-3xl font-bold text-center text-gray-800 dark:text-white mt-4">Loading...</h3>
</div>
<div class="card-back flex flex-col justify-center items-center h-full p-6">
<p class="text-gray-500 dark:text-gray-300 text-sm">Definition</p>
<p id="cardDefinition" class="text-xl text-center text-gray-700 dark:text-gray-200 mt-4">Loading...</p>
</div>
</div>
</div>
</div>
<!-- Controls -->
<div class="flex flex-col sm:flex-row justify-center space-y-4 sm:space-y-0 sm:space-x-4">
<button id="knewItBtn" class="px-6 py-3 bg-green-500 hover:bg-green-600 text-white rounded-lg transition-colors">
<i class="fas fa-check mr-2"></i>Knew It
</button>
<button id="flipCardBtn" class="px-6 py-3 bg-blue-500 hover:bg-blue-600 text-white rounded-lg transition-colors">
<i class="fas fa-sync-alt mr-2"></i>Flip Card
</button>
<button id="didntKnowBtn" class="px-6 py-3 bg-red-500 hover:bg-red-600 text-white rounded-lg transition-colors">
<i class="fas fa-times mr-2"></i>Didn't Know
</button>
</div>
</div>
</div>
<script>
// Theme Management
const themes = {
light: {
class: '',
icon: 'fa-sun',
bg: 'bg-gray-200',
text: 'text-gray-700'
},
dark: {
class: 'dark',
icon: 'fa-moon',
bg: 'bg-gray-700',
text: 'text-gray-200'
},
blue: {
class: 'blue-theme',
icon: 'fa-droplet',
bg: 'bg-blue-100',
text: 'text-blue-700'
},
green: {
class: 'green-theme',
icon: 'fa-leaf',
bg: 'bg-green-100',
text: 'text-green-700'
}
};
// Set theme
function setTheme(themeName) {
// Remove all theme classes first
document.documentElement.classList.remove('dark', 'blue-theme', 'green-theme');
// Add selected theme class
if (themeName !== 'light') {
document.documentElement.classList.add(themes[themeName].class);
}
// Update active button styles
Object.keys(themes).forEach(theme => {
const btn = document.getElementById(`${theme}ThemeBtn`);
if (btn) {
btn.className = `p-2 rounded-full ${theme === themeName ?
`${themes[theme].bg} ${themes[theme].text}` :
'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200'}`;
}
});
// Save to localStorage
localStorage.setItem('theme', themeName);
}
// Translation texts
const translations = {
en: {
title: "Flash Card Simulator",
createCards: "Create Your Cards",
deckTitle: "Deck Title",
term: "Term",
definition: "Definition",
difficulty: "Difficulty",
preview: "Preview",
addCard: "Add Card",
startStudy: "Start Studying",
studying: "Studying",
exitStudy: "Exit Study Mode",
knewIt: "Knew It",
flipCard: "Flip Card",
didntKnow: "Didn't Know"
},
pt: {
title: "Simulador de Cartões",
createCards: "Crie Seus Cartões",
deckTitle: "Título do Baralho",
term: "Termo",
definition: "Definição",
difficulty: "Dificuldade",
preview: "Pré-visualização",
addCard: "Adicionar Cartão",
startStudy: "Começar a Estudar",
studying: "Estudando",
exitStudy: "Sair do Modo Estudo",
knewIt: "Sabia",
flipCard: "Virar Cartão",
didntKnow: "Não Sabia"
}
};
// Set language
function setLanguage(lang) {
document.getElementById('mainTitle').textContent = translations[lang].title;
document.querySelector('#inputSection h2').textContent = translations[lang].createCards;
document.querySelector('#inputSection label').textContent = translations[lang].deckTitle;
document.querySelector('#previewSection h2').textContent = translations[lang].preview;
document.getElementById('addCardBtn').innerHTML = `<i class="fas fa-plus mr-2"></i>${translations[lang].addCard}`;
document.getElementById('startStudyBtn').innerHTML = `<i class="fas fa-play mr-2"></i>${translations[lang].startStudy}`;
document.getElementById('studyDeckTitle').textContent = `${translations[lang].studying}: My Deck`;
document.getElementById('exitStudyBtn').textContent = translations[lang].exitStudy;
document.getElementById('knewItBtn').innerHTML = `<i class="fas fa-check mr-2"></i>${translations[lang].knewIt}`;
document.getElementById('flipCardBtn').innerHTML = `<i class="fas fa-sync-alt mr-2"></i>${translations[lang].flipCard}`;
document.getElementById('didntKnowBtn').innerHTML = `<i class="fas fa-times mr-2"></i>${translations[lang].didntKnow}`;
// Update all input placeholders
document.querySelectorAll('#cardInputs input[type="text"]').forEach(input => {
input.placeholder = translations[lang].term;
});
document.querySelectorAll('#cardInputs textarea').forEach(textarea => {
textarea.placeholder = translations[lang].definition;
});
document.querySelectorAll('#cardInputs select').forEach(select => {
select.innerHTML = `
<option value="easy">${translations[lang].easy || 'Easy'}</option>
<option value="medium">${translations[lang].medium || 'Medium'}</option>
<option value="hard">${translations[lang].hard || 'Hard'}</option>
`;
});
// Update active button
document.getElementById('enLangBtn').className = `p-2 rounded-full ${lang === 'en' ? 'bg-blue-500 text-white' : 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200'}`;
document.getElementById('ptLangBtn').className = `p-2 rounded-full ${lang === 'pt' ? 'bg-blue-500 text-white' : 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200'}`;
localStorage.setItem('language', lang);
}
// Initialize theme and language
const savedTheme = localStorage.getItem('theme') ||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
setTheme(savedTheme);
const savedLanguage = localStorage.getItem('language') || 'en';
setLanguage(savedLanguage);
// Language buttons
document.getElementById('enLangBtn').addEventListener('click', () => setLanguage('en'));
document.getElementById('ptLangBtn').addEventListener('click', () => setLanguage('pt'));
// Theme buttons
document.getElementById('lightThemeBtn').addEventListener('click', () => setTheme('light'));
document.getElementById('darkThemeBtn').addEventListener('click', () => setTheme('dark'));
document.getElementById('blueThemeBtn').addEventListener('click', () => setTheme('blue'));
document.getElementById('greenThemeBtn').addEventListener('click', () => setTheme('green'));
// Card Management
let cards = [];
let currentCardIndex = 0;
let knownCards = 0;
let totalCards = 0;
// Add new card input
document.getElementById('addCardBtn').addEventListener('click', () => {
const cardInputs = document.getElementById('cardInputs');
const newCard = document.createElement('div');
newCard.className = 'card-input-group flex items-start space-x-2 fade-in';
newCard.innerHTML = `
<div class="flex-1 space-y-2">
<input type="text" placeholder="Term" class="w-full px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-white">
<textarea placeholder="Definition" rows="2" class="w-full px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"></textarea>
</div>
<button class="remove-card-btn mt-2 text-red-500 hover:text-red-700 dark:hover:text-red-400">
<i class="fas fa-times"></i>
</button>
`;
cardInputs.appendChild(newCard);
// Add event to remove button
newCard.querySelector('.remove-card-btn').addEventListener('click', () => {
newCard.classList.add('opacity-0', 'h-0', 'overflow-hidden', 'transition-all', 'duration-300');
setTimeout(() => newCard.remove(), 300);
});
// Update preview
updatePreview();
});
// Update preview card
function updatePreview() {
const inputs = document.querySelectorAll('.card-input-group');
if (inputs.length > 0) {
const lastInput = inputs[inputs.length - 1];
const term = lastInput.querySelector('input').value || 'Sample Term';
const definition = lastInput.querySelector('textarea').value || 'Sample definition goes here...';
document.querySelector('#previewCard .card-front h3').textContent = term;
document.querySelector('#previewCard .card-back p:nth-child(2)').textContent = definition;
}
}
// Add input listeners for live preview
document.getElementById('cardInputs').addEventListener('input', (e) => {
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') {
updatePreview();
}
});
// Flip card functionality for preview
document.getElementById('previewCard').addEventListener('click', function() {
this.classList.toggle('flipped');
});
// Start study session
document.getElementById('startStudyBtn').addEventListener('click', () => {
const deckTitle = document.getElementById('deckTitle').value || 'My Study Deck';
const cardInputs = document.querySelectorAll('.card-input-group');
if (cardInputs.length === 0) {
alert('Please add at least one flash card before starting.');
return;
}
// Collect all cards
cards = [];
cardInputs.forEach(input => {
const term = input.querySelector('input').value.trim();
const definition = input.querySelector('textarea').value.trim();
if (term && definition) {
cards.push({
term,
definition,
known: false
});
}
});
if (cards.length === 0) {
alert('Please fill in both term and definition for at least one card.');
return;
}
// Shuffle cards
shuffleArray(cards);
// Reset study stats
currentCardIndex = 0;
knownCards = 0;
totalCards = cards.length;
// Update UI
document.getElementById('studyDeckTitle').textContent = `Studying: ${deckTitle}`;
document.getElementById('inputSection').classList.add('hidden');
document.getElementById('previewSection').classList.add('hidden');
document.getElementById('studySection').classList.remove('hidden');
// Show first card
showCurrentCard();
updateProgress();
});
// Exit study mode
document.getElementById('exitStudyBtn').addEventListener('click', () => {
document.getElementById('inputSection').classList.remove('hidden');
document.getElementById('previewSection').classList.remove('hidden');
document.getElementById('studySection').classList.add('hidden');
});
// Show current card in study mode
function showCurrentCard() {
if (currentCardIndex < cards.length) {
const card = cards[currentCardIndex];
document.getElementById('cardTerm').textContent = card.term;
document.getElementById('cardDefinition').textContent = card.definition;
// Ensure card is not flipped when showing new card
const studyCard = document.getElementById('studyCard');
studyCard.classList.remove('flipped');
} else {
// Study session complete
const score = Math.round((knownCards / totalCards) * 100);
document.getElementById('cardTerm').textContent = 'Study Complete!';
document.getElementById('cardDefinition').textContent = `You knew ${knownCards} of ${totalCards} cards (${score}%)`;
// Disable buttons
document.getElementById('knewItBtn').disabled = true;
document.getElementById('didntKnowBtn').disabled = true;
document.getElementById('flipCardBtn').disabled = true;
}
}
// Update progress bar and text
function updateProgress() {
const progress = Math.round(((currentCardIndex) / totalCards) * 100);
const score = currentCardIndex > 0 ? Math.round((knownCards / currentCardIndex) * 100) : 0;
document.getElementById('progressText').textContent = `${currentCardIndex}/${totalCards} cards`;
document.getElementById('scoreText').textContent = `Score: ${score}%`;
document.getElementById('progressBar').style.width = `${progress}%`;
}
// Flip card in study mode
document.getElementById('flipCardBtn').addEventListener('click', () => {
document.getElementById('studyCard').classList.toggle('flipped');
});
// Click card to flip in study mode
document.getElementById('studyCard').addEventListener('click', function() {
this.classList.toggle('flipped');
});
// Knew it button
document.getElementById('knewItBtn').addEventListener('click', () => {
if (currentCardIndex < cards.length) {
cards[currentCardIndex].known = true;
knownCards++;
currentCardIndex++;
showCurrentCard();
updateProgress();
}
});
// Didn't know button
document.getElementById('didntKnowBtn').addEventListener('click', () => {
if (currentCardIndex < cards.length) {
cards[currentCardIndex].known = false;
currentCardIndex++;
showCurrentCard();
updateProgress();
}
});
// Utility function to shuffle array
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
</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=DanielMoz/flashcard-simulator" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>