'use client'; import { memo, useRef, useEffect, useState, useTransition } from 'react'; import { updateGifMoodItem, deleteGifMoodItem } from '@/actions/gif-mood'; import { IconClose } from '@/components/ui'; interface GifMoodCardProps { sessionId: string; item: { id: string; gifUrl: string; note: string | null; userId: string; }; currentUserId: string; canEdit: boolean; } export const GifMoodCard = memo(function GifMoodCard({ sessionId, item, currentUserId, canEdit, }: GifMoodCardProps) { const [note, setNote] = useState(item.note || ''); const [itemVersion, setItemVersion] = useState(item); const [isPending, startTransition] = useTransition(); const [imgError, setImgError] = useState(false); const [imgLoaded, setImgLoaded] = useState(false); const [isFocused, setIsFocused] = useState(false); const textareaRef = useRef(null); useEffect(() => { const el = textareaRef.current; if (!el) return; el.style.height = 'auto'; el.style.height = el.scrollHeight + 'px'; }, [note]); // Sync from server only when not focused — prevents SSE refresh from wiping in-progress edits if (itemVersion !== item) { setItemVersion(item); if (!isFocused) { setNote(item.note || ''); } } const isOwner = item.userId === currentUserId; const canEditThis = canEdit && isOwner; function handleNoteBlur() { if (!canEditThis) return; startTransition(async () => { await updateGifMoodItem(sessionId, item.id, { note: note.trim() || undefined }); }); } function handleDelete() { if (!canEditThis) return; startTransition(async () => { await deleteGifMoodItem(sessionId, item.id); }); } return (
{/* GIF */} {imgError ? (
🖼️

Image non disponible

) : ( // eslint-disable-next-line @next/next/no-img-element GIF setImgLoaded(true)} onError={() => setImgError(true)} /> )} {/* Gradient overlay on hover (for delete affordance) */} {canEditThis && (
)} {/* Delete button — visible on hover */} {canEditThis && ( )} {/* Note */} {canEditThis ? (