nakama/frontend/src/pages/Feed.jsx

148 lines
4.1 KiB
React
Raw Normal View History

2025-11-03 20:35:01 +00:00
import { useState, useEffect } from 'react'
import { getPosts } from '../utils/api'
import PostCard from '../components/PostCard'
import CreatePostModal from '../components/CreatePostModal'
import { Plus } from 'lucide-react'
import { hapticFeedback } from '../utils/telegram'
import './Feed.css'
export default function Feed({ user }) {
const [posts, setPosts] = useState([])
const [loading, setLoading] = useState(true)
const [showCreateModal, setShowCreateModal] = useState(false)
const [filter, setFilter] = useState('all')
const [page, setPage] = useState(1)
const [hasMore, setHasMore] = useState(true)
useEffect(() => {
loadPosts()
}, [filter])
const loadPosts = async (pageNum = 1) => {
try {
setLoading(true)
const params = {}
if (filter !== 'all') {
params.tag = filter
}
params.page = pageNum
const data = await getPosts(params)
if (pageNum === 1) {
setPosts(data.posts)
} else {
setPosts(prev => [...prev, ...data.posts])
}
setHasMore(pageNum < data.totalPages)
setPage(pageNum)
} catch (error) {
console.error('Ошибка загрузки постов:', error)
} finally {
setLoading(false)
}
}
const handleCreatePost = () => {
hapticFeedback('light')
setShowCreateModal(true)
}
const handlePostCreated = (newPost) => {
setPosts(prev => [newPost, ...prev])
setShowCreateModal(false)
}
const handleLoadMore = () => {
if (!loading && hasMore) {
loadPosts(page + 1)
}
}
return (
<div className="feed-page">
{/* Хедер */}
<div className="feed-header">
<h1>NakamaSpace</h1>
<button className="create-btn" onClick={handleCreatePost}>
<Plus size={20} />
</button>
</div>
{/* Фильтры */}
<div className="feed-filters">
<button
className={`filter-btn ${filter === 'all' ? 'active' : ''}`}
onClick={() => setFilter('all')}
>
Все
</button>
<button
className={`filter-btn ${filter === 'furry' ? 'active' : ''}`}
onClick={() => setFilter('furry')}
style={{ color: filter === 'furry' ? 'var(--tag-furry)' : undefined }}
>
Furry
</button>
<button
className={`filter-btn ${filter === 'anime' ? 'active' : ''}`}
onClick={() => setFilter('anime')}
style={{ color: filter === 'anime' ? 'var(--tag-anime)' : undefined }}
>
Anime
</button>
<button
className={`filter-btn ${filter === 'other' ? 'active' : ''}`}
onClick={() => setFilter('other')}
style={{ color: filter === 'other' ? 'var(--tag-other)' : undefined }}
>
Other
</button>
</div>
{/* Посты */}
<div className="feed-content">
{loading && posts.length === 0 ? (
<div className="loading-state">
<div className="spinner" />
</div>
) : posts.length === 0 ? (
<div className="empty-state">
<p>Пока нет постов</p>
<button className="btn-primary" onClick={handleCreatePost}>
Создать первый пост
</button>
</div>
) : (
<>
{posts.map(post => (
<PostCard key={post._id} post={post} currentUser={user} onUpdate={loadPosts} />
))}
{hasMore && (
<button
className="load-more-btn"
onClick={handleLoadMore}
disabled={loading}
>
{loading ? 'Загрузка...' : 'Загрузить ещё'}
</button>
)}
</>
)}
</div>
{/* Модальное окно создания поста */}
{showCreateModal && (
<CreatePostModal
user={user}
onClose={() => setShowCreateModal(false)}
onPostCreated={handlePostCreated}
/>
)}
</div>
)
}