update pay function
This commit is contained in:
@@ -22,26 +22,38 @@ import {
|
||||
useDisclosure,
|
||||
Flex,
|
||||
Badge,
|
||||
Tabs,
|
||||
TabList,
|
||||
TabPanels,
|
||||
Tab,
|
||||
TabPanel,
|
||||
Icon,
|
||||
} from '@chakra-ui/react';
|
||||
import { Search, PenSquare, TrendingUp, Clock, Heart } from 'lucide-react';
|
||||
import { Search, PenSquare, TrendingUp, Clock, Heart, Zap } from 'lucide-react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { forumColors } from '@theme/forumTheme';
|
||||
import { getPosts, searchPosts } from '@services/elasticsearchService';
|
||||
import { getTopics } from '@services/predictionMarketService';
|
||||
import PostCard from './components/PostCard';
|
||||
import PredictionTopicCard from './components/PredictionTopicCard';
|
||||
import CreatePostModal from './components/CreatePostModal';
|
||||
import CreatePredictionModal from './components/CreatePredictionModal';
|
||||
|
||||
const MotionBox = motion(Box);
|
||||
|
||||
const ValueForum = () => {
|
||||
const [posts, setPosts] = useState([]);
|
||||
const [predictionTopics, setPredictionTopics] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [searchKeyword, setSearchKeyword] = useState('');
|
||||
const [sortBy, setSortBy] = useState('created_at');
|
||||
const [page, setPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [hasMore, setHasMore] = useState(true);
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const { isOpen: isPostModalOpen, onOpen: onPostModalOpen, onClose: onPostModalClose } = useDisclosure();
|
||||
const { isOpen: isPredictionModalOpen, onOpen: onPredictionModalOpen, onClose: onPredictionModalClose } = useDisclosure();
|
||||
|
||||
// 获取帖子列表
|
||||
const fetchPosts = async (currentPage = 1, reset = false) => {
|
||||
@@ -78,10 +90,27 @@ const ValueForum = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 获取预测话题列表
|
||||
const fetchPredictionTopics = () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const topics = getTopics({ status: 'active', sortBy });
|
||||
setPredictionTopics(topics);
|
||||
} catch (error) {
|
||||
console.error('获取预测话题失败:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化加载
|
||||
useEffect(() => {
|
||||
fetchPosts(1, true);
|
||||
}, [sortBy]);
|
||||
if (activeTab === 0) {
|
||||
fetchPosts(1, true);
|
||||
} else {
|
||||
fetchPredictionTopics();
|
||||
}
|
||||
}, [sortBy, activeTab]);
|
||||
|
||||
// 搜索处理
|
||||
const handleSearch = () => {
|
||||
@@ -102,6 +131,11 @@ const ValueForum = () => {
|
||||
fetchPosts(1, true);
|
||||
};
|
||||
|
||||
// 预测话题创建成功回调
|
||||
const handlePredictionCreated = (newTopic) => {
|
||||
setPredictionTopics((prev) => [newTopic, ...prev]);
|
||||
};
|
||||
|
||||
// 排序选项
|
||||
const sortOptions = [
|
||||
{ value: 'created_at', label: '最新发布', icon: Clock },
|
||||
@@ -143,21 +177,41 @@ const ValueForum = () => {
|
||||
</VStack>
|
||||
|
||||
{/* 发帖按钮 */}
|
||||
<Button
|
||||
leftIcon={<PenSquare size={18} />}
|
||||
bg={forumColors.gradients.goldPrimary}
|
||||
color={forumColors.background.main}
|
||||
size="lg"
|
||||
fontWeight="bold"
|
||||
onClick={onOpen}
|
||||
_hover={{
|
||||
transform: 'translateY(-2px)',
|
||||
boxShadow: forumColors.shadows.goldHover,
|
||||
}}
|
||||
_active={{ transform: 'translateY(0)' }}
|
||||
>
|
||||
发布帖子
|
||||
</Button>
|
||||
<HStack spacing="3">
|
||||
<Button
|
||||
leftIcon={<PenSquare size={18} />}
|
||||
bg={forumColors.background.card}
|
||||
color={forumColors.text.primary}
|
||||
size="lg"
|
||||
fontWeight="bold"
|
||||
border="1px solid"
|
||||
borderColor={forumColors.border.default}
|
||||
onClick={onPostModalOpen}
|
||||
_hover={{
|
||||
transform: 'translateY(-2px)',
|
||||
borderColor: forumColors.border.gold,
|
||||
}}
|
||||
_active={{ transform: 'translateY(0)' }}
|
||||
>
|
||||
发布帖子
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
leftIcon={<Zap size={18} />}
|
||||
bg={forumColors.gradients.goldPrimary}
|
||||
color={forumColors.background.main}
|
||||
size="lg"
|
||||
fontWeight="bold"
|
||||
onClick={onPredictionModalOpen}
|
||||
_hover={{
|
||||
transform: 'translateY(-2px)',
|
||||
boxShadow: forumColors.shadows.goldHover,
|
||||
}}
|
||||
_active={{ transform: 'translateY(0)' }}
|
||||
>
|
||||
发起预测
|
||||
</Button>
|
||||
</HStack>
|
||||
</Flex>
|
||||
|
||||
{/* 搜索和筛选栏 */}
|
||||
@@ -224,86 +278,190 @@ const ValueForum = () => {
|
||||
</VStack>
|
||||
</MotionBox>
|
||||
|
||||
{/* 帖子网格 */}
|
||||
{loading && page === 1 ? (
|
||||
<Center py="20">
|
||||
<VStack spacing="4">
|
||||
<Spinner
|
||||
size="xl"
|
||||
thickness="4px"
|
||||
speed="0.8s"
|
||||
color={forumColors.primary[500]}
|
||||
/>
|
||||
<Text color={forumColors.text.secondary}>加载中...</Text>
|
||||
</VStack>
|
||||
</Center>
|
||||
) : posts.length === 0 ? (
|
||||
<Center py="20">
|
||||
<VStack spacing="4">
|
||||
<Text color={forumColors.text.secondary} fontSize="lg">
|
||||
{searchKeyword ? '未找到相关帖子' : '暂无帖子,快来发布第一篇吧!'}
|
||||
</Text>
|
||||
{!searchKeyword && (
|
||||
<Button
|
||||
leftIcon={<PenSquare size={18} />}
|
||||
bg={forumColors.gradients.goldPrimary}
|
||||
color={forumColors.background.main}
|
||||
onClick={onOpen}
|
||||
_hover={{ opacity: 0.9 }}
|
||||
{/* 标签页 */}
|
||||
<Tabs
|
||||
index={activeTab}
|
||||
onChange={setActiveTab}
|
||||
variant="soft-rounded"
|
||||
colorScheme="yellow"
|
||||
>
|
||||
<TabList mb="8" bg={forumColors.background.card} p="2" borderRadius="xl">
|
||||
<Tab
|
||||
_selected={{
|
||||
bg: forumColors.gradients.goldPrimary,
|
||||
color: forumColors.background.main,
|
||||
}}
|
||||
>
|
||||
<HStack spacing="2">
|
||||
<Icon as={PenSquare} boxSize="16px" />
|
||||
<Text>社区帖子</Text>
|
||||
</HStack>
|
||||
</Tab>
|
||||
<Tab
|
||||
_selected={{
|
||||
bg: forumColors.gradients.goldPrimary,
|
||||
color: forumColors.background.main,
|
||||
}}
|
||||
>
|
||||
<HStack spacing="2">
|
||||
<Icon as={Zap} boxSize="16px" />
|
||||
<Text>预测市场</Text>
|
||||
<Badge
|
||||
bg="red.500"
|
||||
color="white"
|
||||
borderRadius="full"
|
||||
px="2"
|
||||
fontSize="xs"
|
||||
>
|
||||
发布帖子
|
||||
</Button>
|
||||
)}
|
||||
</VStack>
|
||||
</Center>
|
||||
) : (
|
||||
<>
|
||||
<SimpleGrid columns={{ base: 1, md: 2, lg: 3, xl: 4 }} spacing="6">
|
||||
<AnimatePresence>
|
||||
{posts.map((post, index) => (
|
||||
<MotionBox
|
||||
key={post.id}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -20 }}
|
||||
transition={{ duration: 0.3, delay: index * 0.05 }}
|
||||
>
|
||||
<PostCard post={post} />
|
||||
</MotionBox>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
</SimpleGrid>
|
||||
NEW
|
||||
</Badge>
|
||||
</HStack>
|
||||
</Tab>
|
||||
</TabList>
|
||||
|
||||
{/* 加载更多按钮 */}
|
||||
{hasMore && (
|
||||
<Center mt="10">
|
||||
<Button
|
||||
onClick={loadMore}
|
||||
isLoading={loading}
|
||||
loadingText="加载中..."
|
||||
bg={forumColors.background.card}
|
||||
color={forumColors.text.primary}
|
||||
border="1px solid"
|
||||
borderColor={forumColors.border.default}
|
||||
_hover={{
|
||||
borderColor: forumColors.border.gold,
|
||||
bg: forumColors.background.hover,
|
||||
}}
|
||||
>
|
||||
加载更多
|
||||
</Button>
|
||||
</Center>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<TabPanels>
|
||||
{/* 普通帖子标签页 */}
|
||||
<TabPanel p="0">
|
||||
{loading && page === 1 ? (
|
||||
<Center py="20">
|
||||
<VStack spacing="4">
|
||||
<Spinner
|
||||
size="xl"
|
||||
thickness="4px"
|
||||
speed="0.8s"
|
||||
color={forumColors.primary[500]}
|
||||
/>
|
||||
<Text color={forumColors.text.secondary}>加载中...</Text>
|
||||
</VStack>
|
||||
</Center>
|
||||
) : posts.length === 0 ? (
|
||||
<Center py="20">
|
||||
<VStack spacing="4">
|
||||
<Text color={forumColors.text.secondary} fontSize="lg">
|
||||
{searchKeyword ? '未找到相关帖子' : '暂无帖子,快来发布第一篇吧!'}
|
||||
</Text>
|
||||
{!searchKeyword && (
|
||||
<Button
|
||||
leftIcon={<PenSquare size={18} />}
|
||||
bg={forumColors.gradients.goldPrimary}
|
||||
color={forumColors.background.main}
|
||||
onClick={onPostModalOpen}
|
||||
_hover={{ opacity: 0.9 }}
|
||||
>
|
||||
发布帖子
|
||||
</Button>
|
||||
)}
|
||||
</VStack>
|
||||
</Center>
|
||||
) : (
|
||||
<>
|
||||
<SimpleGrid columns={{ base: 1, md: 2, lg: 3, xl: 4 }} spacing="6">
|
||||
<AnimatePresence>
|
||||
{posts.map((post, index) => (
|
||||
<MotionBox
|
||||
key={post.id}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -20 }}
|
||||
transition={{ duration: 0.3, delay: index * 0.05 }}
|
||||
>
|
||||
<PostCard post={post} />
|
||||
</MotionBox>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
</SimpleGrid>
|
||||
|
||||
{/* 加载更多按钮 */}
|
||||
{hasMore && (
|
||||
<Center mt="10">
|
||||
<Button
|
||||
onClick={loadMore}
|
||||
isLoading={loading}
|
||||
loadingText="加载中..."
|
||||
bg={forumColors.background.card}
|
||||
color={forumColors.text.primary}
|
||||
border="1px solid"
|
||||
borderColor={forumColors.border.default}
|
||||
_hover={{
|
||||
borderColor: forumColors.border.gold,
|
||||
bg: forumColors.background.hover,
|
||||
}}
|
||||
>
|
||||
加载更多
|
||||
</Button>
|
||||
</Center>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</TabPanel>
|
||||
|
||||
{/* 预测市场标签页 */}
|
||||
<TabPanel p="0">
|
||||
{loading ? (
|
||||
<Center py="20">
|
||||
<VStack spacing="4">
|
||||
<Spinner
|
||||
size="xl"
|
||||
thickness="4px"
|
||||
speed="0.8s"
|
||||
color={forumColors.primary[500]}
|
||||
/>
|
||||
<Text color={forumColors.text.secondary}>加载中...</Text>
|
||||
</VStack>
|
||||
</Center>
|
||||
) : predictionTopics.length === 0 ? (
|
||||
<Center py="20">
|
||||
<VStack spacing="4">
|
||||
<Icon as={Zap} boxSize="48px" color={forumColors.text.tertiary} />
|
||||
<Text color={forumColors.text.secondary} fontSize="lg">
|
||||
暂无预测话题,快来发起第一个吧!
|
||||
</Text>
|
||||
<Button
|
||||
leftIcon={<Zap size={18} />}
|
||||
bg={forumColors.gradients.goldPrimary}
|
||||
color={forumColors.background.main}
|
||||
onClick={onPredictionModalOpen}
|
||||
_hover={{ opacity: 0.9 }}
|
||||
>
|
||||
发起预测
|
||||
</Button>
|
||||
</VStack>
|
||||
</Center>
|
||||
) : (
|
||||
<SimpleGrid columns={{ base: 1, md: 2, lg: 3 }} spacing="6">
|
||||
<AnimatePresence>
|
||||
{predictionTopics.map((topic, index) => (
|
||||
<MotionBox
|
||||
key={topic.id}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -20 }}
|
||||
transition={{ duration: 0.3, delay: index * 0.05 }}
|
||||
>
|
||||
<PredictionTopicCard topic={topic} />
|
||||
</MotionBox>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
</SimpleGrid>
|
||||
)}
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
</Container>
|
||||
|
||||
{/* 发帖模态框 */}
|
||||
<CreatePostModal
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
isOpen={isPostModalOpen}
|
||||
onClose={onPostModalClose}
|
||||
onPostCreated={handlePostCreated}
|
||||
/>
|
||||
|
||||
{/* 发起预测模态框 */}
|
||||
<CreatePredictionModal
|
||||
isOpen={isPredictionModalOpen}
|
||||
onClose={onPredictionModalClose}
|
||||
onTopicCreated={handlePredictionCreated}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user