Spaces:
Sleeping
Sleeping
| import { useState, useRef } from 'react'; | |
| import DocumentProcessor from './DocumentProcessor'; | |
| function Homepage() { | |
| const [hasFile, setHasFile] = useState(false); | |
| const [fileName, setFileName] = useState(''); | |
| const [selectedFile, setSelectedFile] = useState(null); | |
| const [academicBackground, setAcademicBackground] = useState(''); | |
| const [showAbout, setShowAbout] = useState(false); | |
| const [showDocumentProcessor, setShowDocumentProcessor] = useState(false); | |
| const fileRef = useRef(null); | |
| function openFilePicker() { | |
| if (fileRef.current) fileRef.current.click(); | |
| } | |
| function handleFileChange(event) { | |
| const file = event.target.files?.[0]; | |
| if (file) { | |
| setSelectedFile(file); | |
| setHasFile(true); | |
| setFileName(file.name); | |
| setTimeout(() => setShowAbout(true), 250); | |
| } | |
| } | |
| function handleContinue() { | |
| setShowDocumentProcessor(true); | |
| } | |
| // If we're showing the document processor, render it instead of the onboarding | |
| if (showDocumentProcessor) { | |
| return ( | |
| <DocumentProcessor | |
| initialFile={selectedFile} | |
| fileName={fileName} | |
| academicBackground={academicBackground} | |
| /> | |
| ); | |
| } | |
| return ( | |
| <div className="min-h-screen w-full bg-gray-50 text-gray-900 flex items-center justify-center p-6"> | |
| <div className="max-w-4xl w-full"> | |
| <div className="mb-6 flex items-center justify-between"> | |
| <div className="flex items-center gap-3"> | |
| <div className="h-10 w-10 rounded-2xl bg-indigo-500 text-white flex items-center justify-center"> | |
| <svg viewBox='0 0 24 24' className='h-6 w-6'> | |
| <path d='M12 3l7.5 4.5v9L12 21 4.5 16.5v-9L12 3z' fill='currentColor'/> | |
| </svg> | |
| </div> | |
| <div> | |
| <h1 className="text-2xl font-semibold tracking-tight">SocraticAI</h1> | |
| <p className="text-sm text-gray-600">Guided comprehension for complex papers</p> | |
| </div> | |
| </div> | |
| <div className="text-xs text-gray-500">Onboarding Flow</div> | |
| </div> | |
| {!hasFile && !showAbout && ( | |
| <Landing | |
| openFilePicker={openFilePicker} | |
| fileRef={fileRef} | |
| handleFileChange={handleFileChange} | |
| academicBackground={academicBackground} | |
| setAcademicBackground={setAcademicBackground} | |
| /> | |
| )} | |
| {hasFile && showAbout && ( | |
| <About | |
| fileName={fileName} | |
| onContinue={handleContinue} | |
| openFilePicker={openFilePicker} | |
| academicBackground={academicBackground} | |
| /> | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| } | |
| function Landing({ openFilePicker, fileRef, handleFileChange, academicBackground, setAcademicBackground }) { | |
| return ( | |
| <div className="rounded-2xl border border-gray-200 bg-white shadow-lg p-8 md:p-12"> | |
| <div> | |
| <h2 className="text-3xl md:text-4xl font-semibold leading-tight text-gray-900">Welcome to SocraticAI</h2> | |
| <p className="mt-3 text-gray-600"> | |
| Your mentor-like companion for mastering research papers. Upload a paper and we'll turn it into a guided | |
| learning path — with questions, feedback, and visible progress. | |
| </p> | |
| <div className="mt-6"> | |
| <label htmlFor="academic-background" className="block text-sm font-medium text-gray-700 mb-2"> | |
| Describe your academic background | |
| </label> | |
| <p className="text-xs text-gray-500 mb-3"> | |
| This helps us adjust our tutoring AI to adapt to what you already know. | |
| </p> | |
| <textarea | |
| id="academic-background" | |
| value={academicBackground} | |
| onChange={(e) => setAcademicBackground(e.target.value)} | |
| placeholder="e.g., PhD in Computer Science, undergraduate in Physics, working professional in data science..." | |
| className="w-full px-4 py-3 rounded-lg border border-gray-300 text-gray-900 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 resize-none" | |
| rows="3" | |
| /> | |
| </div> | |
| <div className="mt-8"> | |
| <button | |
| onClick={openFilePicker} | |
| className="inline-flex items-center gap-2 rounded-lg px-5 py-3 bg-indigo-500 hover:bg-indigo-600 transition text-white font-medium shadow-lg" | |
| > | |
| <UploadIcon /> Upload a paper (PDF) | |
| </button> | |
| <input | |
| ref={fileRef} | |
| type="file" | |
| accept="application/pdf" | |
| className="hidden" | |
| onChange={handleFileChange} | |
| /> | |
| </div> | |
| <p className="mt-3 text-xs text-gray-500">Your PDF will be processed locally and securely.</p> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| function About({ fileName, onContinue, openFilePicker, academicBackground }) { | |
| return ( | |
| <div className="rounded-2xl border border-gray-200 bg-white shadow-lg p-8 md:p-12"> | |
| <div className="flex items-start gap-4"> | |
| <div className="h-10 w-10 rounded-xl bg-emerald-100 border border-emerald-200 flex items-center justify-center"> | |
| <CheckIcon /> | |
| </div> | |
| <div className="flex-1"> | |
| <h3 className="text-2xl font-semibold text-gray-900">Paper added</h3> | |
| <p className="text-gray-600 mt-1">{fileName}</p> | |
| {academicBackground && ( | |
| <p className="text-gray-500 mt-2 text-sm"> | |
| Background: {academicBackground} | |
| </p> | |
| )} | |
| <p className="mt-4 text-gray-800">Here's how SocraticAI helps you learn deeply:</p> | |
| <ul className="mt-3 text-gray-600 space-y-2 list-disc list-inside"> | |
| <li><span className="font-medium text-gray-800">Automatic inflection points.</span> We flag hypotheses, assumptions, method shifts, and key claims.</li> | |
| <li><span className="font-medium text-gray-800">Guided micro-conversations.</span> Short question/answer loops validate and extend your understanding.</li> | |
| <li><span className="font-medium text-gray-800">Visible progress.</span> Confidence builds as you complete focused checkpoints.</li> | |
| </ul> | |
| <div className="mt-6 flex flex-wrap gap-3"> | |
| <button | |
| onClick={onContinue} | |
| className="rounded-lg px-5 py-3 bg-indigo-500 hover:bg-indigo-600 transition text-white font-medium shadow-lg" | |
| > | |
| Continue | |
| </button> | |
| <button | |
| onClick={openFilePicker} | |
| className="rounded-lg px-5 py-3 bg-gray-100 hover:bg-gray-200 transition text-gray-700 font-medium border border-gray-300" | |
| > | |
| Choose another paper | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| function UploadIcon() { | |
| return ( | |
| <svg viewBox="0 0 24 24" className="h-5 w-5" fill="none" stroke="currentColor" strokeWidth="1.8"> | |
| <path d="M12 16V4m0 0l-4 4m4-4l4 4"/> | |
| <path d="M20 16v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-2"/> | |
| </svg> | |
| ); | |
| } | |
| function CheckIcon() { | |
| return ( | |
| <svg viewBox="0 0 24 24" className="h-5 w-5 text-emerald-600" fill="none" stroke="currentColor" strokeWidth="2"> | |
| <path d="M20 6L9 17l-5-5" /> | |
| </svg> | |
| ); | |
| } | |
| export default Homepage; |