Spaces:
Sleeping
Sleeping
| "use client" | |
| import { useState, ComponentType } from 'react' | |
| import FileUpload from './FileUpload' | |
| import { | |
| Box, | |
| Container, | |
| Typography, | |
| TextField, | |
| Button, | |
| CircularProgress, | |
| Paper, | |
| Fade, | |
| } from '@mui/material' | |
| import QuestionAnswerIcon from '@mui/icons-material/QuestionAnswer' | |
| import { motion } from 'framer-motion' | |
| interface Document { | |
| text: string | |
| } | |
| const MotionContainer = motion(Container as any) | |
| const MotionPaper = motion(Paper as any) | |
| export default function QASystem() { | |
| const [query, setQuery] = useState('') | |
| const [answer, setAnswer] = useState('') | |
| const [loading, setLoading] = useState(false) | |
| const [documents, setDocuments] = useState<Document[]>([]) | |
| const handleDocumentsLoaded = (newDocuments: Document[]) => { | |
| setDocuments(newDocuments) | |
| } | |
| const handleSubmit = async (e: React.FormEvent) => { | |
| e.preventDefault() | |
| if (documents.length === 0) { | |
| alert('Please upload some documents first') | |
| return | |
| } | |
| setLoading(true) | |
| try { | |
| const response = await fetch('/api/qa', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ query, documents }), | |
| }) | |
| const data = await response.json() | |
| setAnswer(data.answer) | |
| } catch (error) { | |
| console.error('Error:', error) | |
| setAnswer('Failed to get answer. Please try again.') | |
| } finally { | |
| setLoading(false) | |
| } | |
| } | |
| return ( | |
| <Box | |
| sx={{ | |
| minHeight: '100vh', | |
| background: 'linear-gradient(135deg, #f6f8fc 0%, #f0f4f8 100%)', | |
| py: 8 | |
| }} | |
| > | |
| <MotionContainer | |
| maxWidth="lg" | |
| initial={{ opacity: 0, y: 20 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| transition={{ duration: 0.5 }} | |
| > | |
| <Box sx={{ textAlign: 'center', mb: 8 }}> | |
| <Typography | |
| variant="h1" | |
| component="h1" | |
| sx={{ | |
| mb: 3, | |
| fontSize: { xs: '2rem', md: '3rem' }, | |
| fontWeight: 800, | |
| background: 'linear-gradient(135deg, #2563eb 0%, #7c3aed 100%)', | |
| backgroundClip: 'text', | |
| WebkitBackgroundClip: 'text', | |
| color: 'transparent', | |
| textShadow: '0 2px 10px rgba(37, 99, 235, 0.1)', | |
| }} | |
| > | |
| AI Document Assistant | |
| </Typography> | |
| <Typography | |
| variant="h6" | |
| sx={{ | |
| color: 'text.secondary', | |
| maxWidth: '600px', | |
| mx: 'auto', | |
| lineHeight: 1.6 | |
| }} | |
| > | |
| Upload your documents and get instant, AI-powered answers to your questions | |
| </Typography> | |
| </Box> | |
| <MotionPaper | |
| elevation={0} | |
| initial={{ opacity: 0, y: 20 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| transition={{ duration: 0.5, delay: 0.2 }} | |
| sx={{ | |
| p: { xs: 3, md: 5 }, | |
| mb: 4, | |
| border: '1px solid', | |
| borderColor: 'grey.100', | |
| backgroundColor: 'rgba(255, 255, 255, 0.9)', | |
| backdropFilter: 'blur(10px)', | |
| borderRadius: 3, | |
| boxShadow: '0 4px 20px rgba(0, 0, 0, 0.05)', | |
| }} | |
| > | |
| <FileUpload onDocumentsLoaded={handleDocumentsLoaded} /> | |
| <Box component="form" onSubmit={handleSubmit} sx={{ mt: 4 }}> | |
| <TextField | |
| fullWidth | |
| multiline | |
| rows={3} | |
| label="What would you like to know?" | |
| value={query} | |
| onChange={(e) => setQuery(e.target.value)} | |
| sx={{ | |
| mb: 3, | |
| '& .MuiOutlinedInput-root': { | |
| backgroundColor: 'white', | |
| borderRadius: 2, | |
| boxShadow: '0 2px 8px rgba(0, 0, 0, 0.05)', | |
| } | |
| }} | |
| variant="outlined" | |
| /> | |
| <Button | |
| fullWidth | |
| type="submit" | |
| disabled={loading || documents.length === 0} | |
| variant="contained" | |
| size="large" | |
| sx={{ | |
| py: 2, | |
| background: 'linear-gradient(135deg, #2563eb 0%, #7c3aed 100%)', | |
| borderRadius: 2, | |
| transition: 'all 0.3s ease', | |
| '&:hover': { | |
| transform: 'translateY(-2px)', | |
| boxShadow: '0 6px 20px rgba(37, 99, 235, 0.2)', | |
| background: 'linear-gradient(135deg, #1d4ed8 0%, #6d28d9 100%)', | |
| }, | |
| '&:disabled': { | |
| background: '#e2e8f0', | |
| color: '#94a3b8', | |
| } | |
| }} | |
| startIcon={loading ? <CircularProgress size={20} color="inherit" /> : <QuestionAnswerIcon />} | |
| > | |
| {loading ? 'Processing...' : 'Ask Question'} | |
| </Button> | |
| </Box> | |
| </MotionPaper> | |
| <Fade in={!!answer}> | |
| <MotionPaper | |
| elevation={0} | |
| initial={{ opacity: 0, y: 20 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| transition={{ duration: 0.5 }} | |
| sx={{ | |
| p: { xs: 3, md: 5 }, | |
| border: '1px solid', | |
| borderColor: 'grey.100', | |
| backgroundColor: 'rgba(255, 255, 255, 0.9)', | |
| backdropFilter: 'blur(10px)', | |
| borderRadius: 3, | |
| boxShadow: '0 4px 20px rgba(0, 0, 0, 0.05)', | |
| }} | |
| > | |
| <Typography | |
| variant="h6" | |
| sx={{ | |
| mb: 3, | |
| fontWeight: 700, | |
| color: 'text.primary', | |
| fontSize: '1.25rem', | |
| }} | |
| > | |
| Answer | |
| </Typography> | |
| <Box | |
| sx={{ | |
| p: 4, | |
| backgroundColor: '#f8fafc', | |
| borderRadius: 2, | |
| border: '1px solid', | |
| borderColor: 'grey.100', | |
| }} | |
| > | |
| <Typography sx={{ | |
| color: 'text.secondary', | |
| lineHeight: 1.8, | |
| fontSize: '1.1rem' | |
| }}> | |
| {answer} | |
| </Typography> | |
| </Box> | |
| </MotionPaper> | |
| </Fade> | |
| </MotionContainer> | |
| </Box> | |
| ) | |
| } |