```html
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Green Flashcards</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<nav>
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#create">Create</a></li>
<li><a href="#study">Study</a></li>
</ul>
</nav>
<main id="app">
<!-- Content will be dynamically inserted here -->
</main>
<script src="app.js"></script>
</body>
</html>
```
```css
/* styles.css */
:root {
--primary-color: #4CAF50;
--secondary-color: #45a049;
--text-color: #333;
--background-color: #f4f4f4;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: var(--text-color);
background-color: var(--background-color);
margin: 0;
padding: 0;
}
nav {
background-color: var(--primary-color);
padding: 1rem;
}
nav ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
justify-content: space-around;
}
nav a {
color: white;
text-decoration: none;
}
main {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
.btn {
background-color: var(--primary-color);
color: white;
padding: 0.5rem 1rem;
border: none;
cursor: pointer;
font-size: 1rem;
}
.btn:hover {
background-color: var(--secondary-color);
}
.flashcard {
background-color: white;
border: 1px solid #ddd;
border-radius: 5px;
padding: 1rem;
margin-bottom: 1rem;
cursor: pointer;
}
.flashcard-front, .flashcard-back {
display: none;
}
.flashcard.show-front .flashcard-front,
.flashcard.show-back .flashcard-back {
display: block;
}
```
```javascript
// app.js
class Flashcard {
constructor(front, back) {
this.front = front;
this.back = back;
this.box = 0;
this.nextReview = new Date();
}
}
class FlashcardApp {
constructor() {
this.flashcards = [];
this.currentPage = 'home';
this.initEventListeners();
this.renderPage();
}
initEventListeners() {
document.querySelector('nav').addEventListener('click', (e) => {
if (e.target.tagName === 'A') {
e.preventDefault();
this.currentPage = e.target.getAttribute('href').slice(1);
this.renderPage();
}
});
}
renderPage() {
const app = document.getElementById('app');
app.innerHTML = '';
switch (this.currentPage) {
case 'home':
this.renderHome(app);
break;
case 'create':
this.renderCreate(app);
break;
case 'study':
this.renderStudy(app);
break;
}
}
renderHome(app) {
const title = document.createElement('h1');
title.textContent = 'Green Flashcards';
app.appendChild(title);
const uploadBtn = document.createElement('input');
uploadBtn.type = 'file';
uploadBtn.accept = '.txt';
uploadBtn.addEventListener('change', (e) => this.handleFileUpload(e));
app.appendChild(uploadBtn);
const flashcardList = document.createElement('div');
this.flashcards.forEach((card, index) => {
const cardElement = document.createElement('div');
cardElement.className = 'flashcard';
cardElement.textContent = `Flashcard ${index + 1}: ${card.front}`;
cardElement.addEventListener('click', () => this.viewFlashcard(index));
flashcardList.appendChild(cardElement);
});
app.appendChild(flashcardList);
}
renderCreate(app) {
const title = document.createElement('h2');
title.textContent = 'Create Flashcard';
app.appendChild(title);
const form = document.createElement('form');
form.innerHTML = `
<label for="front">Front:</label>
<input type="text" id="front" required>
<label for="back">Back:</label>
<input type="text" id="back" required>
<button type="submit" class="btn">Create</button>
`;
form.addEventListener('submit', (e) => this.handleCreateFlashcard(e));
app.appendChild(form);
}
renderStudy(app) {
if (this.flashcards.length === 0) {
app.textContent = 'No flashcards to study. Create some first!';
return;
}
const card = this.getNextCardToStudy();
const cardElement = document.createElement('div');
cardElement.className = 'flashcard show-front';
cardElement.innerHTML = `
<div class="flashcard-front">${card.front}</div>
<div class="flashcard-back">${card.back}</div>
`;
cardElement.addEventListener('click', () => {
cardElement.classList.toggle('show-front');
cardElement.classList.toggle('show-back');
});
app.appendChild(cardElement);
const buttonsContainer = document.createElement('div');
['Again', 'Hard', 'Good', 'Easy'].forEach(label => {
const btn = document.createElement('button');
btn.textContent = label;
btn.className = 'btn';
btn.addEventListener('click', () => this.processAnswer(card, label));
buttonsContainer.appendChild(btn);
});
app.appendChild(buttonsContainer);
}
handleFileUpload(e) {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = (e) => {
const content = e.target.result;
this.parseTextToFlashcards(content);
};
reader.readAsText(file);
}
parseTextToFlashcards(text) {
const lines = text.split('\n');
for (let i = 0; i < lines.length; i += 2) {
if (lines[i] && lines[i + 1]) {
this.flashcards.push(new Flashcard(lines[i].trim(), lines[i + 1].trim()));
}
}
this.renderPage();
}
handleCreateFlashcard(e) {
e.preventDefault();
const front = document.getElementById('front').value;
const back = document.getElementById('back').value;
this.flashcards.push(new Flashcard(front, back));
this.renderPage();
}
viewFlashcard(index) {
// Implement flashcard viewing logic
}
getNextCardToStudy() {
// Implement spaced repetition algorithm
return this.flashcards[Math.floor(Math.random() * this.flashcards.length)];
}
processAnswer(card, difficulty) {
// Implement spaced repetition logic based on the answer
this.renderPage();
}
}
new FlashcardApp();
```
This code provides a basic structure for the flashcard application with the following features:
1. A minimalist green-themed UI
2. Navigation between Home, Create, and Study pages
3. File upload functionality to convert .txt files to flashcards
4. Manual flashcard creation
5. A simple study interface with flashcard flipping
6. Placeholders for implementing a spaced repetition system
To fully implement the application, you would need to:
1. Expand the spaced repetition algorithm in the `getNextCardToStudy` and `processAnswer` methods
2. Implement local storage or a backend API to persist flashcards
3. Add more robust error handling and input validation
4. Enhance the UI with animations and more detailed styling
5. Implement the `viewFlashcard` method for individual card viewing
This skeleton provides a solid foundation for building out the complete flashcard application with the specified features.