Spaces:
Sleeping
Sleeping
| import { Card, CardContent } from "@/components/ui/card"; | |
| import { Button } from "@/components/ui/button"; | |
| import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; | |
| import { Input } from "@/components/ui/input"; | |
| import { Textarea } from "@/components/ui/textarea"; | |
| import { Badge } from "@/components/ui/badge"; | |
| import { Avatar, AvatarFallback } from "@/components/ui/avatar"; | |
| import { MessageSquareIcon, UploadIcon, BrainIcon, FolderIcon, BookOpenIcon, ClockIcon, SendIcon } from "lucide-react"; | |
| import { useState } from "react"; | |
| const GoogleAPI = 'AIzaSyAMqFn0dNAoS75Zo4GUdcD99reEIM2IvzU' | |
| export default function TeachingAssistantDashboard() { | |
| const [message, setMessage] = useState(""); | |
| const [chatHistory, setChatHistory] = useState([]); | |
| const handleSend = async () => { | |
| if (message.trim() === "") return; | |
| const newEntry = { sender: "user", content: message }; | |
| setChatHistory([...chatHistory, newEntry]); | |
| setMessage(""); | |
| try { | |
| const response = await fetch( | |
| `https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${GoogleAPI}`, | |
| { | |
| method: "POST", | |
| headers: { | |
| "Content-Type": "application/json" | |
| }, | |
| body: JSON.stringify({ | |
| contents: [{ parts: [{ text: message }] }] | |
| }) | |
| } | |
| ); | |
| const data = await response.json(); | |
| console.log("Gemini raw response:", data); | |
| // More robust extraction of AI message | |
| let aiMessage = ""; | |
| if (data.candidates && data.candidates.length > 0) { | |
| const candidate = data.candidates[0]; | |
| // Try nested parts | |
| if (candidate.content?.parts) { | |
| aiMessage = candidate.content.parts.map(p => p.text).join("\n"); | |
| } | |
| // Fallback to simple text | |
| else if (candidate.content?.text) { | |
| aiMessage = candidate.content.text; | |
| } | |
| // Fallback to candidate text | |
| else if (candidate.text) { | |
| aiMessage = candidate.text; | |
| } | |
| } | |
| // Last resort: stringify whole response | |
| if (!aiMessage) { | |
| aiMessage = JSON.stringify(data); | |
| } | |
| setChatHistory(prev => [...prev, { sender: "ai", content: aiMessage }] ); | |
| } catch (error) { | |
| console.error("Error connecting to Gemini API:", error); | |
| setChatHistory(prev => [...prev, { sender: "ai", content: "[Error connecting to Gemini API]" }]); | |
| } | |
| }; | |
| return ( | |
| <div className="grid grid-cols-6 gap-4 p-4 bg-background text-foreground"> | |
| {/* Sidebar */} | |
| <div className="col-span-1 bg-muted rounded-2xl p-4 space-y-4 shadow"> | |
| <h2 className="text-xl font-semibold">AI Teaching Assistant</h2> | |
| <Button variant="ghost" className="w-full justify-start"><UploadIcon className="mr-2" />Upload</Button> | |
| <Button variant="ghost" className="w-full justify-start"><FolderIcon className="mr-2" />Folders</Button> | |
| <Button variant="ghost" className="w-full justify-start"><BookOpenIcon className="mr-2" />Knowledge Map</Button> | |
| <Button variant="ghost" className="w-full justify-start"><MessageSquareIcon className="mr-2" />Chat Assistant</Button> | |
| <Button variant="ghost" className="w-full justify-start"><ClockIcon className="mr-2" />Review</Button> | |
| </div> | |
| {/* Main Content */} | |
| <div className="col-span-5 space-y-4"> | |
| {/* Upload Section */} | |
| <Card> | |
| <CardContent className="p-4"> | |
| <h3 className="text-lg font-semibold mb-2">📂 Upload Documents</h3> | |
| <Input type="file" multiple /> | |
| <p className="text-sm text-muted-foreground mt-1">Supported: PDF, PPT, TXT</p> | |
| </CardContent> | |
| </Card> | |
| {/* Auto-Summarization */} | |
| <Card> | |
| <CardContent className="p-4"> | |
| <h3 className="text-lg font-semibold mb-2">🧠 Auto-Summarization & Tags</h3> | |
| <div className="flex gap-2 flex-wrap"> | |
| <Badge variant="secondary">Constructivism</Badge> | |
| <Badge variant="secondary">Cognitive Load</Badge> | |
| <Badge variant="secondary">Assessment Design</Badge> | |
| <Badge variant="secondary">Multimedia Principles</Badge> | |
| </div> | |
| <Textarea className="mt-2" placeholder="Generated summary will appear here..." rows={3} /> | |
| </CardContent> | |
| </Card> | |
| {/* Folder View */} | |
| <Card> | |
| <CardContent className="p-4"> | |
| <h3 className="text-lg font-semibold mb-2">📁 Knowledge Folders</h3> | |
| <ul className="list-disc list-inside space-y-1"> | |
| <li>Instructional Theories (4 docs)</li> | |
| <li>Learner Characteristics (3 docs)</li> | |
| <li>Design Models (5 docs)</li> | |
| <li>Assessment Methods (2 docs)</li> | |
| </ul> | |
| </CardContent> | |
| </Card> | |
| {/* Chat Assistant */} | |
| <Card> | |
| <CardContent className="p-4 space-y-3"> | |
| <h3 className="text-lg font-semibold">🤖 Chat with AI Assistant</h3> | |
| <div className="space-y-2 max-h-40 overflow-y-auto bg-muted p-2 rounded"> | |
| {chatHistory.map((entry, index) => ( | |
| <div key={index} className={`text-sm ${entry.sender === "user" ? "text-right" : "text-left"}`}> | |
| <span className="inline-block px-3 py-1 bg-background rounded shadow">{entry.content}</span> | |
| </div> | |
| ))} | |
| </div> | |
| <div className="flex items-center gap-2"> | |
| <Input | |
| className="flex-grow" | |
| placeholder="Ask about any concept..." | |
| value={message} | |
| onChange={(e) => setMessage(e.target.value)} | |
| onKeyDown={(e) => e.key === 'Enter' && handleSend()} | |
| /> | |
| <Button onClick={handleSend} variant="default"><SendIcon size={16} /></Button> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| {/* Spaced Repetition */} | |
| <Card> | |
| <CardContent className="p-4"> | |
| <h3 className="text-lg font-semibold mb-2">⏳ Review Reminders</h3> | |
| <p className="text-sm">Next review cycle: <strong>Tomorrow (2 docs)</strong> based on Ebbinghaus curve</p> | |
| </CardContent> | |
| </Card> | |
| </div> | |
| </div> | |
| ); | |
| } | |