story-ai / templates /index.html
qdqd's picture
Create templates/index.html
bb0e9e0 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Wattpad Story Generator</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<link href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
</head>
<body>
<nav class="navbar">
<div class="nav-container">
<div class="logo">
<i class="fas fa-book-open"></i>
<h1>Story<span>AI</span></h1>
</div>
<div class="nav-links">
<a href="#" class="active"><i class="fas fa-magic"></i> Generate</a>
<a href="#"><i class="fas fa-book"></i> </a>
</div>
</div>
</nav>
<div class="container">
<main>
<div class="story-generator">
<div class="input-section">
<h2><i class="fas fa-feather-alt"></i> Create Your Story</h2>
<p class="subtitle">Transform your ideas into captivating stories</p>
<div class="input-group">
<div class="input-wrapper">
<i class="fas fa-pencil-alt input-icon"></i>
<input type="text" id="topic" placeholder="Enter your story topic..." required>
</div>
<button id="generate-btn">
<i class="fas fa-wand-magic-sparkles"></i>
Generate Story
</button>
</div>
</div>
<div class="loading-spinner" style="display: none;">
<div class="spinner"></div>
<p><i class="fas fa-pen-fancy"></i> Crafting your story with creativity...</p>
</div>
<div class="story-container" style="display: none;">
<div class="chapter-navigation">
<button class="nav-btn" id="prev-chapter" disabled>
<i class="fas fa-chevron-left"></i> Previous Chapter
</button>
<span class="chapter-indicator">Chapter <span id="current-chapter">1</span></span>
<button class="nav-btn" id="next-chapter">
Next Chapter <i class="fas fa-chevron-right"></i>
</button>
</div>
<div class="story-header">
<div class="story-meta">
<i class="fas fa-book-open story-icon"></i>
<h3 class="story-title"></h3>
</div>
<div class="story-stats">
<span><i class="fas fa-eye"></i> 0 Reads</span>
<span><i class="fas fa-star"></i> 0 Votes</span>
<span><i class="fas fa-comment"></i> 0 Comments</span>
</div>
</div>
<div class="chapters-list">
<!-- Chapters will be dynamically added here -->
</div>
<div class="story-actions">
<button class="action-btn"><i class="fas fa-star"></i> Vote</button>
<button class="action-btn"><i class="fas fa-comment"></i> Comment</button>
<button class="action-btn"><i class="fas fa-share"></i> Share</button>
</div>
</div>
</div>
</main>
</div>
<script>
let currentChapter = 1;
let allChapters = [];
let currentTopic = '';
document.getElementById('generate-btn').addEventListener('click', async () => {
const topic = document.getElementById('topic').value.trim();
if (!topic) {
alert('Please enter a topic');
return;
}
currentTopic = topic;
currentChapter = 1;
allChapters = [];
await generateChapter(topic);
});
document.getElementById('next-chapter').addEventListener('click', async () => {
// Only use the last chapter as context
const lastChapter = allChapters[allChapters.length - 1].content;
currentChapter++;
await generateChapter(currentTopic, lastChapter);
});
document.getElementById('prev-chapter').addEventListener('click', () => {
if (currentChapter > 1) {
currentChapter--;
updateChapterDisplay();
updateNavigationButtons();
}
});
async function generateChapter(topic, previousChapter = '') {
const loadingSpinner = document.querySelector('.loading-spinner');
const storyContainer = document.querySelector('.story-container');
loadingSpinner.style.display = 'flex';
storyContainer.style.display = 'none';
try {
const response = await fetch('/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
topic,
previous_chapter: previousChapter,
chapter_number: currentChapter
}),
});
const data = await response.json();
if (response.ok) {
if (currentChapter === 1) {
allChapters = [];
}
allChapters.push({
number: currentChapter,
content: data.story,
topic: topic
});
document.querySelector('.story-title').textContent = topic;
updateChapterDisplay();
storyContainer.style.display = 'block';
updateNavigationButtons();
window.scrollTo({
top: storyContainer.offsetTop - 20,
behavior: 'smooth'
});
} else {
alert(data.error || 'Failed to generate story');
}
} catch (error) {
alert('An error occurred while generating the story');
} finally {
loadingSpinner.style.display = 'none';
}
}
function updateChapterDisplay() {
const chaptersContainer = document.querySelector('.chapters-list');
chaptersContainer.innerHTML = '';
allChapters.forEach((chapter, index) => {
const chapterDiv = document.createElement('div');
chapterDiv.className = 'chapter-content' + (index + 1 === currentChapter ? ' active' : '');
chapterDiv.style.display = index + 1 === currentChapter ? 'block' : 'none';
chapterDiv.innerHTML = formatChapter(chapter.content, index + 1);
chaptersContainer.appendChild(chapterDiv);
});
document.getElementById('current-chapter').textContent = currentChapter;
}
function updateNavigationButtons() {
const prevButton = document.getElementById('prev-chapter');
const nextButton = document.getElementById('next-chapter');
prevButton.disabled = currentChapter === 1;
nextButton.disabled = false;
}
function formatChapter(content, chapterNum) {
return content
.replace(/\n/g, '<br>')
.replace(/<chapter>/g, `<div class="chapter-section">`)
.replace(/<\/chapter>/g, '</div>')
.replace(/<chapter_number>(.*?)<\/chapter_number>/g, `<h4 class="chapter-title">Chapter ${chapterNum}</h4>`)
.replace(/<chapter_summary>(.*?)<\/chapter_summary>/g, '<div class="chapter-summary">$1</div>')
.replace(/<narrative_hook>(.*?)<\/narrative_hook>/g, '<div class="narrative-hook">$1</div>')
.replace(/<content_warning>(.*?)<\/content_warning>/g, '<div class="content-warning"><i class="fas fa-exclamation-triangle"></i> Content Warning: $1</div>');
}
</script>
</body>
</html>