';
cardProgress.textContent = "Card 0 of 0";
return;
}
const deck = flashcardData.decks.find(d => d.id == deckId);
if (!deck) return;
studySession.deck = deck;
studySession.currentIndex = 0;
studySession.shuffledIndices = Array.from(Array(deck.cards.length).keys());
flashcardData.lastStudiedDeckId = deck.id;
saveData();
renderCurrentCard();
};
const renderCurrentCard = () => {
if (!studySession.deck || studySession.deck.cards.length === 0) {
flashcardContainer.innerHTML = '';
cardProgress.textContent = "Card 0 of 0";
return;
}
const cardIndex = studySession.shuffledIndices[studySession.currentIndex];
const card = studySession.deck.cards[cardIndex];
flashcardContainer.innerHTML = `
`;
cardProgress.textContent = `Card ${studySession.currentIndex + 1} of ${studySession.deck.cards.length}`;
};
deckSelector.addEventListener('change', (e) => loadDeckForStudy(e.target.value));
flipCardBtn.addEventListener('click', () => flashcardContainer.querySelector('.flashcard')?.classList.toggle('flipped'));
nextCardBtn.addEventListener('click', () => {
if (studySession.deck && studySession.currentIndex < studySession.deck.cards.length - 1) {
studySession.currentIndex++;
renderCurrentCard();
}
});
prevCardBtn.addEventListener('click', () => {
if (studySession.deck && studySession.currentIndex > 0) {
studySession.currentIndex--;
renderCurrentCard();
}
});
shuffleBtn.addEventListener('click', () => {
if (!studySession.deck || studySession.deck.cards.length < 2) return;
// Fisher-Yates shuffle
for (let i = studySession.shuffledIndices.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[studySession.shuffledIndices[i], studySession.shuffledIndices[j]] = [studySession.shuffledIndices[j], studySession.shuffledIndices[i]];
}
studySession.currentIndex = 0;
renderCurrentCard();
showMessage('Deck shuffled!', false);
});
// --- MANAGE LIBRARY TAB LOGIC ---
const renderDeckManagement = () => {
deckManagementList.innerHTML = '';
if (flashcardData.decks.length === 0) {
deckManagementList.innerHTML = '
`;
deckManagementList.appendChild(deckContainer);
});
};
addDeckBtn.addEventListener('click', () => {
const name = newDeckNameInput.value.trim();
if (!name) {
showMessage('Please enter a deck name.');
return;
}
flashcardData.decks.push({
id: Date.now(),
name: name,
cards: []
});
newDeckNameInput.value = '';
saveData();
renderDeckManagement();
showMessage('Deck created successfully!', false);
});
deckManagementList.addEventListener('click', (e) => {
const target = e.target;
// Add Card
if (target.classList.contains('add-card-btn')) {
const deckId = target.dataset.deckId;
const form = target.closest('.add-card-form');
const termInput = form.querySelector('.new-card-term');
const defInput = form.querySelector('.new-card-def');
const term = termInput.value.trim();
const def = defInput.value.trim();
if (!term || !def) {
showMessage('Both term and definition are required.');
return;
}
const deck = flashcardData.decks.find(d => d.id == deckId);
deck.cards.push({ id: Date.now(), term, definition: def });
termInput.value = '';
defInput.value = '';
saveData();
renderDeckManagement();
}
// Delete Card
if (target.classList.contains('delete-card-btn')) {
const deckId = target.dataset.deckId;
const cardId = target.dataset.cardId;
const deck = flashcardData.decks.find(d => d.id == deckId);
deck.cards = deck.cards.filter(c => c.id != cardId);
saveData();
renderDeckManagement();
}
// Delete Deck
if (target.classList.contains('delete-deck-btn')) {
const deckId = target.dataset.deckId;
if (confirm('Are you sure you want to delete this entire deck?')) {
flashcardData.decks = flashcardData.decks.filter(d => d.id != deckId);
if (flashcardData.lastStudiedDeckId == deckId) {
flashcardData.lastStudiedDeckId = null;
}
saveData();
renderDeckManagement();
}
}
// Download PDF
if (target.classList.contains('download-pdf-btn')) {
handlePdfDownload(target.dataset.deckId);
}
});
// --- PDF DOWNLOAD LOGIC ---
const handlePdfDownload = (deckId) => {
const deck = flashcardData.decks.find(d => d.id == deckId);
if (!deck) return;
showMessage('Preparing PDF...', false);
// Create a temporary, hidden element for PDF generation
const pdfElement = document.createElement('div');
pdfElement.style.position = 'absolute';
pdfElement.style.left = '-9999px';
pdfElement.style.width = '800px';
pdfElement.style.padding = '20px';
pdfElement.innerHTML = `
`;
document.body.appendChild(pdfElement);
const { jsPDF } = window.jspdf;
html2canvas(pdfElement, { scale: 2 }).then(canvas => {
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({ orientation: 'portrait', unit: 'in', format: 'letter' });
const pdfWidth = pdf.internal.pageSize.getWidth() - 1;
const pdfHeight = (canvas.height * pdfWidth) / canvas.width;
pdf.addImage(imgData, 'PNG', 0.5, 0.5, pdfWidth, pdfHeight);
pdf.save(`${deck.name.replace(/ /g, '_')}_Flashcards.pdf`);
document.body.removeChild(pdfElement);
showMessage('PDF downloaded!', false);
}).catch(err => {
console.error("PDF Generation Error:", err);
showMessage("An error occurred during PDF generation.");
document.body.removeChild(pdfElement);
});
};
// --- INITIALIZATION ---
const initializeApp = () => {
loadData();
switchTab('tab1');
};
initializeApp();
});
This deck is empty. Add cards in the "Manage Library" tab.
${card.term}
${card.definition}
You have no decks. Create one above to get started.
'; return; } flashcardData.decks.forEach(deck => { const deckContainer = document.createElement('div'); deckContainer.className = 'border border-gray-200 rounded-lg'; deckContainer.innerHTML = `${deck.name}
${deck.cards.map(card => `
${card.term}: ${card.definition}
`).join('') || 'This deck is empty.
'}${deck.name}
| Term | Definition |
|---|---|
| ${card.term} | ${card.definition} |
