2025-04-15 16:28:03 +05:30
|
|
|
import React, { createContext, useContext, useState, useEffect } from 'react';
|
|
|
|
|
import { useToast } from '@/components/ui/use-toast';
|
2025-04-16 14:45:27 +05:30
|
|
|
import { Cell, Post, Comment } from '@/types';
|
2025-04-15 16:28:03 +05:30
|
|
|
import { useAuth } from './AuthContext';
|
2025-04-22 10:50:08 +05:30
|
|
|
import {
|
|
|
|
|
getDataFromCache,
|
|
|
|
|
createPost,
|
|
|
|
|
createComment,
|
|
|
|
|
vote,
|
|
|
|
|
createCell,
|
|
|
|
|
refreshData as refreshNetworkData,
|
|
|
|
|
initializeNetwork,
|
|
|
|
|
setupPeriodicQueries,
|
|
|
|
|
monitorNetworkHealth,
|
|
|
|
|
ForumContextType
|
|
|
|
|
} from './forum';
|
2025-04-15 16:28:03 +05:30
|
|
|
|
|
|
|
|
const ForumContext = createContext<ForumContextType | undefined>(undefined);
|
|
|
|
|
|
|
|
|
|
export function ForumProvider({ children }: { children: React.ReactNode }) {
|
|
|
|
|
const [cells, setCells] = useState<Cell[]>([]);
|
|
|
|
|
const [posts, setPosts] = useState<Post[]>([]);
|
|
|
|
|
const [comments, setComments] = useState<Comment[]>([]);
|
2025-04-22 10:39:32 +05:30
|
|
|
|
2025-04-22 10:50:08 +05:30
|
|
|
// Loading states
|
2025-04-22 10:39:32 +05:30
|
|
|
const [isInitialLoading, setIsInitialLoading] = useState(true);
|
|
|
|
|
const [isPostingCell, setIsPostingCell] = useState(false);
|
|
|
|
|
const [isPostingPost, setIsPostingPost] = useState(false);
|
|
|
|
|
const [isPostingComment, setIsPostingComment] = useState(false);
|
|
|
|
|
const [isVoting, setIsVoting] = useState(false);
|
|
|
|
|
const [isRefreshing, setIsRefreshing] = useState(false);
|
|
|
|
|
|
|
|
|
|
// Network connection status
|
|
|
|
|
const [isNetworkConnected, setIsNetworkConnected] = useState(false);
|
|
|
|
|
|
2025-04-15 16:28:03 +05:30
|
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
|
const { currentUser, isAuthenticated } = useAuth();
|
|
|
|
|
const { toast } = useToast();
|
|
|
|
|
|
2025-04-22 10:39:32 +05:30
|
|
|
// Function to update UI state from message cache
|
|
|
|
|
const updateStateFromCache = () => {
|
2025-04-22 10:50:08 +05:30
|
|
|
const data = getDataFromCache();
|
|
|
|
|
setCells(data.cells);
|
|
|
|
|
setPosts(data.posts);
|
|
|
|
|
setComments(data.comments);
|
2025-04-22 10:39:32 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Function to refresh data from the network
|
2025-04-22 10:50:08 +05:30
|
|
|
const handleRefreshData = async () => {
|
|
|
|
|
setIsRefreshing(true);
|
|
|
|
|
await refreshNetworkData(isNetworkConnected, toast, updateStateFromCache, setError);
|
|
|
|
|
setIsRefreshing(false);
|
2025-04-22 10:39:32 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Monitor network connection status
|
|
|
|
|
useEffect(() => {
|
2025-04-22 10:50:08 +05:30
|
|
|
const { unsubscribe } = monitorNetworkHealth(setIsNetworkConnected, toast);
|
|
|
|
|
return unsubscribe;
|
2025-04-22 10:39:32 +05:30
|
|
|
}, [toast]);
|
|
|
|
|
|
2025-04-15 16:28:03 +05:30
|
|
|
useEffect(() => {
|
|
|
|
|
const loadData = async () => {
|
2025-04-22 10:50:08 +05:30
|
|
|
setIsInitialLoading(true);
|
|
|
|
|
await initializeNetwork(toast, updateStateFromCache, setError);
|
|
|
|
|
setIsInitialLoading(false);
|
2025-04-15 16:28:03 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
|
|
loadData();
|
2025-04-22 10:39:32 +05:30
|
|
|
|
2025-04-22 10:50:08 +05:30
|
|
|
// Set up periodic queries
|
|
|
|
|
const { cleanup } = setupPeriodicQueries(isNetworkConnected, updateStateFromCache);
|
2025-04-22 10:39:32 +05:30
|
|
|
|
2025-04-22 10:50:08 +05:30
|
|
|
return cleanup;
|
2025-04-22 10:39:32 +05:30
|
|
|
}, [toast]);
|
2025-04-15 16:28:03 +05:30
|
|
|
|
|
|
|
|
const getCellById = (id: string): Cell | undefined => {
|
|
|
|
|
return cells.find(cell => cell.id === id);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getPostsByCell = (cellId: string): Post[] => {
|
|
|
|
|
return posts.filter(post => post.cellId === cellId)
|
|
|
|
|
.sort((a, b) => b.timestamp - a.timestamp);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getCommentsByPost = (postId: string): Comment[] => {
|
|
|
|
|
return comments.filter(comment => comment.postId === postId)
|
|
|
|
|
.sort((a, b) => a.timestamp - b.timestamp);
|
|
|
|
|
};
|
|
|
|
|
|
2025-04-22 10:50:08 +05:30
|
|
|
const handleCreatePost = async (cellId: string, title: string, content: string): Promise<Post | null> => {
|
|
|
|
|
setIsPostingPost(true);
|
|
|
|
|
const result = await createPost(cellId, title, content, currentUser, isAuthenticated, toast, updateStateFromCache);
|
|
|
|
|
setIsPostingPost(false);
|
|
|
|
|
return result;
|
2025-04-15 16:28:03 +05:30
|
|
|
};
|
|
|
|
|
|
2025-04-22 10:50:08 +05:30
|
|
|
const handleCreateComment = async (postId: string, content: string): Promise<Comment | null> => {
|
|
|
|
|
setIsPostingComment(true);
|
|
|
|
|
const result = await createComment(postId, content, currentUser, isAuthenticated, toast, updateStateFromCache);
|
|
|
|
|
setIsPostingComment(false);
|
|
|
|
|
return result;
|
2025-04-15 16:28:03 +05:30
|
|
|
};
|
|
|
|
|
|
2025-04-22 10:50:08 +05:30
|
|
|
const handleVotePost = async (postId: string, isUpvote: boolean): Promise<boolean> => {
|
|
|
|
|
setIsVoting(true);
|
|
|
|
|
const result = await vote(postId, isUpvote, currentUser, isAuthenticated, toast, updateStateFromCache);
|
|
|
|
|
setIsVoting(false);
|
|
|
|
|
return result;
|
2025-04-15 16:28:03 +05:30
|
|
|
};
|
|
|
|
|
|
2025-04-22 10:50:08 +05:30
|
|
|
const handleVoteComment = async (commentId: string, isUpvote: boolean): Promise<boolean> => {
|
|
|
|
|
setIsVoting(true);
|
|
|
|
|
const result = await vote(commentId, isUpvote, currentUser, isAuthenticated, toast, updateStateFromCache);
|
|
|
|
|
setIsVoting(false);
|
|
|
|
|
return result;
|
2025-04-15 16:28:03 +05:30
|
|
|
};
|
|
|
|
|
|
2025-04-22 10:50:08 +05:30
|
|
|
const handleCreateCell = async (name: string, description: string, icon: string): Promise<Cell | null> => {
|
|
|
|
|
setIsPostingCell(true);
|
|
|
|
|
const result = await createCell(name, description, icon, currentUser, isAuthenticated, toast, updateStateFromCache);
|
|
|
|
|
setIsPostingCell(false);
|
|
|
|
|
return result;
|
2025-04-15 16:28:03 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<ForumContext.Provider
|
|
|
|
|
value={{
|
|
|
|
|
cells,
|
|
|
|
|
posts,
|
|
|
|
|
comments,
|
2025-04-22 10:39:32 +05:30
|
|
|
isInitialLoading,
|
|
|
|
|
isPostingCell,
|
|
|
|
|
isPostingPost,
|
|
|
|
|
isPostingComment,
|
|
|
|
|
isVoting,
|
|
|
|
|
isRefreshing,
|
|
|
|
|
isNetworkConnected,
|
2025-04-15 16:28:03 +05:30
|
|
|
error,
|
|
|
|
|
getCellById,
|
|
|
|
|
getPostsByCell,
|
|
|
|
|
getCommentsByPost,
|
2025-04-22 10:50:08 +05:30
|
|
|
createPost: handleCreatePost,
|
|
|
|
|
createComment: handleCreateComment,
|
|
|
|
|
votePost: handleVotePost,
|
|
|
|
|
voteComment: handleVoteComment,
|
|
|
|
|
createCell: handleCreateCell,
|
|
|
|
|
refreshData: handleRefreshData
|
2025-04-15 16:28:03 +05:30
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{children}
|
|
|
|
|
</ForumContext.Provider>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const useForum = () => {
|
|
|
|
|
const context = useContext(ForumContext);
|
|
|
|
|
if (context === undefined) {
|
2025-04-22 10:39:32 +05:30
|
|
|
throw new Error('useForum must be used within a ForumProvider');
|
2025-04-15 16:28:03 +05:30
|
|
|
}
|
|
|
|
|
return context;
|
|
|
|
|
};
|