'use client'; /** * Memory Detail * Shows detailed information about a selected memory * including related memories and decay visualization */ import { useMemo } from 'react'; import { Memory, MemoryLink } from '@/types/memory'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { getCategoryColor, getTypeColor } from '@/lib/category-colors'; import { calculateDecayFactor } from '@/lib/position-algorithm'; interface MemoryDetailProps { memory: Memory; links?: MemoryLink[]; memories?: Memory[]; onClose: () => void; onReinforce?: (id: number) => void; onSelectMemory?: (id: number) => void; } // Relationship styling const RELATIONSHIP_STYLES: Record = { references: { color: '#60a5fa', label: 'References', icon: '→' }, extends: { color: '#34d399', label: 'Extends', icon: '⊃' }, contradicts: { color: '#f87171', label: 'Contradicts', icon: '⊗' }, related: { color: '#a78bfa', label: 'Related', icon: '~' }, }; // Get health status based on decay function getHealthStatus(decayFactor: number): { label: string; color: string; bgColor: string } { if (decayFactor > 0.7) { return { label: 'Healthy', color: '#22C55E', bgColor: 'rgba(34, 197, 94, 0.15)' }; } if (decayFactor > 0.4) { return { label: 'Fading', color: '#EAB308', bgColor: 'rgba(234, 179, 8, 0.15)' }; } return { label: 'Critical', color: '#EF4444', bgColor: 'rgba(239, 68, 68, 0.15)' }; } export function MemoryDetail({ memory, links = [], memories = [], onClose, onReinforce, onSelectMemory, }: MemoryDetailProps) { const decayFactor = calculateDecayFactor(memory); const categoryColor = getCategoryColor(memory.category); const typeColor = getTypeColor(memory.type); const healthStatus = getHealthStatus(decayFactor); // Find related memories through links const relatedMemories = useMemo(() => { const related: Array<{ memory: Memory; relationship: string; strength: number; direction: 'from' | 'to'; }> = []; for (const link of links) { if (link.source_id === memory.id) { const target = memories.find(m => m.id === link.target_id); if (target) { related.push({ memory: target, relationship: link.relationship, strength: link.strength, direction: 'to', }); } } else if (link.target_id === memory.id) { const source = memories.find(m => m.id === link.source_id); if (source) { related.push({ memory: source, relationship: link.relationship, strength: link.strength, direction: 'from', }); } } } // Sort by strength return related.sort((a, b) => b.strength - a.strength); }, [memory.id, links, memories]); const formatDate = (dateStr: string) => { const date = new Date(dateStr); return date.toLocaleString(); }; const timeSince = (dateStr: string) => { const date = new Date(dateStr); const now = new Date(); const hours = Math.floor((now.getTime() - date.getTime()) / (1000 * 60 * 60)); if (hours < 1) return 'Just now'; if (hours < 24) return `${hours}h ago`; const days = Math.floor(hours / 24); if (days < 7) return `${days}d ago`; return `${Math.floor(days / 7)}w ago`; }; return (
{memory.title}
{memory.category} {memory.type.replace('_', '-')}
{/* Content */}

Content

{memory.content}

{/* Health Status Banner */}
{healthStatus.label}
{decayFactor > 0.7 ? 'Memory is strong and stable' : decayFactor > 0.4 ? 'Memory is fading - reinforce to preserve' : 'Memory at risk of deletion - reinforce now'}
{/* Metrics */}
Salience
{(memory.salience * 100).toFixed(0)}%
Decay Factor
{(decayFactor * 100).toFixed(0)}%
{/* Access info */}
Access Count {memory.accessCount} times
Last Accessed {timeSince(memory.lastAccessed)}
Created {formatDate(memory.createdAt)}
{/* Related Memories */} {relatedMemories.length > 0 && (

🔗 Related Memories ({relatedMemories.length})

{relatedMemories.map(({ memory: related, relationship, strength, direction }) => { const style = RELATIONSHIP_STYLES[relationship] || RELATIONSHIP_STYLES.related; const relatedCategoryColor = getCategoryColor(related.category); return ( ); })}
)} {/* Tags */} {memory.tags && memory.tags.length > 0 && (

Tags

{memory.tags.map((tag, i) => ( {tag} ))}
)} {/* Actions */}
{onReinforce && ( )}
); }