edgellm / frontend /src /pages /Assistants.tsx
wu981526092's picture
Restructure features: separate Assistants and Community from Model Catalog
1c47f1e
raw
history blame
9.88 kB
import { useState, useEffect } from 'react'
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import {
Bot,
MessageSquare,
Trash2,
Share,
Plus,
Sparkles
} from 'lucide-react'
export function Assistants() {
const [savedAssistants, setSavedAssistants] = useState<any[]>([])
useEffect(() => {
loadSavedAssistants()
}, [])
const loadSavedAssistants = () => {
try {
const assistants = JSON.parse(localStorage.getItem('savedAssistants') || '[]')
setSavedAssistants(assistants)
} catch (error) {
console.error('Failed to load assistants:', error)
}
}
const loadAssistant = (assistant: any) => {
localStorage.setItem('loadAssistantConfig', JSON.stringify(assistant))
window.location.href = '/playground'
}
const deleteAssistant = (assistantId: string) => {
const updatedAssistants = savedAssistants.filter(a => a.id !== assistantId)
setSavedAssistants(updatedAssistants)
localStorage.setItem('savedAssistants', JSON.stringify(updatedAssistants))
}
const shareMyAssistant = (assistant: any) => {
alert(`"${assistant.name}" has been shared to the community! (This is a demo - in production, it would be submitted for review.)`)
}
const createNewAssistant = () => {
window.location.href = '/playground'
}
return (
<div className="min-h-screen bg-background">
{/* Header */}
<div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="max-w-6xl mx-auto p-6">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-8 h-8 bg-purple-600 rounded-lg flex items-center justify-center">
<Bot className="h-5 w-5 text-white" />
</div>
<div>
<h1 className="text-2xl font-bold">My Assistants</h1>
<p className="text-sm text-muted-foreground">
Manage your custom AI assistants and configurations
</p>
</div>
</div>
<Button onClick={createNewAssistant} className="flex items-center gap-2">
<Plus className="h-4 w-4" />
Create New Assistant
</Button>
</div>
</div>
</div>
<div className="flex-1 p-6">
<div className="max-w-6xl mx-auto space-y-6">
{/* Info Card */}
<Card className="bg-purple-50 border-purple-200">
<CardContent className="pt-6">
<div className="flex items-start gap-3">
<Sparkles className="h-5 w-5 text-purple-600 mt-0.5" />
<div>
<h3 className="font-medium text-purple-900">Custom AI Assistants</h3>
<p className="text-sm text-purple-700 mt-1">
Create specialized AI assistants by configuring models, prompts, and parameters in the Playground.
Save different configurations for various tasks and workflows.
</p>
</div>
</div>
</CardContent>
</Card>
{/* Assistants Grid */}
{savedAssistants.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{savedAssistants.map((assistant) => (
<AssistantCard
key={assistant.id}
assistant={assistant}
onUse={() => loadAssistant(assistant)}
onDelete={() => deleteAssistant(assistant.id)}
onShare={() => shareMyAssistant(assistant)}
/>
))}
</div>
) : (
<Card className="text-center py-16">
<Bot className="h-16 w-16 mx-auto text-muted-foreground mb-6" />
<h3 className="text-xl font-medium mb-3">No assistants yet</h3>
<p className="text-muted-foreground mb-6 max-w-md mx-auto">
Create your first AI assistant by configuring parameters and prompts in the Playground,
then saving your configuration for future use.
</p>
<Button onClick={createNewAssistant} size="lg" className="flex items-center gap-2 mx-auto">
<Plus className="h-5 w-5" />
Create Your First Assistant
</Button>
</Card>
)}
{/* Stats Cards */}
{savedAssistants.length > 0 && (
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<Card>
<CardContent className="pt-6">
<div className="flex items-center justify-between">
<div>
<div className="text-2xl font-bold text-purple-600">
{savedAssistants.length}
</div>
<div className="text-sm text-muted-foreground">Total Assistants</div>
</div>
<Bot className="h-8 w-8 text-purple-600" />
</div>
</CardContent>
</Card>
<Card>
<CardContent className="pt-6">
<div className="flex items-center justify-between">
<div>
<div className="text-2xl font-bold text-blue-600">
{new Set(savedAssistants.map(a => a.model)).size}
</div>
<div className="text-sm text-muted-foreground">Models Used</div>
</div>
<MessageSquare className="h-8 w-8 text-blue-600" />
</div>
</CardContent>
</Card>
<Card>
<CardContent className="pt-6">
<div className="flex items-center justify-between">
<div>
<div className="text-2xl font-bold text-green-600">
{savedAssistants.filter(a => a.createdAt &&
new Date(a.createdAt) > new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
).length}
</div>
<div className="text-sm text-muted-foreground">Created This Week</div>
</div>
<Sparkles className="h-8 w-8 text-green-600" />
</div>
</CardContent>
</Card>
</div>
)}
</div>
</div>
</div>
)
}
// Assistant Card Component
function AssistantCard({
assistant,
onUse,
onDelete,
onShare
}: {
assistant: any
onUse: () => void
onDelete: () => void
onShare: () => void
}) {
return (
<Card className="hover:shadow-lg transition-all duration-200 hover:-translate-y-1">
<CardHeader className="pb-3">
<div className="flex items-start justify-between">
<div className="flex-1">
<CardTitle className="text-base flex items-center gap-2">
<Bot className="h-4 w-4 text-purple-600" />
{assistant.name}
</CardTitle>
<p className="text-sm text-muted-foreground mt-1">
{assistant.description || 'No description provided'}
</p>
</div>
<div className="flex gap-1">
<Button
variant="ghost"
size="sm"
onClick={onShare}
className="text-blue-600 hover:text-blue-700 hover:bg-blue-50"
title="Share to community"
>
<Share className="h-4 w-4" />
</Button>
<Button
variant="ghost"
size="sm"
onClick={onDelete}
className="text-red-500 hover:text-red-600 hover:bg-red-50"
title="Delete assistant"
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
</div>
</CardHeader>
<CardContent className="space-y-4">
{/* Configuration Details */}
<div className="grid grid-cols-2 gap-3 text-xs">
<div className="bg-gray-50 rounded p-2">
<span className="font-medium text-gray-600">Model:</span>
<p className="text-gray-800 truncate">{assistant.model}</p>
</div>
<div className="bg-gray-50 rounded p-2">
<span className="font-medium text-gray-600">Temperature:</span>
<p className="text-gray-800">{assistant.temperature}</p>
</div>
<div className="bg-gray-50 rounded p-2">
<span className="font-medium text-gray-600">Max Tokens:</span>
<p className="text-gray-800">{assistant.maxTokens}</p>
</div>
<div className="bg-gray-50 rounded p-2">
<span className="font-medium text-gray-600">Created:</span>
<p className="text-gray-800">{new Date(assistant.createdAt).toLocaleDateString()}</p>
</div>
</div>
{/* System Prompt Preview */}
{assistant.systemPrompt && (
<div className="bg-blue-50 rounded p-2">
<span className="text-xs font-medium text-blue-700">System Prompt:</span>
<p className="text-xs text-blue-600 mt-1 line-clamp-2">
{assistant.systemPrompt}
</p>
</div>
)}
{/* Action Button */}
<Button onClick={onUse} className="w-full flex items-center gap-2">
<MessageSquare className="h-4 w-4" />
Use Assistant
</Button>
</CardContent>
</Card>
)
}