Update files

This commit is contained in:
glpshchn 2025-12-05 00:39:03 +03:00
parent 458c7fadc8
commit a19c4bca62
1 changed files with 78 additions and 73 deletions

View File

@ -72,7 +72,7 @@ export default function CommentsModal({ post, onClose, onUpdate }) {
return () => { return () => {
cancelled = true cancelled = true
} }
}, [post?._id || null]) // Только ID поста в зависимостях, используем null для стабильности }, [post?._id]) // Используем просто post?._id без || null
// Проверка на существование поста ПОСЛЕ хуков // Проверка на существование поста ПОСЛЕ хуков
const displayPost = fullPost || post const displayPost = fullPost || post
@ -104,10 +104,6 @@ export default function CommentsModal({ post, onClose, onUpdate }) {
setComment('') setComment('')
hapticFeedback('success') hapticFeedback('success')
// Обновить данные поста для синхронизации (но не блокируем UI)
// Перезагружаем через useEffect, который сработает при изменении post._id
// Но так как post._id не меняется, просто обновим локально
if (onUpdate) { if (onUpdate) {
onUpdate() onUpdate()
} }
@ -124,6 +120,7 @@ export default function CommentsModal({ post, onClose, onUpdate }) {
} }
const formatDate = (date) => { const formatDate = (date) => {
if (!date) return 'только что'
const d = new Date(date) const d = new Date(date)
const now = new Date() const now = new Date()
const diff = Math.floor((now - d) / 1000) // секунды const diff = Math.floor((now - d) / 1000) // секунды
@ -142,17 +139,15 @@ export default function CommentsModal({ post, onClose, onUpdate }) {
} }
} }
// Если нет валидного поста, не рендерим модалку вообще // ВСЕГДА рендерим createPortal, даже если пост не валиден
if (!hasValidPost) { // Это критично для соблюдения правил хуков
return null
}
return createPortal( return createPortal(
<div <div
className="comments-modal-overlay" className="comments-modal-overlay"
onMouseDown={(e) => e.stopPropagation()} onMouseDown={(e) => e.stopPropagation()}
onTouchStart={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()}
onClick={handleOverlayClick} onClick={handleOverlayClick}
style={{ display: hasValidPost ? 'flex' : 'none' }}
> >
<div className="comments-modal" onClick={(e) => e.stopPropagation()}> <div className="comments-modal" onClick={(e) => e.stopPropagation()}>
{/* Хедер */} {/* Хедер */}
@ -165,7 +160,13 @@ export default function CommentsModal({ post, onClose, onUpdate }) {
</div> </div>
{/* Пост */} {/* Пост */}
{loadingPost ? ( {!hasValidPost ? (
<div className="post-preview">
<div className="loading-state">
<p>Загрузка...</p>
</div>
</div>
) : loadingPost ? (
<div className="post-preview"> <div className="post-preview">
<div className="loading-state"> <div className="loading-state">
<div className="spinner" /> <div className="spinner" />
@ -205,71 +206,75 @@ export default function CommentsModal({ post, onClose, onUpdate }) {
)} )}
{/* Список комментариев */} {/* Список комментариев */}
<div className="comments-list"> {hasValidPost && (
{comments.length === 0 ? ( <div className="comments-list">
<div className="empty-comments"> {comments.length === 0 ? (
<p>Пока нет комментариев</p> <div className="empty-comments">
<span>Будьте первым!</span> <p>Пока нет комментариев</p>
</div> <span>Будьте первым!</span>
) : (
comments
.filter(c => {
// Фильтруем комментарии без автора или с неполным автором
return c && c.author && (typeof c.author === 'object') && c.content
})
.map((c, index) => {
// Используем _id если есть, иначе index
const commentId = c._id || c.id || `comment-${index}`
// Проверяем, что автор полностью загружен
if (!c.author || typeof c.author !== 'object') {
console.warn('[CommentsModal] Комментарий без автора:', c)
return null
}
return (
<div key={commentId} className="comment-item fade-in">
<img
src={c.author?.photoUrl || '/default-avatar.png'}
alt={c.author?.username || c.author?.firstName || 'User'}
className="comment-avatar"
onError={(e) => { e.target.src = '/default-avatar.png' }}
/>
<div className="comment-content">
<div className="comment-header">
<span className="comment-author">
{c.author?.firstName || ''} {c.author?.lastName || ''}
{!c.author?.firstName && !c.author?.lastName && 'Пользователь'}
</span>
<span className="comment-time">{formatDate(c.createdAt)}</span>
</div>
<p className="comment-text">{decodeHtmlEntities(c.content)}</p>
</div>
</div> </div>
) ) : (
}) comments
.filter(Boolean) // Убираем null значения .filter(c => {
)} // Фильтруем комментарии без автора или с неполным автором
</div> return c && c.author && (typeof c.author === 'object') && c.content
})
.map((c, index) => {
// Используем _id если есть, иначе index
const commentId = c._id || c.id || `comment-${index}`
// Проверяем, что автор полностью загружен
if (!c.author || typeof c.author !== 'object') {
console.warn('[CommentsModal] Комментарий без автора:', c)
return null
}
return (
<div key={commentId} className="comment-item fade-in">
<img
src={c.author?.photoUrl || '/default-avatar.png'}
alt={c.author?.username || c.author?.firstName || 'User'}
className="comment-avatar"
onError={(e) => { e.target.src = '/default-avatar.png' }}
/>
<div className="comment-content">
<div className="comment-header">
<span className="comment-author">
{c.author?.firstName || ''} {c.author?.lastName || ''}
{!c.author?.firstName && !c.author?.lastName && 'Пользователь'}
</span>
<span className="comment-time">{formatDate(c.createdAt)}</span>
</div>
<p className="comment-text">{decodeHtmlEntities(c.content)}</p>
</div>
</div>
)
})
.filter(Boolean) // Убираем null значения
)}
</div>
)}
{/* Форма добавления комментария */} {/* Форма добавления комментария */}
<div className="comment-form"> {hasValidPost && (
<input <div className="comment-form">
type="text" <input
placeholder="Написать комментарий..." type="text"
value={comment} placeholder="Написать комментарий..."
onChange={e => setComment(e.target.value)} value={comment}
onKeyPress={e => e.key === 'Enter' && handleSubmit()} onChange={e => setComment(e.target.value)}
maxLength={500} onKeyPress={e => e.key === 'Enter' && handleSubmit()}
/> maxLength={500}
<button />
onClick={handleSubmit} <button
disabled={loading || !comment.trim()} onClick={handleSubmit}
className="send-btn" disabled={loading || !comment.trim()}
> className="send-btn"
<Send size={20} /> >
</button> <Send size={20} />
</div> </button>
</div>
)}
</div> </div>
</div> </div>,
document.body
) )
} }