'use client' import { Note, NOTE_COLORS, NoteColor } from '@/lib/types' import { Card } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Checkbox } from '@/components/ui/checkbox' import { Badge } from '@/components/ui/badge' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' import { Archive, ArchiveRestore, MoreVertical, Palette, Pin, Tag, Trash2, } from 'lucide-react' import { useState } from 'react' import { deleteNote, toggleArchive, togglePin, updateColor, updateNote } from '@/app/actions/notes' import { cn } from '@/lib/utils' interface NoteCardProps { note: Note onEdit?: (note: Note) => void onDragStart?: (note: Note) => void onDragEnd?: () => void onDragOver?: (note: Note) => void isDragging?: boolean } export function NoteCard({ note, onEdit, onDragStart, onDragEnd, onDragOver, isDragging }: NoteCardProps) { const [isDeleting, setIsDeleting] = useState(false) const colorClasses = NOTE_COLORS[note.color as NoteColor] || NOTE_COLORS.default const handleDelete = async () => { if (confirm('Are you sure you want to delete this note?')) { setIsDeleting(true) try { await deleteNote(note.id) } catch (error) { console.error('Failed to delete note:', error) setIsDeleting(false) } } } const handleTogglePin = async () => { await togglePin(note.id, !note.isPinned) } const handleToggleArchive = async () => { await toggleArchive(note.id, !note.isArchived) } const handleColorChange = async (color: string) => { await updateColor(note.id, color) } const handleCheckItem = async (checkItemId: string) => { if (note.type === 'checklist' && note.checkItems) { const updatedItems = note.checkItems.map(item => item.id === checkItemId ? { ...item, checked: !item.checked } : item ) await updateNote(note.id, { checkItems: updatedItems }) } } if (isDeleting) return null return ( { e.stopPropagation() onDragStart?.(note) }} onDragEnd={onDragEnd} onDragOver={(e) => { e.preventDefault() e.stopPropagation() onDragOver?.(note) }} className={cn( 'group relative p-4 transition-all duration-200 border', 'cursor-move hover:shadow-md', colorClasses.card, isDragging && 'opacity-30 scale-95' )} onClick={(e) => { // Only trigger edit if not clicking on buttons const target = e.target as HTMLElement if (!target.closest('button') && !target.closest('[role="checkbox"]')) { onEdit?.(note) } }} > {/* Pin Icon */} {note.isPinned && ( )} {/* Title */} {note.title && (

{note.title}

)} {/* Images */} {note.images && note.images.length > 0 && (
{note.images.length === 1 ? ( ) : note.images.length === 2 ? (
{note.images.map((img, idx) => ( ))}
) : note.images.length === 3 ? (
{note.images.slice(1).map((img, idx) => ( ))}
) : (
{note.images.slice(0, 4).map((img, idx) => ( ))} {note.images.length > 4 && (
+{note.images.length - 4}
)}
)}
)} {/* Content */} {note.type === 'text' ? (

{note.content}

) : (
{note.checkItems?.map((item) => (
{ e.stopPropagation() handleCheckItem(item.id) }} > {item.text}
))}
)} {/* Labels */} {note.labels && note.labels.length > 0 && (
{note.labels.map((label) => ( {label} ))}
)} {/* Action Bar - Shows on Hover */}
e.stopPropagation()} > {/* Pin Button */} {/* Color Palette */}
{Object.entries(NOTE_COLORS).map(([colorName, classes]) => (
{/* More Options */} {note.isArchived ? ( <> Unarchive ) : ( <> Archive )} Delete
) }