"use client"; import { useState, useEffect, useCallback, useMemo, Fragment } from "react"; import Link from "next/link"; import { MessageCircle, Reply, Trash2 } from "lucide-react"; import { toast } from "sonner"; import { useTranslations } from "next-intl"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Separator } from "@/components/ui/separator"; import { CommentReactions } from "@/components/social/comment-reactions"; import { ReportButton } from "@/components/social/report-button"; import { cn } from "@/lib/utils"; type Comment = { id: string; content: string; parentId: string | null; createdAt: string; userId: string; userName: string; userUsername: string | null; userAvatarUrl: string | null; }; const MAX_VISUAL_INDENT = 4; const MENTION_REGEX = /@([a-z0-9_-]{3,30})/gi; function renderContentWithMentions(content: string) { const parts = content.split(MENTION_REGEX); // split() with a capturing group interleaves [text, username, text, username, ...text] return parts.map((part, i) => i % 2 === 1 ? ( @{part} ) : ( {part} ) ); } function timeAgo(dateStr: string, t: ReturnType) { const diff = Date.now() - new Date(dateStr).getTime(); const mins = Math.floor(diff / 60000); if (mins < 1) return t("justNow"); if (mins < 60) return t("minutesAgo", { mins }); const hours = Math.floor(mins / 60); if (hours < 24) return t("hoursAgo", { hours }); return t("daysAgo", { days: Math.floor(hours / 24) }); } function CommentForm({ recipeId, parentId, onSubmit, placeholder, onCancel, }: { recipeId: string; parentId?: string; onSubmit: () => void; placeholder?: string; onCancel?: () => void; }) { const t = useTranslations("social"); const tCommon = useTranslations("common"); const [content, setContent] = useState(""); const [submitting, setSubmitting] = useState(false); async function submit() { if (!content.trim()) return; setSubmitting(true); try { const res = await fetch(`/api/v1/recipes/${recipeId}/comments`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ content: content.trim(), parentId }), }); if (!res.ok) { toast.error(t("commentFailed")); return; } setContent(""); onSubmit(); } finally { setSubmitting(false); } } return (