'use client' import { useState, useEffect } from 'react' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' import { Lightbulb, ThumbsUp, ThumbsDown, X, Sparkles, ArrowRight } from 'lucide-react' import { toast } from 'sonner' interface MemoryEchoInsight { id: string note1Id: string note2Id: string note1: { id: string title: string | null content: string } note2: { id: string title: string | null content: string } similarityScore: number insight: string insightDate: Date viewed: boolean feedback: string | null } interface MemoryEchoNotificationProps { onOpenNote?: (noteId: string) => void } export function MemoryEchoNotification({ onOpenNote }: MemoryEchoNotificationProps) { const [insight, setInsight] = useState(null) const [isLoading, setIsLoading] = useState(false) const [isDismissed, setIsDismissed] = useState(false) const [showModal, setShowModal] = useState(false) // Fetch insight on mount useEffect(() => { fetchInsight() }, []) const fetchInsight = async () => { setIsLoading(true) try { const res = await fetch('/api/ai/echo') const data = await res.json() if (data.insight) { setInsight(data.insight) } } catch (error) { console.error('[MemoryEcho] Failed to fetch insight:', error) } finally { setIsLoading(false) } } const handleView = async () => { if (!insight) return try { // Mark as viewed await fetch('/api/ai/echo', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'view', insightId: insight.id }) }) // Show success message and open modal toast.success('Opening connection...') setShowModal(true) } catch (error) { console.error('[MemoryEcho] Failed to view connection:', error) toast.error('Failed to open connection') } } const handleFeedback = async (feedback: 'thumbs_up' | 'thumbs_down') => { if (!insight) return try { await fetch('/api/ai/echo', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'feedback', insightId: insight.id, feedback }) }) // Show feedback toast if (feedback === 'thumbs_up') { toast.success('Thanks for your feedback!') } else { toast.success('Thanks! We\'ll use this to improve.') } // Dismiss notification setIsDismissed(true) } catch (error) { console.error('[MemoryEcho] Failed to submit feedback:', error) toast.error('Failed to submit feedback') } } const handleDismiss = () => { setIsDismissed(true) } // Don't render notification if dismissed, loading, or no insight if (isDismissed || isLoading || !insight) { return null } // Calculate values for both notification and modal const note1Title = insight.note1.title || 'Untitled' const note2Title = insight.note2.title || 'Untitled' const similarityPercentage = Math.round(insight.similarityScore * 100) // Render modal if requested if (showModal && insight) { return (
{/* Header */}

💡 Memory Echo Discovery

These notes are connected by {similarityPercentage}% similarity

{/* AI-generated insight */}

{insight.insight}

{/* Notes Grid */}
{/* Note 1 */}
{ if (onOpenNote) { onOpenNote(insight.note1.id) setShowModal(false) } }} className="cursor-pointer border dark:border-zinc-700 rounded-lg p-4 hover:border-amber-300 dark:hover:border-amber-700 transition-colors" >

{note1Title}

{insight.note1.content}

Click to view note →

{/* Note 2 */}
{ if (onOpenNote) { onOpenNote(insight.note2.id) setShowModal(false) } }} className="cursor-pointer border dark:border-zinc-700 rounded-lg p-4 hover:border-purple-300 dark:hover:border-purple-700 transition-colors" >

{note2Title}

{insight.note2.content}

Click to view note →

{/* Feedback Section */}

Is this connection helpful?

) } return (
💡 I noticed something... Proactive connections between your notes
{/* AI-generated insight */}

{insight.insight}

{/* Connected notes */}
{note1Title} {note2Title} {similarityPercentage}% match
{/* Action buttons */}
{/* Dismiss link */}
) }