Spaces:
Sleeping
Sleeping
File size: 6,350 Bytes
8fe50ee | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | 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>
);
}
|