Levi / frontend /src /components /Dashboard.tsx
Manish Kumar
chnage model
0a7f861
Raw
History Blame Contribute Delete
10.8 kB
import type React from 'react';
import {
MessageSquare, Code, FileText, ShieldAlert, List, RefreshCw,
Cpu, HardDrive, Database
} from 'lucide-react';
import type { ModelInfo } from '../types';
interface DashboardProps {
modelInfo: ModelInfo | null;
setActiveTab: (tab: string) => void;
createNewConversation: (title?: string) => void;
sendMessage: (msg: string) => void;
}
export const Dashboard: React.FC<DashboardProps> = ({
modelInfo,
setActiveTab,
createNewConversation,
sendMessage,
}) => {
const quickActions = [
{ id: 'chat', title: 'AI Chat', desc: 'Chat with your AI assistant', icon: MessageSquare },
{ id: 'playground', title: 'Playground', desc: 'Run code and experiments', icon: Code },
{ id: 'explain', title: 'Explain Code', desc: 'Get detailed explanations', icon: FileText, prompt: 'Explain how this code block functions and list edge cases:\n\n' },
{ id: 'debug', title: 'Debug Code', desc: 'Find and fix issues', icon: ShieldAlert, prompt: 'Find bugs and syntax errors in this code block:\n\n' },
{ id: 'tests', title: 'Generate Tests', desc: 'Create unit tests', icon: List, prompt: 'Write comprehensive unit tests for this code block:\n\n' },
{ id: 'refactor', title: 'Refactor Code', desc: 'Improve code quality', icon: RefreshCw, prompt: 'Refactor this code block to improve readability and complexity:\n\n' },
];
const recentConversations = [
{ title: 'Python async queue implementation', time: '2 mins ago' },
{ title: 'React custom hook optimization', time: '28 mins ago' },
{ title: 'SQL query performance tuning', time: '1 hour ago' },
{ title: 'Debug memory leak in Node.js', time: '3 hours ago' },
{ title: 'Implement auth with JWT', time: '5 hours ago' },
];
const examplePrompts = [
{ label: 'Explain this code', prompt: 'Explain the runtime complexity of this function:\n\n', icon: FileText },
{ label: 'Write a Python function', prompt: 'Write a Python function to check if a string is a palindrome.', icon: Code },
{ label: 'Debug this error', prompt: 'Explain how to fix this TypeError exception:\n\n', icon: ShieldAlert },
{ label: 'Optimize this SQL query', prompt: 'Optimize this slow SQL query using proper indexes:\n\n', icon: Database },
{ label: 'Generate unit tests', prompt: 'Generate unit tests for a standard user authentication class.', icon: List },
];
const handleActionClick = (action: typeof quickActions[0]) => {
if (action.id === 'chat') {
createNewConversation();
setActiveTab('chat');
} else if (action.id === 'playground') {
setActiveTab('playground');
} else if (action.prompt) {
createNewConversation(action.title);
setActiveTab('chat');
setTimeout(() => {
sendMessage(action.prompt || '');
}, 100);
}
};
const handlePromptClick = (label: string, promptText: string) => {
createNewConversation(label);
setActiveTab('chat');
setTimeout(() => {
sendMessage(promptText);
}, 100);
};
const modelName = modelInfo?.model_name || 'SmolLM2-360M-Instruct-Q4_K_M';
return (
<div className="flex-1 overflow-y-auto bg-[#090810] p-6 space-y-6 font-sans max-w-[1400px] mx-auto w-full">
{/* Welcome Row with status badges */}
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4 border-b border-[#1d1b2e] pb-5 select-none">
<div className="space-y-1">
<h1 className="text-2xl font-bold tracking-tight text-white">Welcome back, Developer 👋</h1>
<p className="text-xs text-[#9d99b3]">Your AI Coding Assistant is ready to help you build, debug and ship faster.</p>
</div>
<div className="flex items-center gap-3">
<div className="flex items-center gap-2 px-3.5 py-1.5 bg-[#131121] border border-[#1d1b2e] rounded-xl text-xs">
<span className="text-[#9d99b3]">LOCAL MODEL:</span>
<span className="font-semibold font-mono text-primary">{modelName}</span>
</div>
<div className="flex items-center gap-2 px-3.5 py-1.5 bg-[#131121] border border-[#1d1b2e] rounded-xl text-xs">
<span className="text-[#9d99b3]">SYSTEM STATUS:</span>
<span className="flex items-center gap-1.5 font-semibold text-emerald-500">
<span className="h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse"></span>
Healthy
</span>
</div>
</div>
</div>
{/* Grid: System Status */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 select-none">
{/* Model Status Card */}
<div className="bg-[#131121] border border-[#1d1b2e] p-5 rounded-2xl flex flex-col gap-4 min-h-[110px] hover:border-primary/20 transition-all">
<div className="flex items-center justify-between">
<span className="text-[10px] font-bold text-[#9d99b3] uppercase tracking-wider">Model</span>
<div className="p-1.5 bg-emerald-500/10 rounded-lg text-emerald-500">
<Cpu size={14} />
</div>
</div>
<div className="space-y-1 flex-1 flex flex-col justify-end">
<h2 className="text-sm font-bold truncate text-white">{modelName}</h2>
<p className="text-[10px] text-emerald-500 font-semibold">Local Inference</p>
</div>
</div>
{/* Memory Card */}
<div className="bg-[#131121] border border-[#1d1b2e] p-5 rounded-2xl flex flex-col gap-4 min-h-[110px] hover:border-primary/20 transition-all">
<div className="flex items-center justify-between">
<span className="text-[10px] font-bold text-[#9d99b3] uppercase tracking-wider">Model Size</span>
<div className="p-1.5 bg-blue-500/10 rounded-lg text-blue-500">
<HardDrive size={14} />
</div>
</div>
<div className="space-y-1 flex-1 flex flex-col justify-end">
<h2 className="text-sm font-bold text-white">~500 MB</h2>
<p className="text-[10px] text-[#58556f]">Q4_K_M quantized</p>
</div>
</div>
{/* Context Card */}
<div className="bg-[#131121] border border-[#1d1b2e] p-5 rounded-2xl flex flex-col gap-4 min-h-[110px] hover:border-primary/20 transition-all">
<div className="flex items-center justify-between">
<span className="text-[10px] font-bold text-[#9d99b3] uppercase tracking-wider">Context</span>
<div className="p-1.5 bg-primary/10 rounded-lg text-primary">
<RefreshCw size={14} />
</div>
</div>
<div className="space-y-1 flex-1 flex flex-col justify-end">
<h2 className="text-xl font-bold text-white">512</h2>
<p className="text-[10px] text-[#58556f]">Tokens context window</p>
</div>
</div>
</div>
{/* Main Layout Split */}
<div className="grid grid-cols-1 lg:grid-cols-5 gap-6">
{/* Left: Quick Actions Grid */}
<div className="lg:col-span-3 space-y-4">
<div className="select-none">
<h3 className="text-sm font-bold text-white">Quick Actions</h3>
<p className="text-[10px] text-[#9d99b3] mt-0.5">Choose a tool to get started</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{quickActions.map((action, idx) => {
const Icon = action.icon;
return (
<button
key={idx}
onClick={() => handleActionClick(action)}
className="flex items-center gap-3.5 p-4 bg-[#131121] hover:bg-[#1c1a30] border border-[#1d1b2e] hover:border-primary/40 rounded-xl text-left transition-all duration-200 cursor-pointer shadow-sm group"
>
<div className="p-2 bg-primary/10 rounded-lg text-primary glow-primary shrink-0 group-hover:scale-105 transition-transform">
<Icon size={15} />
</div>
<div className="space-y-0.5 min-w-0">
<h4 className="font-bold text-xs text-white group-hover:text-primary transition-colors">{action.title}</h4>
<p className="text-[10px] text-[#9d99b3] leading-relaxed truncate">{action.desc}</p>
</div>
</button>
);
})}
</div>
</div>
{/* Right: Recent Conversations */}
<div className="lg:col-span-2 space-y-4 flex flex-col">
<div className="flex items-center justify-between select-none">
<h3 className="text-sm font-bold text-white">Recent Conversations</h3>
<button
onClick={() => setActiveTab('chat')}
className="text-[10px] font-bold text-primary hover:underline cursor-pointer"
>
View all
</button>
</div>
<div className="flex-1 bg-[#131121] border border-[#1d1b2e] rounded-2xl overflow-hidden select-none">
{recentConversations.map((conv, idx) => (
<div
key={idx}
className="flex items-center justify-between px-4 py-3 border-b border-[#1d1b2e] last:border-0 hover:bg-[#1c1a30] cursor-pointer transition-colors gap-4"
onClick={() => { createNewConversation(conv.title); setActiveTab('chat'); }}
>
<span className="text-xs font-medium text-[#eae9fc] truncate min-w-0 flex-1">{conv.title}</span>
<span className="text-[10px] text-[#58556f] font-mono shrink-0 whitespace-nowrap">{conv.time}</span>
</div>
))}
</div>
</div>
</div>
{/* Bottom: Example Prompts */}
<div className="space-y-4 pt-2">
<div className="select-none">
<h3 className="text-sm font-bold text-white">Example Prompts</h3>
<p className="text-[10px] text-[#9d99b3] mt-0.5">Try these examples to get started</p>
</div>
<div className="flex flex-wrap gap-3">
{examplePrompts.map((ep, idx) => {
const Icon = ep.icon;
return (
<button
key={idx}
onClick={() => handlePromptClick(ep.label, ep.prompt)}
className="flex items-center gap-2 px-3.5 py-2.5 bg-[#131121] hover:bg-[#1c1a30] border border-[#1d1b2e] hover:border-primary/40 text-xs text-[#eae9fc] font-medium rounded-xl transition-all cursor-pointer shadow-sm"
>
<Icon size={12} className="text-[#9d99b3]" />
<span>{ep.label}</span>
</button>
);
})}
</div>
</div>
</div>
);
};