feat: implement interactive knowledge graph visualization and AI-driven graph optimization dashboard
This commit is contained in:
@@ -17,7 +17,13 @@ const Dashboard = () => {
|
||||
const learnDone = storage.get(`user:${currentUser?.id}:week:${weekNumber}:learn_done`, false);
|
||||
const testResult = getTestResult(currentUser?.id, weekNumber);
|
||||
|
||||
const leaderboard = storage.get('leaderboard:current', []).sort((a, b) => b.points - a.points);
|
||||
const allUsers = storage.get('users:registry', []);
|
||||
const nonAdminIds = allUsers.filter(u => u.role !== 'admin').map(u => u.id);
|
||||
|
||||
const leaderboard = storage.get('leaderboard:current', [])
|
||||
.filter(u => nonAdminIds.includes(u.userId))
|
||||
.sort((a, b) => b.points - a.points);
|
||||
|
||||
const top3 = leaderboard.slice(0, 3);
|
||||
const myRank = leaderboard.findIndex(u => u.userId === currentUser?.id) + 1;
|
||||
const myPoints = leaderboard.find(u => u.userId === currentUser?.id)?.points || 0;
|
||||
|
||||
@@ -19,9 +19,12 @@ const Leaderboard = () => {
|
||||
useEffect(() => {
|
||||
// Re-evaluate badges before displaying
|
||||
let data = storage.get('leaderboard:current', []);
|
||||
|
||||
// Supplement with users that haven't scored yet
|
||||
const allUsers = storage.get('users:registry', []);
|
||||
|
||||
// Filter out admins from the leaderboard entirely
|
||||
const nonAdminIds = allUsers.filter(u => u.role !== 'admin').map(u => u.id);
|
||||
data = data.filter(entry => nonAdminIds.includes(entry.userId));
|
||||
|
||||
const userMap = new Map(data.map(u => [u.userId, u]));
|
||||
|
||||
allUsers.forEach(user => {
|
||||
|
||||
@@ -185,14 +185,14 @@ const Leren = () => {
|
||||
}
|
||||
|
||||
// ── Overview ──────────────────────────────────────────────
|
||||
const otherTopics = allTopics.filter(t => t.id !== assignedTopic?.id);
|
||||
const otherTopics = allTopics.filter(t => t.id !== assignedTopic?.id && t.type !== 'fact');
|
||||
|
||||
return (
|
||||
<div className="p-4 md:p-8 max-w-5xl mx-auto pb-24 md:pb-8 animate-in fade-in duration-300">
|
||||
<div className="mb-10">
|
||||
<h1 className="text-3xl md:text-4xl font-bold text-teal mb-3">Learning Station</h1>
|
||||
<p className="text-fg-muted text-lg">
|
||||
You must complete at least 1 topic per week. Feel free to explore more or create your own!
|
||||
You must complete at least 1 topic per week. Feel free to explore more from the library!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -229,27 +229,7 @@ const Leren = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Create Custom Topic */}
|
||||
<div className="mb-12">
|
||||
<h2 className="text-xl font-bold mb-4">Explore Something New</h2>
|
||||
<Card className="border border-bg-warm bg-paper">
|
||||
<form onSubmit={handleCreateCustom} className="flex flex-col md:flex-row gap-4">
|
||||
<div className="flex-1">
|
||||
<Input
|
||||
placeholder="What do you want to learn about today? (e.g. Advanced Git Workflows)"
|
||||
value={customTopicQuery}
|
||||
onChange={e => setCustomTopicQuery(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit" disabled={!customTopicQuery.trim() || isLoading} className="flex-shrink-0">
|
||||
<Plus size={18} className="mr-2" /> Generate Topic
|
||||
</Button>
|
||||
</form>
|
||||
<p className="text-xs text-fg-muted mt-3 flex items-center gap-1">
|
||||
<BookOpen size={12}/> The AI will instantly build a new learning module for anything you type.
|
||||
</p>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Other Available Topics */}
|
||||
{otherTopics.length > 0 && (
|
||||
|
||||
Reference in New Issue
Block a user