cryogenic22 commited on
Commit
1a776d4
·
verified ·
1 Parent(s): 8ef59a1

Create frontend/src/App.js

Browse files
Files changed (1) hide show
  1. frontend/src/App.js +252 -0
frontend/src/App.js ADDED
@@ -0,0 +1,252 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect } from 'react';
2
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
3
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
4
+ import { Avatar } from 'lucide-react';
5
+
6
+ // AI Tutor Avatar Component
7
+ const TutorAvatar = ({ state = 'neutral', speaking = false }) => {
8
+ const [isBlinking, setIsBlinking] = useState(false);
9
+
10
+ useEffect(() => {
11
+ const blinkInterval = setInterval(() => {
12
+ setIsBlinking(true);
13
+ setTimeout(() => setIsBlinking(false), 200);
14
+ }, Math.random() * 4000 + 2000);
15
+
16
+ return () => clearInterval(blinkInterval);
17
+ }, []);
18
+
19
+ return (
20
+ <div className="flex justify-center items-center p-4">
21
+ <svg
22
+ viewBox="0 0 100 100"
23
+ className="w-32 h-32 transition-transform duration-300 hover:scale-110"
24
+ >
25
+ {/* Avatar face */}
26
+ <circle cx="50" cy="50" r="45" className="fill-blue-500" />
27
+
28
+ {/* Eyes */}
29
+ {isBlinking ? (
30
+ <g>
31
+ <line x1="30" y1="40" x2="40" y2="40" stroke="white" strokeWidth="3" />
32
+ <line x1="60" y1="40" x2="70" y2="40" stroke="white" strokeWidth="3" />
33
+ </g>
34
+ ) : (
35
+ <g>
36
+ <circle cx="35" cy="40" r="5" fill="white" />
37
+ <circle cx="65" cy="40" r="5" fill="white" />
38
+ </g>
39
+ )}
40
+
41
+ {/* Mouth based on state */}
42
+ <path
43
+ d={
44
+ state === 'happy'
45
+ ? 'M 30 60 Q 50 80 70 60'
46
+ : state === 'thinking'
47
+ ? 'M 30 65 Q 50 65 70 65'
48
+ : 'M 30 60 Q 50 70 70 60'
49
+ }
50
+ stroke="white"
51
+ fill="none"
52
+ strokeWidth="3"
53
+ className={speaking ? 'animate-bounce' : ''}
54
+ />
55
+ </svg>
56
+ </div>
57
+ );
58
+ };
59
+
60
+ // Chat Message Component
61
+ const ChatMessage = ({ message, role }) => (
62
+ <div className={`flex ${role === 'user' ? 'justify-end' : 'justify-start'} mb-4`}>
63
+ <div className={`max-w-[80%] rounded-lg p-3 ${
64
+ role === 'user' ? 'bg-blue-500 text-white' : 'bg-gray-100'
65
+ }`}>
66
+ {message}
67
+ </div>
68
+ </div>
69
+ );
70
+
71
+ // Learning Module Component
72
+ const LearningModule = ({ module, onComplete }) => (
73
+ <Card className="mb-4">
74
+ <CardHeader>
75
+ <CardTitle>{module.name}</CardTitle>
76
+ </CardHeader>
77
+ <CardContent>
78
+ <div className="prose dark:prose-invert">
79
+ <div className="mb-4">
80
+ <h4 className="font-semibold">Introduction</h4>
81
+ <p>{module.content.introduction}</p>
82
+ </div>
83
+
84
+ <div className="mb-4">
85
+ <h4 className="font-semibold">Key Points</h4>
86
+ <ul>
87
+ {module.content.key_points.map((point, idx) => (
88
+ <li key={idx}>{point}</li>
89
+ ))}
90
+ </ul>
91
+ </div>
92
+
93
+ <div className="mb-4">
94
+ <h4 className="font-semibold">Examples</h4>
95
+ <ul>
96
+ {module.content.examples.map((example, idx) => (
97
+ <li key={idx}>{example}</li>
98
+ ))}
99
+ </ul>
100
+ </div>
101
+
102
+ <div className="mb-4">
103
+ <h4 className="font-semibold">Practice Problems</h4>
104
+ <ol>
105
+ {module.content.practice_problems.map((problem, idx) => (
106
+ <li key={idx}>{problem}</li>
107
+ ))}
108
+ </ol>
109
+ </div>
110
+
111
+ <button
112
+ onClick={onComplete}
113
+ className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600 transition"
114
+ >
115
+ Mark as Complete
116
+ </button>
117
+ </div>
118
+ </CardContent>
119
+ </Card>
120
+ );
121
+
122
+ // Main App Component
123
+ const App = () => {
124
+ const [activeTab, setActiveTab] = useState('learning');
125
+ const [messages, setMessages] = useState([]);
126
+ const [userInput, setUserInput] = useState('');
127
+ const [tutorState, setTutorState] = useState('neutral');
128
+ const [selectedPath, setSelectedPath] = useState(null);
129
+
130
+ // Simulated learning paths data (would come from API)
131
+ const learningPaths = {
132
+ 'physics_mechanics': {
133
+ name: 'Classical Mechanics',
134
+ // ... rest of the data structure
135
+ },
136
+ 'ai_fundamentals': {
137
+ name: 'AI Fundamentals',
138
+ // ... rest of the data structure
139
+ }
140
+ };
141
+
142
+ const handleSendMessage = async () => {
143
+ if (!userInput.trim()) return;
144
+
145
+ // Add user message
146
+ setMessages(prev => [...prev, { role: 'user', content: userInput }]);
147
+ setTutorState('thinking');
148
+
149
+ try {
150
+ // API call to get AI response
151
+ const response = await fetch('/api/chat', {
152
+ method: 'POST',
153
+ headers: { 'Content-Type': 'application/json' },
154
+ body: JSON.stringify({ message: userInput })
155
+ });
156
+
157
+ const data = await response.json();
158
+
159
+ // Add AI response
160
+ setMessages(prev => [...prev, { role: 'assistant', content: data.response }]);
161
+ setTutorState('happy');
162
+ } catch (error) {
163
+ console.error('Error:', error);
164
+ setTutorState('neutral');
165
+ }
166
+
167
+ setUserInput('');
168
+ };
169
+
170
+ return (
171
+ <div className="min-h-screen bg-gray-50">
172
+ <header className="bg-white shadow-sm">
173
+ <div className="max-w-7xl mx-auto px-4 py-4">
174
+ <h1 className="text-2xl font-bold text-gray-900">🎓 EduAI Platform</h1>
175
+ </div>
176
+ </header>
177
+
178
+ <main className="max-w-7xl mx-auto px-4 py-6">
179
+ <Tabs value={activeTab} onValueChange={setActiveTab}>
180
+ <TabsList>
181
+ <TabsTrigger value="learning">📚 Learning Paths</TabsTrigger>
182
+ <TabsTrigger value="tutor">🤖 AI Tutor</TabsTrigger>
183
+ <TabsTrigger value="playground">💻 Code Playground</TabsTrigger>
184
+ </TabsList>
185
+
186
+ <TabsContent value="learning">
187
+ {/* Learning Paths Content */}
188
+ <div className="grid grid-cols-1 gap-6">
189
+ {Object.entries(learningPaths).map(([id, path]) => (
190
+ <Card key={id}>
191
+ <CardHeader>
192
+ <CardTitle>{path.name}</CardTitle>
193
+ </CardHeader>
194
+ <CardContent>
195
+ {/* Add learning path content */}
196
+ </CardContent>
197
+ </Card>
198
+ ))}
199
+ </div>
200
+ </TabsContent>
201
+
202
+ <TabsContent value="tutor">
203
+ {/* AI Tutor Content */}
204
+ <div className="flex flex-col h-[600px]">
205
+ <TutorAvatar state={tutorState} />
206
+
207
+ <div className="flex-1 overflow-y-auto mb-4 space-y-4">
208
+ {messages.map((msg, idx) => (
209
+ <ChatMessage key={idx} {...msg} />
210
+ ))}
211
+ </div>
212
+
213
+ <div className="flex gap-2">
214
+ <input
215
+ type="text"
216
+ value={userInput}
217
+ onChange={(e) => setUserInput(e.target.value)}
218
+ onKeyPress={(e) => e.key === 'Enter' && handleSendMessage()}
219
+ placeholder="Ask your question..."
220
+ className="flex-1 p-2 border rounded"
221
+ />
222
+ <button
223
+ onClick={handleSendMessage}
224
+ className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
225
+ >
226
+ Send
227
+ </button>
228
+ </div>
229
+ </div>
230
+ </TabsContent>
231
+
232
+ <TabsContent value="playground">
233
+ {/* Code Playground Content */}
234
+ <Card>
235
+ <CardContent>
236
+ <textarea
237
+ className="w-full h-64 font-mono p-4 border rounded"
238
+ placeholder="Write your Python code here..."
239
+ />
240
+ <button className="mt-4 bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">
241
+ Run Code
242
+ </button>
243
+ </CardContent>
244
+ </Card>
245
+ </TabsContent>
246
+ </Tabs>
247
+ </main>
248
+ </div>
249
+ );
250
+ };
251
+
252
+ export default App;