Keep/keep-notes/components/comparison-modal.tsx

176 lines
6.3 KiB
TypeScript

'use client'
import { useState } from 'react'
import { Dialog, DialogContent } from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
import { X, Sparkles, ThumbsUp, ThumbsDown } from 'lucide-react'
import { cn } from '@/lib/utils'
import { Note } from '@/lib/types'
import { useLanguage } from '@/lib/i18n/LanguageProvider'
interface ComparisonModalProps {
isOpen: boolean
onClose: () => void
notes: Array<Partial<Note>>
similarity?: number
onOpenNote?: (noteId: string) => void
}
export function ComparisonModal({
isOpen,
onClose,
notes,
similarity,
onOpenNote
}: ComparisonModalProps) {
const { t } = useLanguage()
const [feedback, setFeedback] = useState<'thumbs_up' | 'thumbs_down' | null>(null)
const handleFeedback = async (type: 'thumbs_up' | 'thumbs_down') => {
setFeedback(type)
// TODO: Send feedback to backend
setTimeout(() => {
onClose()
}, 500)
}
const getNoteColor = (index: number) => {
const colors = [
'border-primary/20 dark:border-primary/30 hover:border-primary/30 dark:hover:border-primary/40',
'border-purple-200 dark:border-purple-800 hover:border-purple-300 dark:hover:border-purple-700',
'border-green-200 dark:border-green-800 hover:border-green-300 dark:hover:border-green-700'
]
return colors[index % colors.length]
}
const getTitleColor = (index: number) => {
const colors = [
'text-primary dark:text-primary-foreground',
'text-purple-600 dark:text-purple-400',
'text-green-600 dark:text-green-400'
]
return colors[index % colors.length]
}
const maxModalWidth = notes.length === 2 ? 'max-w-6xl' : 'max-w-7xl'
const similarityPercentage = similarity ? Math.round(similarity * 100) : 0
return (
<Dialog open={isOpen} onOpenChange={onClose}>
<DialogContent className={cn(
"max-h-[90vh] overflow-hidden flex flex-col p-0",
maxModalWidth
)}>
{/* Header */}
<div className="flex items-center justify-between p-6 border-b dark:border-zinc-700">
<div className="flex items-center gap-3">
<div className="p-2 bg-amber-100 dark:bg-amber-900/30 rounded-full">
<Sparkles className="h-5 w-5 text-amber-600 dark:text-amber-400" />
</div>
<div>
<h2 className="text-xl font-semibold">
{t('memoryEcho.comparison.title')}
</h2>
<p className="text-sm text-gray-600 dark:text-gray-400">
{t('memoryEcho.comparison.similarityInfo', { similarity: similarityPercentage })}
</p>
</div>
</div>
<button
onClick={onClose}
className="text-gray-500 hover:text-gray-700 dark:hover:text-gray-300"
>
<X className="h-6 w-6" />
</button>
</div>
{/* AI Insight Section - Optional for now */}
{similarityPercentage >= 80 && (
<div className="px-6 py-4 bg-amber-50 dark:bg-amber-950/20 border-b dark:border-zinc-700">
<div className="flex items-start gap-2">
<Sparkles className="h-4 w-4 text-amber-600 dark:text-amber-400 mt-0.5 flex-shrink-0" />
<p className="text-sm text-gray-700 dark:text-gray-300">
{t('memoryEcho.comparison.highSimilarityInsight')}
</p>
</div>
</div>
)}
{/* Notes Grid */}
<div className={cn(
"flex-1 overflow-y-auto p-6",
notes.length === 2 ? "grid grid-cols-2 gap-6" : "grid grid-cols-3 gap-4"
)}>
{notes.map((note, index) => {
const title = note.title || t('memoryEcho.comparison.untitled')
const noteColor = getNoteColor(index)
const titleColor = getTitleColor(index)
return (
<div
key={note.id || index}
onClick={() => {
if (onOpenNote && note.id) {
onOpenNote(note.id)
onClose()
}
}}
className={cn(
"cursor-pointer border dark:border-zinc-700 rounded-lg p-4 transition-all hover:shadow-md",
noteColor
)}
>
<h3 className={cn("font-semibold text-lg mb-3", titleColor)}>
{title}
</h3>
<div className="text-sm text-gray-600 dark:text-gray-400 line-clamp-8 whitespace-pre-wrap">
{note.content}
</div>
<div className="mt-4 pt-3 border-t dark:border-zinc-700">
<p className="text-xs text-gray-500 flex items-center gap-1">
{t('memoryEcho.comparison.clickToView')}
<span className="transform rotate-[-45deg]"></span>
</p>
</div>
</div>
)
})}
</div>
{/* Footer - Feedback */}
<div className="px-6 py-4 border-t dark:border-zinc-700 bg-gray-50 dark:bg-zinc-800/50">
<div className="flex items-center justify-between">
<p className="text-sm text-gray-600 dark:text-gray-400">
{t('memoryEcho.comparison.helpfulQuestion')}
</p>
<div className="flex items-center gap-2">
<Button
size="sm"
variant={feedback === 'thumbs_up' ? 'default' : 'outline'}
onClick={() => handleFeedback('thumbs_up')}
className={cn(
feedback === 'thumbs_up' && "bg-green-600 hover:bg-green-700 text-white"
)}
>
<ThumbsUp className="h-4 w-4 mr-2" />
{t('memoryEcho.comparison.helpful')}
</Button>
<Button
size="sm"
variant={feedback === 'thumbs_down' ? 'default' : 'outline'}
onClick={() => handleFeedback('thumbs_down')}
className={cn(
feedback === 'thumbs_down' && "bg-red-600 hover:bg-red-700 text-white"
)}
>
<ThumbsDown className="h-4 w-4 mr-2" />
{t('memoryEcho.comparison.notHelpful')}
</Button>
</div>
</div>
</div>
</DialogContent>
</Dialog>
)
}