EduHelp / index.html
shukdevdatta123's picture
Update index.html
8b0c7f6 verified
raw
history blame
23.7 kB
<!DOCTYPE html>
<html lang="en" data-bs-theme="light">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Educational Assistant Pro</title>
<!-- Bootstrap 5 -->
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-c7DF2uX692G1LB+AU6CtQbmu6Ubfbdr6FLllSVEW9v56MZPPiBYkoQ7RZ2hFOTg1"
crossorigin="anonymous"
/>
<!-- Animate.css -->
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
/>
<!-- AOS -->
<link
href="https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.css"
rel="stylesheet"
/>
<!-- Font Awesome -->
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
/>
<!-- Google Fonts -->
<link
href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&family=Montserrat:wght@700;800;900&display=swap"
rel="stylesheet"
/>
<style>
:root {
--primary: #4361ee;
--primary-dark: #3a56d4;
--secondary: #06d6a0;
--accent: #ef476f;
--light: #f8f9fa;
--dark: #212529;
--white: #ffffff;
--border-radius: 12px;
--box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
--transition: all 0.3s ease-in-out;
}
body {
font-family: 'Poppins', sans-serif;
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
min-height: 100vh;
padding-bottom: 3rem;
}
.btn {
border-radius: 50px;
padding: 0.5rem 1.5rem;
font-weight: 500;
transition: var(--transition);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.btn-primary {
background: var(--primary);
border-color: var(--primary);
}
.btn-primary:hover, .btn-primary:focus {
background: var(--primary-dark);
border-color: var(--primary-dark);
transform: translateY(-3px);
box-shadow: 0 6px 10px rgba(67, 97, 238, 0.3);
}
.btn-success {
background: var(--secondary);
border-color: var(--secondary);
}
.btn-success:hover, .btn-success:focus {
background: #05c08e;
border-color: #05c08e;
transform: translateY(-3px);
box-shadow: 0 6px 10px rgba(6, 214, 160, 0.3);
}
.btn-outline-primary {
color: var(--primary);
border-color: var(--primary);
}
.btn-outline-primary:hover {
background: var(--primary);
color: white;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(67, 97, 238, 0.3);
}
.card {
border: none;
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
overflow: hidden;
transition: var(--transition);
background: rgba(255, 255, 255, 0.9);
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
}
.form-control, .form-select {
border-radius: 8px;
padding: 0.75rem 1rem;
border: 1px solid #e2e8f0;
transition: var(--transition);
}
.form-control:focus, .form-select:focus {
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.2);
}
.navbar {
padding: 1rem 1.5rem;
background: rgba(255, 255, 255, 0.9) !important;
backdrop-filter: blur(10px);
}
.navbar-brand {
font-family: 'Montserrat', sans-serif;
font-weight: 800;
color: var(--primary) !important;
letter-spacing: -0.5px;
}
.offcanvas {
border-radius: 0 20px 20px 0;
}
.offcanvas-header {
background-color: var(--primary);
color: white;
padding: 1.5rem;
}
.offcanvas-header h5 {
font-weight: 600;
font-family: 'Montserrat', sans-serif;
}
.offcanvas-body {
padding: 1.5rem;
}
.offcanvas-body ol {
counter-reset: item;
list-style-type: none;
padding-left: 0;
}
.offcanvas-body ol li {
position: relative;
padding-left: 2.5rem;
margin-bottom: 1.25rem;
counter-increment: item;
}
.offcanvas-body ol li:before {
content: counter(item);
position: absolute;
left: 0;
top: -2px;
width: 28px;
height: 28px;
background: var(--primary);
color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 0.875rem;
}
.offcanvas-body ul {
list-style-type: none;
padding-left: 0.5rem;
margin-top: 0.75rem;
}
.offcanvas-body ul li {
position: relative;
padding-left: 1.5rem;
margin-bottom: 0.5rem;
}
.offcanvas-body ul li:before {
content: "";
position: absolute;
left: 0;
top: 8px;
width: 8px;
height: 8px;
background: var(--secondary);
border-radius: 50%;
}
.hero {
position: relative;
height: 400px;
background: linear-gradient(135deg, rgba(67, 97, 238, 0.9) 0%, rgba(47, 73, 194, 0.9) 100%), url('https://images.unsplash.com/photo-1488190211105-8b0e65b80b4e?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80') center/cover no-repeat;
border-radius: 0 0 50px 50px;
overflow: hidden;
margin-bottom: 3rem;
}
.hero::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100px;
background: linear-gradient(to top, rgba(0,0,0,0.2), transparent);
}
.hero-content {
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
padding: 0 3rem;
position: relative;
z-index: 1;
}
.hero h1 {
font-family: 'Montserrat', sans-serif;
font-weight: 800;
font-size: 3.5rem;
color: white;
margin-bottom: 1rem;
text-shadow: 0 4px 8px rgba(0,0,0,0.3);
}
.hero p {
color: rgba(255, 255, 255, 0.9);
font-size: 1.25rem;
max-width: 600px;
margin-bottom: 2rem;
}
/* Animated Shapes */
.shapes {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
z-index: 0;
}
.shape {
position: absolute;
opacity: 0.3;
}
.shape-1 {
top: 20%;
left: 10%;
width: 80px;
height: 80px;
background: var(--secondary);
border-radius: 40% 60% 70% 30% / 40% 50% 60% 50%;
animation: float1 8s infinite alternate;
}
.shape-2 {
top: 60%;
right: 10%;
width: 60px;
height: 60px;
background: var(--accent);
border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%;
animation: float2 9s infinite alternate;
}
.shape-3 {
bottom: 10%;
left: 20%;
width: 70px;
height: 70px;
background: white;
border-radius: 50% 50% 20% 80% / 25% 80% 20% 75%;
animation: float3 7s infinite alternate;
}
@keyframes float1 {
0% {
transform: translateY(0) rotate(0deg);
}
100% {
transform: translateY(-30px) rotate(180deg);
}
}
@keyframes float2 {
0% {
transform: translateY(0) rotate(0deg);
}
100% {
transform: translateY(40px) rotate(-180deg);
}
}
@keyframes float3 {
0% {
transform: translateY(0) rotate(0deg);
}
100% {
transform: translateY(-20px) rotate(90deg);
}
}
/* Card Custom Styling */
.card-title {
color: var(--primary);
font-weight: 600;
font-size: 1.25rem;
margin-bottom: 1.5rem;
display: flex;
align-items: center;
}
.card-title i {
margin-right: 0.5rem;
color: var(--secondary);
}
.card-body {
padding: 2rem;
}
.form-label {
font-weight: 500;
color: var(--dark);
margin-bottom: 0.5rem;
}
#result {
min-height: 250px;
background: rgba(245, 247, 250, 0.7);
border-radius: 8px;
padding: 1.5rem;
font-size: 0.95rem;
line-height: 1.6;
color: #333;
transition: var(--transition);
}
.badge-container {
display: flex;
gap: 0.75rem;
margin-top: 1rem;
flex-wrap: wrap;
}
.badge {
padding: 0.5rem 1rem;
border-radius: 50px;
font-weight: 500;
font-size: 0.85rem;
}
.badge-primary {
background-color: rgba(67, 97, 238, 0.1);
color: var(--primary);
}
.badge-secondary {
background-color: rgba(6, 214, 160, 0.1);
color: var(--secondary);
}
/* Loading Animation */
.loader {
display: none;
width: 48px;
height: 48px;
border: 5px solid var(--primary);
border-bottom-color: transparent;
border-radius: 50%;
margin: 2rem auto;
animation: rotation 1s linear infinite;
}
@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Feature Icons */
.features {
display: flex;
justify-content: space-around;
margin: 3rem 0;
}
.feature {
text-align: center;
padding: 1rem;
transition: var(--transition);
}
.feature:hover {
transform: translateY(-5px);
}
.feature i {
font-size: 2rem;
color: var(--primary);
margin-bottom: 1rem;
padding: 1rem;
background-color: rgba(67, 97, 238, 0.1);
border-radius: 50%;
width: 4rem;
height: 4rem;
display: flex;
align-items: center;
justify-content: center;
}
.feature h5 {
color: var(--dark);
font-weight: 600;
margin-bottom: 0.5rem;
}
.feature p {
color: #6c757d;
font-size: 0.9rem;
max-width: 200px;
margin: 0 auto;
}
/* Dark Mode Toggle */
.dark-mode-toggle {
position: fixed;
bottom: 2rem;
right: 2rem;
width: 50px;
height: 50px;
border-radius: 50%;
background: var(--primary);
color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
z-index: 1000;
transition: var(--transition);
}
.dark-mode-toggle:hover {
transform: scale(1.1);
}
.dark-mode-toggle i {
font-size: 1.25rem;
}
/* Dark Mode Styles */
[data-bs-theme="dark"] {
--light: #212529;
--dark: #f8f9fa;
}
[data-bs-theme="dark"] body {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
color: var(--dark);
}
[data-bs-theme="dark"] .card {
background: rgba(26, 26, 46, 0.8);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}
[data-bs-theme="dark"] .navbar {
background: rgba(26, 26, 46, 0.9) !important;
}
[data-bs-theme="dark"] .form-control,
[data-bs-theme="dark"] .form-select {
background-color: rgba(255, 255, 255, 0.05);
border-color: rgba(255, 255, 255, 0.1);
color: var(--dark);
}
[data-bs-theme="dark"] #result {
background: rgba(0, 0, 0, 0.2);
color: var(--dark);
}
[data-bs-theme="dark"] .form-label {
color: var(--dark);
}
[data-bs-theme="dark"] .dark-mode-toggle {
background: #ffc107;
}
[data-bs-theme="dark"] .feature i {
background-color: rgba(255, 255, 255, 0.1);
}
[data-bs-theme="dark"] .feature h5 {
color: var(--dark);
}
[data-bs-theme="dark"] .feature p {
color: rgba(255, 255, 255, 0.7);
}
/* Responsive Adjustments */
@media (max-width: 991.98px) {
.hero {
height: 350px;
}
.hero h1 {
font-size: 2.5rem;
}
.features {
flex-wrap: wrap;
}
.feature {
width: 50%;
margin-bottom: 2rem;
}
}
@media (max-width: 767.98px) {
.hero {
height: 300px;
}
.hero h1 {
font-size: 2rem;
}
.hero p {
font-size: 1rem;
}
.feature {
width: 100%;
}
}
/* Progress Bar Animation */
.progress-animation {
width: 100%;
height: 5px;
background: linear-gradient(to right, var(--primary), var(--secondary));
position: fixed;
top: 0;
left: 0;
z-index: 9999;
animation: progress-grow 0.4s ease;
}
@keyframes progress-grow {
0% {
width: 0%;
}
100% {
width: 100%;
}
}
/* Toast Notification Styles */
.toast-container {
position: fixed;
top: 1rem;
right: 1rem;
z-index: 9999;
}
.toast {
opacity: 0;
transform: translateY(-20px);
transition: all 0.3s ease;
max-width: 350px;
}
.toast.show {
opacity: 1;
transform: translateY(0);
}
</style>
</head>
<body>
<!-- Progress Bar Animation (appears during loading) -->
<div class="progress-animation d-none" id="progressBar"></div>
<!-- Toast Notifications Container -->
<div class="toast-container" id="toastContainer"></div>
<!-- Navbar with sidebar toggle -->
<nav class="navbar navbar-light shadow-sm fixed-top">
<div class="container">
<button
class="btn btn-outline-primary"
type="button"
data-bs-toggle="offcanvas"
data-bs-target="#sidebar"
aria-controls="sidebar"
>
<i class="fas fa-bars me-2"></i> Instructions
</button>
<span class="navbar-brand animate__animated animate__fadeIn">
<i class="fas fa-brain me-2"></i> Educational Assistant Pro
</span>
</div>
</nav>
<!-- Offcanvas Sidebar -->
<div
class="offcanvas offcanvas-start"
tabindex="-1"
id="sidebar"
aria-labelledby="sidebarLabel"
>
<div class="offcanvas-header">
<h5 id="sidebarLabel"><i class="fas fa-book-open me-2"></i> How It Works</h5>
<button
type="button"
class="btn-close btn-close-white"
data-bs-dismiss="offcanvas"
aria-label="Close"
></button>
</div>
<div class="offcanvas-body">
<ol>
<li>Enter your OpenAI API key below (securely stored)</li>
<li>Upload a PDF document using the upload button</li>
<li>Select one of our AI-powered tools:
<ul>
<li>Generate Summary - Get a concise overview</li>
<li>Generate Quiz - Create practice questions</li>
<li>Ask a Question - Get specific answers</li>
<li>Generate Study Plan - Create a 7-day curriculum</li>
</ul>
</li>
<li>If asking a question, type it in the field that appears</li>
<li>Click "Generate" and download your personalized result</li>
</ol>
<div class="badge-container">
<span class="badge badge-primary">PDF Processing</span>
<span class="badge badge-secondary">AI-Powered</span>
<span class="badge badge-primary">Study Tools</span>
</div>
</div>
</div>
<!-- Hero Section -->
<section class="hero">
<div class="shapes">
<div class="shape shape-1"></div>
<div class="shape shape-2"></div>
<div class="shape shape-3"></div>
</div>
<div class="hero-content">
<h1 class="animate__animated animate__fadeInUp">Study Smarter, Not Harder</h1>
<p class="animate__animated animate__fadeInUp animate__delay-1s">Transform your learning experience with our AI-powered study assistant. Upload any PDF and get summaries, quizzes, and personalized study plans in seconds.</p>
</div>
</section>
<!-- Feature Icons -->
<div class="container">
<div class="features" data-aos="fade-up" data-aos-delay="200">
<div class="feature">
<i class="fas fa-file-alt"></i>
<h5>Summarize</h5>
<p>Get concise summaries of any document</p>
</div>
<div class="feature">
<i class="fas fa-question-circle"></i>
<h5>Quiz</h5>
<p>Generate practice questions instantly</p>
</div>
<div class="feature">
<i class="fas fa-lightbulb"></i>
<h5>Ask</h5>
<p>Get answers to specific questions</p>
</div>
<div class="feature">
<i class="fas fa-calendar-alt"></i>
<h5>Plan</h5>
<p>Create customized study schedules</p>
</div>
</div>
</div>
<!-- Main Content -->
<div class="container mt-5">
<div class="row g-4">
<!-- Controls Column -->
<div class="col-lg-4" data-aos="fade-right">
<div class="card">
<div class="card-body">
<h5 class="card-title"><i class="fas fa-cogs"></i> Controls</h5>
<div class="mb-4">
<label for="apiKey" class="form-label">OpenAI API Key</label>
<div class="input-group">
<span class="input-group-text bg-light">
<i class="fas fa-key"></i>
</span>
<input
type="password"
class="form-control"
id="apiKey"
placeholder="sk-..."
/>
</div>
<small class="text-muted">Your key is stored locally and never sent to our servers</small>
</div>
<div class="mb-4">
<label for="pdfUpload" class="form-label">Upload PDF</label>
<div class="input-group">
<span class="input-group-text bg-light">
<i class="fas fa-file-pdf"></i>
</span>
<input
class="form-control"
type="file"
id="pdfUpload"
accept="application/pdf"
/>
</div>
</div>
<div class="mb-4">
<label class="form-label">Choose Tool</label>
<select class="form-select" id="optionSelect">
<option value="Generate Summary">Generate Summary</option>
<option value="Generate Quiz">Generate Quiz</option>
<option value="Ask a Question">Ask a Question</option>
<option value="Generate Study Plan">Generate Study Plan</option>
</select>
</div>
<div class="mb-4 d-none" id="questionGroup">
<label for="questionInput" class="form-label">Your Question</label>
<div class="input-group">
<span class="input-group-text bg-light">
<i class="fas fa-question"></i>
</span>
<input
type="text"
class="form-control"
id="questionInput"
placeholder="Type your question..."
/>
</div>
</div>
<div class="d-grid">
<button class="btn btn-primary" id="generateBtn">
<i class="fas fa-magic me-2"></i> Generate
</button>
</div>
</div>
</div>
</div>
<!-- Output Column -->
<div class="col-lg-8" data-aos="fade-left">
<div class="card">
<div class="card-body">
<h5 class="card-title"><i class="fas fa-clipboard-list"></i> Result</h5>
<div class="loader" id="loader"></div>
<div id="result">
<!-- AI response appears here -->
<div class="text-center text-muted">
<i class="fas fa-robot fa-3x mb-3 text-primary opacity-50"></i>
<p>Your results will appear here after generation.</p>
</div>
</div>
<div class="mt-4 text-end">
<button
class="btn btn-success d-none"
id="downloadBtn"
>
<i class="fas fa-download me-2"></i> Download as PDF
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Dark Mode Toggle -->
<div class="dark-mode-toggle" id="darkModeToggle">
<i class="fas fa-sun"></i>
</div>
<!-- Scripts -->
<!-- Bootstrap JS & dependencies -->
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-E6mRv7/D+K0PtPpK0O1J3DRgIh+tp3loX3f7ogf20+RskmIOrthyxU2048gASBZd"
crossorigin="anonymous"
></script>
<!-- PDF.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.min.js"></script>
<!-- jsPDF -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
<!-- AOS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.js"></script>
<script>
// Initialize animations
AOS.init({
duration: 800,
easing: 'ease-in-out',
once: true
});
// Set up PDF.js
const pdfjsLib = window['pdfjs-dist/build/pdf'];
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.worker.min.js';
let pdfText = '';
let pdfName = '';
const resultDiv = document.getElementById('result');
const loader = document.getElementById('loader');
const progressBar = document.getElementById('progressBar');
// Add padding to body for fixed navbar
document.body.style.paddingTop = '76px';
// Show/hide question input
document.getElementById('optionSelect').addEventListener('change', (e) => {
const questionGroup = document.getElementById('questionGroup');
if (e.target.value === 'Ask a Question') {
questionGroup.classList.remove('d-none');
questionGroup.classList.add('animate__animated', 'animate__fadeIn');
} else {
questionGroup.classList.add('d-none');
}
});
// Toast notification function
function showToast(message, type = 'success') {
const toastContainer = document.getElementById('toastContainer');
const toastId = 'toast-' + Date.now();
const bgColor = type === 'success' ? 'bg-success' : type === 'error' ? 'bg-danger' : 'bg-primary';
const icon = type === 'success' ? 'fas fa-check-circle' : type === 'error' ? 'fas fa-exclamation-circle' : 'fas fa-info-circle';
const toastHTML = `
<div class="toast ${bgColor} text-white" id="${toastId}">
<div class="toast-header">
<i class="${icon} me-2"></i>
<strong class="me-auto">Educational Assistant</strong>
<small>Just now</small>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
${message}
</div>
</div>
`;
toastContainer.insertAdjacentHTML('beforeend', toastHTML);
const toastElement = document.getElementById(toastId);
toastElement.classList.add('show');
setTimeout(() => {
toastElement.classList.remove('show');
setTimeout(() => toastElement.remove(), 300);
}, 5000);
}
// Load PDF and extract text
document.getElementById('pdfUpload').addEventListener('change', async (e) => {
const file = e.target.files[0];
if (!file) return;
pdfName = file.name.replace('.pdf', '');
// Show loading state
resultDiv.innerHTML = `<div class="text-center text-muted">