Study_RAG_Final / index.html
Asalun's picture
Upload 4 files
0c86a5d verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Study RAG Assistant</title>
<style>
:root {
--primary: #2563EB;
--primary-hover: #1D4ED8;
--bg-body: #F3F4F6;
--bg-white: #FFFFFF;
--text-main: #1F2937;
--text-muted: #6B7280;
--border: #E5E7EB;
--success: #10B981;
--warning: #F59E0B;
--error: #EF4444;
--font-main: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
--font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
}
* { box-sizing: border-box; }
body { margin: 0; font-family: var(--font-main); background: var(--bg-body); color: var(--text-main); height: 100vh; display: flex; flex-direction: column; overflow: hidden; }
header {
height: 60px; background: var(--bg-white); border-bottom: 1px solid var(--border);
display: flex; align-items: center; justify-content: space-between; padding: 0 20px;
box-shadow: 0 1px 2px rgba(0,0,0,0.05); z-index: 10;
}
.brand { font-weight: 700; font-size: 18px; color: var(--primary); display: flex; align-items: center; gap: 8px; }
.header-controls { display: flex; gap: 20px; align-items: center; }
.control-group { display: flex; align-items: center; gap: 8px; font-size: 13px; }
select, input[type="number"] {
padding: 4px 8px; border: 1px solid var(--border); border-radius: 4px; font-size: 13px; background: var(--bg-white);
}
.stats-pill {
background: #EEF2FF; color: var(--primary); padding: 4px 12px; border-radius: 99px; font-size: 12px; font-weight: 600;
}
.app-container { display: flex; flex: 1; overflow: hidden; }
aside {
width: 280px; background: var(--bg-white); border-right: 1px solid var(--border);
display: flex; flex-direction: column;
}
.upload-zone {
margin: 15px; padding: 20px; border: 2px dashed var(--border); border-radius: 8px;
text-align: center; color: var(--text-muted); font-size: 13px; cursor: pointer; transition: 0.2s;
}
.upload-zone:hover { border-color: var(--primary); background: #F9FAFB; }
.file-list { flex: 1; overflow-y: auto; padding: 0 15px; }
.file-item {
display: flex; align-items: center; padding: 10px; border-radius: 6px; margin-bottom: 4px;
border: 1px solid transparent; cursor: pointer;
}
.file-item:hover { background: #F9FAFB; }
.file-icon { width: 32px; height: 32px; background: #EFF6FF; color: var(--primary); border-radius: 4px; display: flex; align-items: center; justify-content: center; margin-right: 10px; flex-shrink: 0; }
.file-info { flex: 1; min-width: 0; }
.file-name { font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.file-meta { display: flex; align-items: center; gap: 6px; margin-top: 2px; }
.status-badge { font-size: 10px; padding: 2px 6px; border-radius: 4px; font-weight: 600; }
.status-ready { background: #D1FAE5; color: #065F46; }
.status-indexing { background: #DBEAFE; color: #1E40AF; }
.status-error { background: #FEE2E2; color: #991B1B; }
.file-actions { opacity: 0; transition: 0.2s; }
.file-item:hover .file-actions { opacity: 1; }
.btn-icon { background: none; border: none; cursor: pointer; color: var(--text-muted); padding: 2px; }
.btn-icon:hover { color: var(--text-main); }
.sidebar-footer { padding: 15px; border-top: 1px solid var(--border); }
.toggle-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; font-size: 13px; }
.btn-glossary { width: 100%; padding: 8px; background: var(--bg-body); border: 1px solid var(--border); border-radius: 6px; text-align: left; font-size: 13px; display: flex; justify-content: space-between; cursor: pointer; }
main { flex: 1; display: flex; flex-direction: column; background: #fff; position: relative; }
.tabs { display: flex; border-bottom: 1px solid var(--border); background: var(--bg-white); padding: 0 20px; }
.tab-btn {
padding: 15px 20px; background: none; border: none; border-bottom: 2px solid transparent; font-size: 14px; font-weight: 500; color: var(--text-muted); cursor: pointer;
}
.tab-btn.active { color: var(--primary); border-bottom-color: var(--primary); }
.tab-btn:hover { color: var(--text-main); }
.tab-content { display: none; flex: 1; overflow: hidden; flex-direction: column; }
.tab-content.active { display: flex; }
.chat-area { flex: 1; padding: 20px; overflow-y: auto; background: #FAFAFA; display: flex; flex-direction: column; gap: 20px; }
.message { max-width: 80%; display: flex; flex-direction: column; gap: 6px; }
.message.user { align-self: flex-end; align-items: flex-end; }
.message.ai { align-self: flex-start; align-items: flex-start; }
.bubble {
padding: 12px 16px; border-radius: 12px; font-size: 14px; line-height: 1.5; box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}
.user .bubble { background: var(--primary); color: white; border-bottom-right-radius: 2px; }
.ai .bubble { background: white; border: 1px solid var(--border); border-bottom-left-radius: 2px; }
.input-area {
padding: 20px; background: white; border-top: 1px solid var(--border);
}
.quick-actions { display: flex; gap: 8px; margin-bottom: 10px; overflow-x: auto; padding-bottom: 5px; }
.pill { padding: 4px 12px; background: #EFF6FF; color: var(--primary); border-radius: 99px; font-size: 12px; border: 1px solid #BFDBFE; cursor: pointer; white-space: nowrap; }
.pill:hover { background: #DBEAFE; }
.chat-input-wrapper { display: flex; gap: 10px; }
textarea { flex: 1; padding: 10px; border: 1px solid var(--border); border-radius: 8px; resize: none; height: 50px; font-family: inherit; }
.btn-primary { background: var(--primary); color: white; border: none; padding: 0 20px; border-radius: 8px; font-weight: 600; cursor: pointer; }
.btn-primary:hover { background: var(--primary-hover); }
.chat-controls { display: flex; justify-content: space-between; align-items: center; margin-top: 8px; }
.toggle-label { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted); cursor: pointer; }
.citation-group { margin-top: 8px; width: 100%; border-top: 1px solid #f0f0f0; padding-top: 8px; }
.citation-trigger { font-size: 11px; color: var(--text-muted); cursor: pointer; display: flex; align-items: center; gap: 4px; }
.citation-trigger:hover { text-decoration: underline; color: var(--primary); }
.citation-details { background: #F8FAFC; border: 1px solid #E2E8F0; padding: 8px; border-radius: 6px; font-size: 12px; margin-top: 4px; font-family: var(--font-mono); color: #334155; display: none; }
.citation-details.open { display: block; }
.source-tag { color: var(--primary); font-weight: 600; cursor: pointer; }
.source-tag:hover { text-decoration: underline; }
.action-buttons { display: flex; gap: 8px; margin-top: 8px; }
.btn-sm { font-size: 11px; padding: 4px 10px; border: 1px solid var(--border); background: white; border-radius: 4px; cursor: pointer; }
.btn-sm:hover { border-color: var(--primary); color: var(--primary); }
.notes-toolbar { padding: 15px 20px; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; background: #fff; }
.notes-content { flex: 1; padding: 40px; overflow-y: auto; max-width: 800px; margin: 0 auto; width: 100%; }
.notes-topic { font-size: 18px; font-weight: 700; margin-bottom: 15px; margin-top: 30px; color: var(--text-main); padding-bottom: 5px; border-bottom: 2px solid var(--primary); display: inline-block; }
.notes-bullet { margin-bottom: 8px; line-height: 1.6; font-size: 15px; display: flex; gap: 8px; }
.citation-ref { font-size: 10px; background: #E5E7EB; padding: 1px 4px; border-radius: 4px; color: var(--text-muted); margin-top: 3px; white-space: nowrap; }
.quiz-settings { padding: 20px; background: #F9FAFB; border-bottom: 1px solid var(--border); display: flex; gap: 20px; flex-wrap: wrap; align-items: center; }
.quiz-area { flex: 1; padding: 40px; overflow-y: auto; display: flex; justify-content: center; }
.quiz-card { width: 100%; max-width: 700px; background: white; border: 1px solid var(--border); border-radius: 12px; padding: 30px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); }
.modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); display: none; justify-content: center; align-items: center; z-index: 100; }
.modal { background: white; width: 800px; height: 80vh; border-radius: 12px; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1); }
.modal-header { padding: 15px 20px; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; background: #F9FAFB; }
.modal-body { flex: 1; padding: 20px; overflow-y: auto; font-family: var(--font-mono); font-size: 13px; }
</style>
</head>
<body>
<header>
<div class="brand">Study RAG Assistant</div>
<div class="header-controls">
<div class="control-group">
<span>Model:</span>
<select><option>GPT-4o</option><option>Claude 3.5 Sonnet</option></select>
</div>
<div class="control-group">
<span>Chunk:</span>
<input type="number" value="512" style="width: 60px">
<span>Overlap:</span>
<input type="number" value="50" style="width: 50px">
</div>
<div class="stats-pill">4 Files β€’ 1,240 Chunks β€’ Indexed 2m ago</div>
</div>
</header>
<div class="app-container">
<aside>
<div class="upload-zone" onclick="alert('Mock Upload: Files added to queue.')">
Drag & Drop <br>.ipynb or .pdf
</div>
<div class="file-list">
<div class="file-item">
<div class="file-icon">PDF</div>
<div class="file-info">
<div class="file-name">Deep_Learning_Lec1.pdf</div>
<div class="file-meta">
<span class="status-badge status-ready">Ready</span>
</div>
</div>
<input type="checkbox" checked style="margin-left: 8px;">
</div>
<div class="file-item">
<div class="file-icon">NB</div>
<div class="file-info">
<div class="file-name">Neural_Nets_Practice.ipynb</div>
<div class="file-meta">
<span class="status-badge status-ready">Ready</span>
</div>
</div>
<input type="checkbox" checked style="margin-left: 8px;">
</div>
<div class="file-item">
<div class="file-icon">PDF</div>
<div class="file-info">
<div class="file-name">Stats_Review.pdf</div>
<div class="file-meta">
<span class="status-badge status-indexing">Indexing...</span>
</div>
</div>
<input type="checkbox" checked style="margin-left: 8px;">
</div>
</div>
<div class="sidebar-footer">
<div class="toggle-row">
<label>Show Selected Only</label>
<input type="checkbox">
</div>
<button class="btn-glossary" onclick="alert('Glossary Drawer would open here.')">
<span>πŸ“– Memory / Glossary</span>
<span>β€Ί</span>
</button>
</div>
</aside>
<main>
<div class="tabs">
<button class="tab-btn active" onclick="switchTab('chat', event)">Chat</button>
<button class="tab-btn" onclick="switchTab('notes', event)">Notes</button>
<button class="tab-btn" onclick="switchTab('quiz', event)">Quiz</button>
</div>
<div id="tab-chat" class="tab-content active">
<div class="chat-area" id="chat-container">
<div class="message ai">
<div class="bubble">
Hi! I've indexed your documents. Ask me to explain concepts, generate a quiz, or summarize topics.
</div>
</div>
</div>
<div class="input-area">
<div class="quick-actions">
<div class="pill" onclick="setInput('Explain backpropagation like I\\'m 5')">Explain Like I'm 5</div>
<div class="pill" onclick="setInput('Give me 3 code examples of RNNs')">Give Code Examples</div>
<div class="pill" onclick="setInput('What are the key differences between CNN and RNN?')">Compare Concepts</div>
</div>
<div class="chat-input-wrapper">
<textarea id="chat-input" placeholder="Ask a question about your files..."></textarea>
<button class="btn-primary" onclick="sendMessage()">Ask</button>
</div>
<div class="chat-controls">
<label class="toggle-label">
<input type="checkbox" checked> Strictly Grounded (No Guessing)
</label>
</div>
</div>
</div>
<div id="tab-notes" class="tab-content">
<div class="notes-toolbar">
<button class="btn-primary" onclick="alert('Mock: regenerate notes')">Regenerate Notes</button>
<div style="display:flex; gap:10px; align-items:center;">
<span>Format:</span>
<select><option>Bullet Notes</option><option>Cornell Notes</option><option>Outline</option></select>
<button class="btn-sm" onclick="alert('Mock export')">Export MD</button>
</div>
</div>
<div class="notes-content">
<div class="notes-topic">1. Introduction to Neural Networks</div>
<div class="notes-bullet"><span>β€’</span><div>Neural networks are computing systems inspired by biological neural networks.<div class="citation-ref">[Deep_Learning_Lec1.pdf - pg 2]</div></div></div>
<div class="notes-topic">2. Backpropagation</div>
<div class="notes-bullet"><span>β€’</span><div>Backpropagation computes gradients of the loss w.r.t. weights.<div class="citation-ref">[Deep_Learning_Lec1.pdf - pg 14]</div></div></div>
</div>
</div>
<div id="tab-quiz" class="tab-content">
<div class="quiz-settings">
<div class="control-group">
<label>Questions:</label>
<input type="range" min="5" max="50" value="10" oninput="this.nextElementSibling.innerText = this.value">
<span>10</span>
</div>
<div class="control-group">
<label>Type:</label>
<select><option>Multiple Choice</option><option>True/False</option><option>Code Reading</option></select>
</div>
<button class="btn-primary" style="margin-left:auto;" onclick="alert('Mock: generate quiz')">Generate Quiz</button>
</div>
<div class="quiz-area">
<div class="quiz-card">
<div class="q-text">Mock quiz question will show here.</div>
</div>
</div>
</div>
</main>
</div>
<script>
function switchTab(tabId, evt) {
document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active'));
document.querySelectorAll('.tab-btn').forEach(el => el.classList.remove('active'));
document.getElementById('tab-' + tabId).classList.add('active');
if (evt && evt.target) evt.target.classList.add('active');
}
function setInput(text) {
document.getElementById('chat-input').value = text;
}
function sendMessage() {
const input = document.getElementById('chat-input');
const text = input.value;
if (!text.trim()) return;
const container = document.getElementById('chat-container');
const userMsg = document.createElement('div');
userMsg.className = 'message user';
userMsg.innerHTML = `<div class="bubble">${text}</div>`;
container.appendChild(userMsg);
input.value = '';
setTimeout(() => {
const aiMsg = document.createElement('div');
aiMsg.className = 'message ai';
aiMsg.innerHTML = `<div class="bubble">Mock response (backend not connected yet).</div>`;
container.appendChild(aiMsg);
container.scrollTop = container.scrollHeight;
}, 400);
}
</script>
</body>
</html>