Emissary List Compact Component
The EmissaryListCompact component (src/components/EmissaryListCompact.tsx) provides a compact list view of AI assistants (emissaries) with their last message previews and relative timestamps.
Overview
This component displays a list of AI assistants in a compact format, showing each assistant’s avatar, name, last message, and timestamp. It includes Firebase integration to fetch recent messages and provides navigation to individual assistant pages.
Key Features
Message Integration
- Fetches the most recent message for each assistant
- Displays message previews with intelligent truncation
- Shows relative timestamps using the RelativeTime component
- Sorts assistants by last message activity
Interactive Interface
- Click any assistant to navigate to their chat page
- Hover effects for better user experience
- Loading states during data fetching
- Graceful handling of assistants with no messages
Visual Design
- Avatar display with fallback initials
- Compact card layout with borders and spacing
- Responsive text truncation
- Clear visual hierarchy
Props Interface
interface EmissaryListCompactProps {
bots: AssistantDisplay[];
currentUser?: any;
onView?: (bot: AssistantDisplay) => void;
}
Data Types
interface BotWithMessage extends AssistantDisplay {
lastMessage?: string;
lastMessageTime?: Date;
}
Implementation Example
// Basic usage with navigation
<EmissaryListCompact
bots={assistantList}
currentUser={currentUser}
/>
// With custom view handler
<EmissaryListCompact
bots={assistantList}
currentUser={currentUser}
onView={(bot) => {
// Custom navigation or modal opening
openAssistantModal(bot);
}}
/>
Key Functionality
Message Fetching
The component automatically fetches the latest message for each assistant:
const fetchLastMessages = async () => {
const updatedBots: BotWithMessage[] = [];
for (const bot of bots) {
try {
// Fetch most recent message using FirebaseService
const messages = await FirebaseService.getMessages(bot.assistantId, 1);
if (messages && messages.length > 0) {
const lastMsg = messages[messages.length - 1];
lastMessage = lastMsg.content || '';
lastMessageTime = lastMsg.timestamp ? new Date(lastMsg.timestamp) : lastMessageTime;
}
} catch (error) {
console.error(`Error fetching messages for bot ${bot.assistantId}:`, error);
}
updatedBots.push({
...bot,
lastMessage,
lastMessageTime
});
}
// Sort by most recent activity
updatedBots.sort((a, b) => (b.lastMessageTime?.getTime() || 0) - (a.lastMessageTime?.getTime() || 0));
setBotsWithMessages(updatedBots);
};
Message Truncation
Intelligent text truncation for long messages:
const truncateMessage = (message: string, maxWords: number = 30): string => {
const words = message.split(' ');
if (words.length <= maxWords) return message;
return words.slice(0, maxWords).join(' ') + '...';
};
Navigation Handling
Flexible navigation with custom or default behavior:
const handleView = (bot: AssistantDisplay) => {
if (onView) {
onView(bot); // Custom handler
} else {
router.push(`/assistant/${bot.assistantId}`); // Default navigation
}
};
UI Structure
Each assistant is displayed in a consistent card format:
<div className="flex items-center space-x-3 p-4 hover:bg-muted/50 transition-colors cursor-pointer rounded-lg border border-border">
<Avatar className="h-12 w-12">
<AvatarImage src={bot.avatar} alt={bot.name} />
<AvatarFallback>{bot.name?.[0] || '?'}</AvatarFallback>
</Avatar>
<div className="flex-1 min-w-0">
<div className="flex items-center justify-between">
<h3 className="font-medium truncate text-base">{bot.name}</h3>
{bot.lastMessageTime && (
<span className="text-xs text-muted-foreground">
<RelativeTime date={bot.lastMessageTime} />
</span>
)}
</div>
{bot.lastMessage ? (
<p className="text-muted-foreground text-sm line-clamp-2">
{truncateMessage(bot.lastMessage)}
</p>
) : (
<p className="text-muted-foreground text-sm italic">No messages yet</p>
)}
</div>
<ChevronRight className="h-4 w-4 text-muted-foreground" />
</div>
Dependencies
@/types- AssistantDisplay type definition@/components/ui/avatar- Avatar component with fallback@/components/RelativeTime- Timestamp formatting@/lib/firebase- Firebase service for message fetchingnext/navigation- Router for navigationlucide-react- ChevronRight icon
State Management
The component manages several states:
botsWithMessages- Enhanced bot data with message informationloading- Loading state during message fetching- Firebase authentication state monitoring
Loading States
Displays a loading spinner while fetching messages:
if (loading) {
return (
<div className="flex items-center justify-center p-8">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
</div>
);
}
Error Handling
- Graceful handling of message fetch failures
- Fallback to assistant creation date when no messages exist
- Console logging for debugging purposes
- No UI disruption on individual assistant errors
Performance Considerations
- Fetches only the most recent message (limit: 1) for each assistant
- Implements proper async/await patterns
- Includes small delays to ensure Firebase initialization
- Sorts results to show most active assistants first
Integration Notes
This component is typically used in:
- Assistant selection interfaces
- Dashboard views showing assistant activity
- Mobile-friendly list layouts
It requires proper Firebase authentication and integrates with the overall assistant management system in the application.