import { memo, useState } from 'react'; import type { Wish } from '@family-wishlist/shared'; import { Archive, CheckCircle2, Copy, ExternalLink, MoreHorizontal, Pencil, RotateCcw, Trash2, } from 'lucide-react'; import { WishBadges } from '../WishBadges/WishBadges'; import { Button } from '../ui/Button'; import { cn } from '@/lib/cn'; import { formatPrice } from '@/lib/format'; import { useI18n } from '@/i18n/i18n'; export type WishCardView = 'owner' | 'guest'; export interface WishCardAction { key: string; icon: React.ComponentType<{ className?: string }>; label: string; onClick: () => void; danger?: boolean; } interface WishCardProps { wish: Wish & { isNewForOwner?: boolean }; view: WishCardView; onEdit?: () => void; onArchive?: () => void; onComplete?: () => void; onRestore?: () => void; onDuplicate?: () => void; onDelete?: () => void; footer?: React.ReactNode; } function WishCardInner({ wish, view, onEdit, onArchive, onComplete, onRestore, onDuplicate, onDelete, footer, }: WishCardProps) { const [menuOpen, setMenuOpen] = useState(false); const { locale, t } = useI18n(); const completed = wish.status === 'COMPLETED'; const priceLabel = formatPrice(wish.price, wish.currency, locale); const imageSrc = wish.imageUrl ?? '/default-gift.svg'; const actions: WishCardAction[] = []; if (view === 'owner') { if (wish.status === 'ACTIVE') { if (onEdit) actions.push({ key: 'edit', icon: Pencil, label: t('wish.action.edit'), onClick: onEdit }); if (onComplete) actions.push({ key: 'complete', icon: CheckCircle2, label: t('wish.action.complete'), onClick: onComplete, }); if (onArchive) actions.push({ key: 'archive', icon: Archive, label: t('wish.action.archive'), onClick: onArchive }); if (onDelete) actions.push({ key: 'delete', icon: Trash2, label: t('wish.action.delete'), onClick: onDelete, danger: true, }); } else if (wish.status === 'ARCHIVED') { if (onRestore) actions.push({ key: 'restore', icon: RotateCcw, label: t('wish.action.restore'), onClick: onRestore }); if (onDelete) actions.push({ key: 'delete', icon: Trash2, label: t('wish.action.delete'), onClick: onDelete, danger: true, }); } else if (wish.status === 'COMPLETED') { if (onDuplicate) actions.push({ key: 'duplicate', icon: Copy, label: t('wish.action.duplicate'), onClick: onDuplicate, }); if (onDelete) actions.push({ key: 'delete', icon: Trash2, label: t('wish.action.delete'), onClick: onDelete, danger: true, }); } else if (wish.status === 'DELETED') { if (onRestore) actions.push({ key: 'restore', icon: RotateCcw, label: t('wish.action.restore'), onClick: onRestore }); } } return (
{wish.title} { (e.currentTarget as HTMLImageElement).src = '/default-gift.svg'; }} />
{actions.length > 0 && (
{menuOpen && ( <>
setMenuOpen(false)} aria-hidden />
{actions.map((a) => ( ))}
)}
)}

{wish.title}

{priceLabel && {priceLabel}} {wish.url && ( {t('wish.openLink')} )}
{wish.comment &&

{wish.comment}

} {footer}
); } export const WishCard = memo(WishCardInner);