Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>PDF Whisperer Pro - Chat with your documents</title> | |
| <link rel="icon" type="image/x-icon" href="/static/favicon.ico"> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <style> | |
| :root { | |
| --primary: #4f46e5; | |
| --primary-dark: #4338ca; | |
| --secondary: #f9fafb; | |
| --text: #111827; | |
| --text-light: #6b7280; | |
| } | |
| body { | |
| font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; | |
| } | |
| .pdf-container { | |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); | |
| } | |
| .chat-container { | |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| .message-animation { | |
| animation: fadeIn 0.3s ease; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| #pdf-viewer { | |
| height: calc(100vh - 120px); | |
| background-color: #f3f4f6; | |
| } | |
| #pdf-render { | |
| width: 100%; | |
| height: 100%; | |
| border: none; | |
| } | |
| .upload-btn { | |
| background: linear-gradient(135deg, var(--primary), var(--primary-dark)); | |
| transition: all 0.2s ease; | |
| } | |
| .upload-btn:hover { | |
| transform: translateY(-1px); | |
| box-shadow: 0 4px 6px -1px rgba(79, 70, 229, 0.3); | |
| } | |
| .chat-header { | |
| background: linear-gradient(135deg, var(--primary), var(--primary-dark)); | |
| } | |
| .send-btn { | |
| background: linear-gradient(135deg, var(--primary), var(--primary-dark)); | |
| transition: all 0.2s ease; | |
| } | |
| .send-btn:hover { | |
| transform: translateY(-1px); | |
| box-shadow: 0 4px 6px -1px rgba(79, 70, 229, 0.3); | |
| } | |
| .user-message { | |
| background: var(--primary); | |
| color: white; | |
| border-radius: 1rem 1rem 0 1rem; | |
| } | |
| .assistant-message { | |
| background: var(--secondary); | |
| color: var(--text); | |
| border-radius: 1rem 1rem 1rem 0; | |
| box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); | |
| } | |
| @media (max-width: 768px) { | |
| #pdf-viewer { | |
| height: 50vh; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 h-screen overflow-hidden"> | |
| <div class="flex h-full"> | |
| <!-- PDF Viewer Panel --> | |
| <div id="pdf-panel" class="pdf-container w-1/2 bg-white shadow-lg z-10 relative overflow-hidden border-r border-gray-200"> | |
| <div class="flex justify-between items-center p-4 chat-header text-white"> | |
| <h2 class="text-xl font-semibold">Document Viewer</h2> | |
| <button onclick="togglePDFPanel()" class="p-2 rounded-full hover:bg-opacity-80 transition"> | |
| <i data-feather="chevron-right"></i> | |
| </button> | |
| </div> | |
| <div id="pdf-viewer" class="w-full h-full"> | |
| <object id="pdf-render" type="application/pdf" data="" class="w-full h-full"> | |
| <p>PDF viewer not available. Please download the PDF to view it: <a id="pdf-download-link" href="">Download PDF</a></p> | |
| </object> | |
| </div> | |
| <div class="p-4 bg-gray-100 border-t border-gray-200"> | |
| <input type="file" id="file-upload" accept="application/pdf" class="hidden"> | |
| <label for="file-upload" class="p-3 px-4 text-white rounded-lg shadow-md cursor-pointer flex items-center upload-btn"> | |
| <i data-feather="upload" class="mr-2 w-5 h-5"></i> Upload Document | |
| </label> | |
| </div> | |
| </div> | |
| <!-- Chat Panel --> | |
| <div class="chat-container flex-1 flex flex-col h-full bg-gray-50"> | |
| <div class="flex justify-between items-center p-4 chat-header text-white"> | |
| <div class="flex items-center space-x-3"> | |
| <div class="w-8 h-8 bg-white bg-opacity-20 rounded-full flex items-center justify-center"> | |
| <i data-feather="message-square" class="w-4 h-4"></i> | |
| </div> | |
| <h1 class="text-2xl font-semibold">PDF Whisperer Pro</h1> | |
| </div> | |
| <button id="toggle-pdf-btn" onclick="togglePDFPanel()" class="p-2 rounded-full hover:bg-opacity-80 transition"> | |
| <i data-feather="chevron-left"></i> | |
| </button> | |
| </div> | |
| <div id="chat-messages" class="flex-1 overflow-y-auto p-4 space-y-4"> | |
| <div class="message-animation bg-blue-100 p-4 rounded-lg max-w-3xl"> | |
| <p>Welcome to PDF Whisperer Pro! Upload a PDF to start chatting with your document.</p> | |
| </div> | |
| </div> | |
| <div class="p-4 border-t border-gray-200 bg-white"> | |
| <div class="flex space-x-2"> | |
| <input type="text" id="user-input" placeholder="Ask something about the document..." | |
| class="flex-1 p-3 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white"> | |
| <button onclick="sendMessage()" class="p-3 px-6 text-white rounded-lg flex items-center send-btn"> | |
| <i data-feather="send" class="mr-2"></i> Send | |
| </button> | |
| </div> | |
| <div class="mt-2 text-sm text-gray-500"> | |
| <p class="text-xs">Try asking: "Summarize key points" or "Explain page 3 in simple terms"</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Initialize feather icons | |
| feather.replace(); | |
| // Document loading | |
| document.getElementById('file-upload').addEventListener('change', function(e) { | |
| const file = e.target.files[0]; | |
| if (file.type !== 'application/pdf') { | |
| alert('Please upload a PDF file'); | |
| return; | |
| } | |
| const url = URL.createObjectURL(file); | |
| const pdfViewer = document.getElementById('pdf-render'); | |
| const downloadLink = document.getElementById('pdf-download-link'); | |
| // Create iframe as fallback | |
| if (pdfViewer.tagName === 'OBJECT') { | |
| const iframe = document.createElement('iframe'); | |
| iframe.id = 'pdf-render'; | |
| iframe.src = url; | |
| iframe.className = 'w-full h-full'; | |
| pdfViewer.parentNode.replaceChild(iframe, pdfViewer); | |
| } else { | |
| pdfViewer.src = url; | |
| } | |
| downloadLink.href = url; | |
| downloadLink.download = file.name; | |
| // Add a message about the uploaded document | |
| addMessage(`Document loaded: <strong>${file.name}</strong>. You can now ask questions about this document.`, 'assistant'); | |
| }); | |
| // Toggle PDF panel visibility | |
| function togglePDFPanel() { | |
| const pdfPanel = document.getElementById('pdf-panel'); | |
| const toggleBtn = document.getElementById('toggle-pdf-btn'); | |
| if (pdfPanel.classList.contains('w-1/2')) { | |
| pdfPanel.classList.remove('w-1/2'); | |
| pdfPanel.classList.add('w-0', 'opacity-0'); | |
| toggleBtn.innerHTML = feather.icons['chevron-right'].toSvg(); | |
| } else { | |
| pdfPanel.classList.remove('w-0', 'opacity-0'); | |
| pdfPanel.classList.add('w-1/2'); | |
| toggleBtn.innerHTML = feather.icons['chevron-left'].toSvg(); | |
| } | |
| } | |
| // Chat functionality | |
| function addMessage(content, sender) { | |
| const messagesContainer = document.getElementById('chat-messages'); | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.classList.add('message-animation', 'max-w-3xl', 'p-4', 'w-fit'); | |
| if (sender === 'user') { | |
| messageDiv.classList.add('user-message', 'ml-auto'); | |
| messageDiv.innerHTML = `<p class="text-white">${content}</p>`; | |
| } else { | |
| messageDiv.classList.add('assistant-message'); | |
| messageDiv.innerHTML = `<p class="text-gray-800">${content}</p>`; | |
| } | |
| messagesContainer.appendChild(messageDiv); | |
| messagesContainer.scrollTop = messagesContainer.scrollHeight; | |
| } | |
| function sendMessage() { | |
| const input = document.getElementById('user-input'); | |
| const message = input.value.trim(); | |
| if (message === '') return; | |
| addMessage(message, 'user'); | |
| input.value = ''; | |
| // Simulate AI response (in a real app, this would be an API call) | |
| setTimeout(() => { | |
| const responses = [ | |
| "Based on page 3 of your document, the key points are...", | |
| "The document mentions this concept on page 5.", | |
| "I've analyzed the content and found that...", | |
| "The summary of section 2 suggests that...", | |
| "This appears to be related to the topic discussed on page 7." | |
| ]; | |
| const randomResponse = responses[Math.floor(Math.random() * responses.length)]; | |
| addMessage(randomResponse, 'assistant'); | |
| }, 1000); | |
| } | |
| // Allow sending message with Enter key | |
| document.getElementById('user-input').addEventListener('keypress', function(e) { | |
| if (e.key === 'Enter') { | |
| sendMessage(); | |
| } | |
| }); | |
| // Load a sample PDF on first run (optional) | |
| // For demo purposes, you might want to pre-load a PDF | |
| // loadPDF('sample.pdf'); | |
| </script> | |
| </body> | |
| </html> | |