Update files

This commit is contained in:
glpshchn 2025-12-05 00:10:11 +03:00
parent dfa64eccb4
commit 602b23017a
5 changed files with 89 additions and 81 deletions

View File

@ -16,8 +16,6 @@ export default function CommentsModal({ post, onClose, onUpdate }) {
// Загрузить полные данные поста с комментариями // Загрузить полные данные поста с комментариями
const loadFullPost = useCallback(async () => { const loadFullPost = useCallback(async () => {
if (!post?._id) { if (!post?._id) {
setFullPost(post || null)
setComments(post?.comments || [])
return return
} }
@ -27,29 +25,28 @@ export default function CommentsModal({ post, onClose, onUpdate }) {
const foundPost = response.posts?.find(p => p._id === post._id) const foundPost = response.posts?.find(p => p._id === post._id)
if (foundPost) { if (foundPost) {
setFullPost(foundPost) setFullPost(foundPost)
setComments(foundPost.comments || []) // Убедимся, что комментарии загружены с авторами
} else { const commentsWithAuthors = foundPost.comments || []
// Fallback на переданный post setComments(commentsWithAuthors)
setFullPost(post)
setComments(post?.comments || [])
} }
} catch (error) { } catch (error) {
console.error('[CommentsModal] Ошибка загрузки поста:', error) console.error('[CommentsModal] Ошибка загрузки поста:', error)
// Fallback на переданный post
setFullPost(post)
setComments(post?.comments || [])
} finally { } finally {
setLoadingPost(false) setLoadingPost(false)
} }
}, [post]) }, [post?._id])
useEffect(() => { useEffect(() => {
if (post) { if (post) {
// Сначала установим переданные данные
setFullPost(post) setFullPost(post)
setComments(post.comments || []) setComments(post.comments || [])
loadFullPost() // Затем загрузим полные данные
if (post._id) {
loadFullPost()
}
} }
}, [post, loadFullPost]) }, [post?._id, loadFullPost])
// Проверка на существование поста ПОСЛЕ хуков // Проверка на существование поста ПОСЛЕ хуков
if (!post) { if (!post) {
@ -59,19 +56,28 @@ export default function CommentsModal({ post, onClose, onUpdate }) {
const displayPost = fullPost || post const displayPost = fullPost || post
const handleSubmit = async () => { const handleSubmit = async () => {
if (!comment.trim()) return if (!comment.trim() || loading) return
try { try {
setLoading(true) setLoading(true)
hapticFeedback('light') hapticFeedback('light')
const result = await commentPost(post._id, comment) const result = await commentPost(post._id, comment)
setComments(result.comments || []) if (result && result.comments) {
// Обновить комментарии из ответа API
setComments(result.comments)
// Обновить полный пост
if (fullPost) {
setFullPost({ ...fullPost, comments: result.comments })
}
}
setComment('') setComment('')
hapticFeedback('success') hapticFeedback('success')
// Обновить полный пост // Обновить данные поста
await loadFullPost() await loadFullPost()
onUpdate() if (onUpdate) {
onUpdate()
}
} catch (error) { } catch (error) {
console.error('Ошибка добавления комментария:', error) console.error('Ошибка добавления комментария:', error)
hapticFeedback('error') hapticFeedback('error')
@ -163,9 +169,12 @@ export default function CommentsModal({ post, onClose, onUpdate }) {
</div> </div>
) : ( ) : (
comments comments
.filter(c => c.author) // Фильтруем комментарии без автора .filter(c => c && c.author) // Фильтруем комментарии без автора
.map((c, index) => ( .map((c, index) => {
<div key={index} className="comment-item fade-in"> // Используем _id если есть, иначе index
const commentId = c._id || c.id || `comment-${index}`
return (
<div key={commentId} className="comment-item fade-in">
<img <img
src={c.author?.photoUrl || '/default-avatar.png'} src={c.author?.photoUrl || '/default-avatar.png'}
alt={c.author?.username || c.author?.firstName || 'User'} alt={c.author?.username || c.author?.firstName || 'User'}
@ -183,7 +192,8 @@ export default function CommentsModal({ post, onClose, onUpdate }) {
<p className="comment-text">{decodeHtmlEntities(c.content)}</p> <p className="comment-text">{decodeHtmlEntities(c.content)}</p>
</div> </div>
</div> </div>
)) )
})
)} )}
</div> </div>

View File

@ -103,20 +103,18 @@
} }
.user-item-wrapper { .user-item-wrapper {
display: flex;
flex-direction: column;
gap: 8px;
padding: 8px 16px; padding: 8px 16px;
} }
.user-item { .user-item {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 12px;
cursor: pointer; cursor: pointer;
transition: background 0.2s; transition: background 0.2s;
padding: 4px; padding: 8px;
border-radius: 8px; border-radius: 8px;
position: relative;
} }
.user-item:active { .user-item:active {
@ -134,56 +132,56 @@
.user-info { .user-info {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
display: flex;
flex-direction: column;
gap: 2px;
} }
.user-name { .user-name {
font-size: 14px; font-size: 15px;
font-weight: 600; font-weight: 600;
color: var(--text-primary); color: var(--text-primary);
margin-bottom: 2px; line-height: 1.2;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.user-username { .user-username {
font-size: 12px; font-size: 13px;
color: var(--text-secondary); color: var(--text-secondary);
line-height: 1.2;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
/* Follow Button */ /* Follow Button Icon */
.follow-btn { .follow-btn-icon {
width: 36px;
height: 36px;
border-radius: 50%;
background: var(--bg-primary);
color: var(--text-primary);
border: 1px solid var(--divider-color);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 8px; cursor: pointer;
width: 100%; transition: all 0.2s ease;
padding: 10px 18px; flex-shrink: 0;
border-radius: 12px; margin-left: auto;
}
.follow-btn-icon:active {
opacity: 0.7;
transform: scale(0.95);
}
.follow-btn-icon.following {
background: var(--button-accent); background: var(--button-accent);
color: white; color: white;
border: none; border-color: var(--button-accent);
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: opacity 0.2s ease;
}
.follow-btn:active {
opacity: 0.85;
}
.follow-btn.following {
background: var(--bg-primary);
color: var(--text-secondary);
border: 1px solid var(--divider-color);
}
.follow-btn span {
white-space: nowrap;
} }

View File

@ -105,26 +105,20 @@ export default function FollowListModal({ users, title, onClose, currentUser })
</div> </div>
<div className="user-username">@{user.username || user.firstName || 'user'}</div> <div className="user-username">@{user.username || user.firstName || 'user'}</div>
</div> </div>
</div>
{!isOwnProfile && ( {!isOwnProfile && (
<button <button
className={`follow-btn ${isFollowing ? 'following' : ''}`} className={`follow-btn-icon ${isFollowing ? 'following' : ''}`}
onClick={(e) => handleFollowToggle(user._id, e)} onClick={(e) => handleFollowToggle(user._id, e)}
> >
{isFollowing ? ( {isFollowing ? (
<> <UserMinus size={20} />
<UserMinus size={18} /> ) : (
<span>Отписаться</span> <UserPlus size={20} />
</> )}
) : ( </button>
<> )}
<UserPlus size={18} /> </div>
<span>Подписаться</span>
</>
)}
</button>
)}
</div> </div>
) )
})} })}

View File

@ -149,6 +149,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-shrink: 0;
} }
.donation-text h3 { .donation-text h3 {
@ -166,7 +167,7 @@
} }
.donation-button { .donation-button {
align-self: flex-start; width: 100%;
padding: 10px 18px; padding: 10px 18px;
border-radius: 12px; border-radius: 12px;
background: var(--text-primary); background: var(--text-primary);
@ -178,7 +179,7 @@
transition: opacity 0.2s ease; transition: opacity 0.2s ease;
} }
.donation-button:hover { .donation-button:active {
opacity: 0.85; opacity: 0.85;
} }

View File

@ -121,21 +121,20 @@
width: 40px; width: 40px;
height: 40px; height: 40px;
border-radius: 50%; border-radius: 50%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background: var(--bg-primary);
color: white; color: var(--text-primary);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-shrink: 0; flex-shrink: 0;
border: none; border: 1px solid var(--divider-color);
cursor: pointer; cursor: pointer;
transition: all 0.2s ease; transition: all 0.2s ease;
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
} }
.search-submit-btn:active { .search-submit-btn:active {
transform: scale(0.95); transform: scale(0.95);
box-shadow: 0 2px 4px rgba(102, 126, 234, 0.2); opacity: 0.8;
} }
.search-submit-btn:disabled { .search-submit-btn:disabled {
@ -145,7 +144,13 @@
} }
[data-theme="dark"] .search-submit-btn { [data-theme="dark"] .search-submit-btn {
box-shadow: 0 2px 8px rgba(118, 75, 162, 0.4); background: #3A3A3C;
color: #FFFFFF;
border-color: #48484A;
}
[data-theme="dark"] .search-submit-btn:active {
background: #48484A;
} }
.tag-suggestions { .tag-suggestions {