import { useEffect, useState } from 'react' import { createPortal } from 'react-dom' import { X, ThumbsUp, Check, XCircle, Trash2 } from 'lucide-react' import { useLocale } from '@meshkee/dashboard-ui' import type { ProductComment } from '../types/comment' import { formatCommentDate } from '../data/productComments' import { ApiError } from '../lib/api' import { COMMENTS_PER_PAGE, deleteComment, listBlogComments, updateCommentApproval, } from '../services/commentService' import { Pagination } from './Pagination' import styles from './ProductCommentsModal.module.css' interface BlogCommentsModalProps { open: boolean blogId: string blogTitle: string onClose: () => void onCountChange?: (count: number) => void } const ANIMATION_MS = 220 export function BlogCommentsModal({ open, blogId, blogTitle, onClose, onCountChange, }: BlogCommentsModalProps) { const { locale } = useLocale() const dateLocale = locale === 'fa' ? 'fa' : 'en' const [mounted, setMounted] = useState(open) const [closing, setClosing] = useState(false) const [comments, setComments] = useState([]) const [totalComments, setTotalComments] = useState(0) const [currentPage, setCurrentPage] = useState(1) const [isLoading, setIsLoading] = useState(false) const [error, setError] = useState('') const [actionId, setActionId] = useState(null) const totalPages = Math.max(1, Math.ceil(totalComments / COMMENTS_PER_PAGE)) useEffect(() => { if (open) { setMounted(true) setClosing(false) setCurrentPage(1) } else if (mounted) { setClosing(true) const timer = setTimeout(() => { setMounted(false) setClosing(false) }, ANIMATION_MS) return () => clearTimeout(timer) } }, [open, mounted]) useEffect(() => { if (!open || !blogId) return const controller = new AbortController() void loadComments(currentPage, controller.signal) return () => controller.abort() }, [open, blogId, currentPage]) async function loadComments(page: number, signal?: AbortSignal) { setIsLoading(true) setError('') try { const data = await listBlogComments(blogId, page, COMMENTS_PER_PAGE, signal) setComments(data.items) setTotalComments(data.total) onCountChange?.(data.total) } catch (err) { if (err instanceof DOMException && err.name === 'AbortError') return if (err instanceof ApiError) { setError(err.message) } else { setError('Unable to load comments.') } } finally { setIsLoading(false) } } useEffect(() => { if (currentPage > totalPages) { setCurrentPage(totalPages) } }, [currentPage, totalPages]) useEffect(() => { if (!mounted || closing) return const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose() } document.addEventListener('keydown', onKey) return () => document.removeEventListener('keydown', onKey) }, [mounted, closing, onClose]) if (!mounted) return null async function toggleApproval(comment: ProductComment) { setActionId(comment.id) setError('') try { const updated = await updateCommentApproval(comment.id, !comment.approved) setComments((prev) => prev.map((c) => (c.id === comment.id ? updated : c))) } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError('Unable to update comment approval.') } } finally { setActionId(null) } } async function removeComment(commentId: string) { setActionId(commentId) setError('') try { await deleteComment(commentId) const nextTotal = totalComments - 1 const nextTotalPages = Math.max(1, Math.ceil(nextTotal / COMMENTS_PER_PAGE)) const nextPage = currentPage > nextTotalPages ? nextTotalPages : currentPage setTotalComments(nextTotal) onCountChange?.(nextTotal) if (nextPage !== currentPage) { setCurrentPage(nextPage) } else { setComments((prev) => prev.filter((c) => c.id !== commentId)) } } catch (err) { if (err instanceof ApiError) { setError(err.message) } else { setError('Unable to delete comment.') } } finally { setActionId(null) } } return createPortal(
e.stopPropagation()} role="dialog" aria-modal="true" aria-labelledby="blog-comments-title" >

Comments

{blogTitle && (

{blogTitle} ยท {totalComments}{' '} {totalComments === 1 ? 'comment' : 'comments'}

)}
{error && (

{error}

)} {isLoading ? (

Loading comments...

) : totalComments === 0 ? (

No comments yet for this blog post.

) : ( <>
{comments.map((comment) => (
{comment.author}
{formatCommentDate(comment.createdAt, dateLocale)}
{comment.likesCount}

{comment.text}

{comment.approved ? ( ) : ( )}
))}
{totalComments > COMMENTS_PER_PAGE && (
)} )}
, document.body, ) }