cryogenic22's picture
Create frontend/src/App.js
1a776d4 verified
import React, { useState, useEffect } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Avatar } from 'lucide-react';
// AI Tutor Avatar Component
const TutorAvatar = ({ state = 'neutral', speaking = false }) => {
const [isBlinking, setIsBlinking] = useState(false);
useEffect(() => {
const blinkInterval = setInterval(() => {
setIsBlinking(true);
setTimeout(() => setIsBlinking(false), 200);
}, Math.random() * 4000 + 2000);
return () => clearInterval(blinkInterval);
}, []);
return (
<div className="flex justify-center items-center p-4">
<svg
viewBox="0 0 100 100"
className="w-32 h-32 transition-transform duration-300 hover:scale-110"
>
{/* Avatar face */}
<circle cx="50" cy="50" r="45" className="fill-blue-500" />
{/* Eyes */}
{isBlinking ? (
<g>
<line x1="30" y1="40" x2="40" y2="40" stroke="white" strokeWidth="3" />
<line x1="60" y1="40" x2="70" y2="40" stroke="white" strokeWidth="3" />
</g>
) : (
<g>
<circle cx="35" cy="40" r="5" fill="white" />
<circle cx="65" cy="40" r="5" fill="white" />
</g>
)}
{/* Mouth based on state */}
<path
d={
state === 'happy'
? 'M 30 60 Q 50 80 70 60'
: state === 'thinking'
? 'M 30 65 Q 50 65 70 65'
: 'M 30 60 Q 50 70 70 60'
}
stroke="white"
fill="none"
strokeWidth="3"
className={speaking ? 'animate-bounce' : ''}
/>
</svg>
</div>
);
};
// Chat Message Component
const ChatMessage = ({ message, role }) => (
<div className={`flex ${role === 'user' ? 'justify-end' : 'justify-start'} mb-4`}>
<div className={`max-w-[80%] rounded-lg p-3 ${
role === 'user' ? 'bg-blue-500 text-white' : 'bg-gray-100'
}`}>
{message}
</div>
</div>
);
// Learning Module Component
const LearningModule = ({ module, onComplete }) => (
<Card className="mb-4">
<CardHeader>
<CardTitle>{module.name}</CardTitle>
</CardHeader>
<CardContent>
<div className="prose dark:prose-invert">
<div className="mb-4">
<h4 className="font-semibold">Introduction</h4>
<p>{module.content.introduction}</p>
</div>
<div className="mb-4">
<h4 className="font-semibold">Key Points</h4>
<ul>
{module.content.key_points.map((point, idx) => (
<li key={idx}>{point}</li>
))}
</ul>
</div>
<div className="mb-4">
<h4 className="font-semibold">Examples</h4>
<ul>
{module.content.examples.map((example, idx) => (
<li key={idx}>{example}</li>
))}
</ul>
</div>
<div className="mb-4">
<h4 className="font-semibold">Practice Problems</h4>
<ol>
{module.content.practice_problems.map((problem, idx) => (
<li key={idx}>{problem}</li>
))}
</ol>
</div>
<button
onClick={onComplete}
className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600 transition"
>
Mark as Complete
</button>
</div>
</CardContent>
</Card>
);
// Main App Component
const App = () => {
const [activeTab, setActiveTab] = useState('learning');
const [messages, setMessages] = useState([]);
const [userInput, setUserInput] = useState('');
const [tutorState, setTutorState] = useState('neutral');
const [selectedPath, setSelectedPath] = useState(null);
// Simulated learning paths data (would come from API)
const learningPaths = {
'physics_mechanics': {
name: 'Classical Mechanics',
// ... rest of the data structure
},
'ai_fundamentals': {
name: 'AI Fundamentals',
// ... rest of the data structure
}
};
const handleSendMessage = async () => {
if (!userInput.trim()) return;
// Add user message
setMessages(prev => [...prev, { role: 'user', content: userInput }]);
setTutorState('thinking');
try {
// API call to get AI response
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: userInput })
});
const data = await response.json();
// Add AI response
setMessages(prev => [...prev, { role: 'assistant', content: data.response }]);
setTutorState('happy');
} catch (error) {
console.error('Error:', error);
setTutorState('neutral');
}
setUserInput('');
};
return (
<div className="min-h-screen bg-gray-50">
<header className="bg-white shadow-sm">
<div className="max-w-7xl mx-auto px-4 py-4">
<h1 className="text-2xl font-bold text-gray-900">🎓 EduAI Platform</h1>
</div>
</header>
<main className="max-w-7xl mx-auto px-4 py-6">
<Tabs value={activeTab} onValueChange={setActiveTab}>
<TabsList>
<TabsTrigger value="learning">📚 Learning Paths</TabsTrigger>
<TabsTrigger value="tutor">🤖 AI Tutor</TabsTrigger>
<TabsTrigger value="playground">💻 Code Playground</TabsTrigger>
</TabsList>
<TabsContent value="learning">
{/* Learning Paths Content */}
<div className="grid grid-cols-1 gap-6">
{Object.entries(learningPaths).map(([id, path]) => (
<Card key={id}>
<CardHeader>
<CardTitle>{path.name}</CardTitle>
</CardHeader>
<CardContent>
{/* Add learning path content */}
</CardContent>
</Card>
))}
</div>
</TabsContent>
<TabsContent value="tutor">
{/* AI Tutor Content */}
<div className="flex flex-col h-[600px]">
<TutorAvatar state={tutorState} />
<div className="flex-1 overflow-y-auto mb-4 space-y-4">
{messages.map((msg, idx) => (
<ChatMessage key={idx} {...msg} />
))}
</div>
<div className="flex gap-2">
<input
type="text"
value={userInput}
onChange={(e) => setUserInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && handleSendMessage()}
placeholder="Ask your question..."
className="flex-1 p-2 border rounded"
/>
<button
onClick={handleSendMessage}
className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
>
Send
</button>
</div>
</div>
</TabsContent>
<TabsContent value="playground">
{/* Code Playground Content */}
<Card>
<CardContent>
<textarea
className="w-full h-64 font-mono p-4 border rounded"
placeholder="Write your Python code here..."
/>
<button className="mt-4 bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">
Run Code
</button>
</CardContent>
</Card>
</TabsContent>
</Tabs>
</main>
</div>
);
};
export default App;