diff --git a/front_end/src/app/(main)/questions/[id]/components/question_view/forecaster_question_view/index.tsx b/front_end/src/app/(main)/questions/[id]/components/question_view/forecaster_question_view/index.tsx index 0e27865546..138f1e1831 100644 --- a/front_end/src/app/(main)/questions/[id]/components/question_view/forecaster_question_view/index.tsx +++ b/front_end/src/app/(main)/questions/[id]/components/question_view/forecaster_question_view/index.tsx @@ -1,8 +1,11 @@ -import { Fragment } from "react"; +"use client"; + +import { Fragment, useCallback, useEffect, useRef, useState } from "react"; import DetailedGroupCard from "@/components/detailed_question_card/detailed_group_card"; import DetailedQuestionCard from "@/components/detailed_question_card/detailed_question_card"; import ForecastMaker from "@/components/forecast_maker"; +import ClientPostsApi from "@/services/api/posts/posts.client"; import { PostStatus, PostWithForecasts } from "@/types/post"; import { isGroupOfQuestionsPost, @@ -20,20 +23,55 @@ const ForecasterQuestionView: React.FC = ({ postData, preselectedGroupQuestionId, }) => { - const isResolved = postData.status === PostStatus.RESOLVED; - const isGroup = isGroupOfQuestionsPost(postData); + const [currentPost, setCurrentPost] = useState(postData); + const latestRequestIdRef = useRef(0); + + // Sync local state when the server prop changes (e.g., after a + // revalidatePath-driven re-render). + useEffect(() => { + setCurrentPost(postData); + }, [postData]); + + // Refetch fresh post data (including updated CP) after a prediction is + // submitted, so sibling components (DetailedQuestionCard / + // DetailedGroupCard) render the updated CP immediately instead of waiting + // for revalidatePath to land. + const handlePredictionSubmit = useCallback(async () => { + const requestId = ++latestRequestIdRef.current; + try { + const freshPost = await ClientPostsApi.getPost(postData.id); + // Ignore stale responses if a newer request has been issued meanwhile. + if (requestId === latestRequestIdRef.current) { + setCurrentPost(freshPost); + } + } catch (err) { + // Surface the error for observability; the CP will still update on + // the next revalidation / page load. + console.error("Failed to refresh post after prediction submit:", err); + } + }, [postData.id]); + + const isResolved = currentPost.status === PostStatus.RESOLVED; + const isGroup = isGroupOfQuestionsPost(currentPost); return ( - - {isQuestionPost(postData) && } + + {isQuestionPost(currentPost) && ( + + )} {isGroup && ( )} - {(!isResolved || isGroup) && } + {(!isResolved || isGroup) && ( + + )} ); }; diff --git a/front_end/src/components/forecast_maker/index.tsx b/front_end/src/components/forecast_maker/index.tsx index a10575e4cf..77b43526a2 100644 --- a/front_end/src/components/forecast_maker/index.tsx +++ b/front_end/src/components/forecast_maker/index.tsx @@ -18,7 +18,12 @@ type Props = { const ForecastMaker: FC = ({ post, onPredictionSubmit }) => { const { user } = useAuth(); - const { group_of_questions: groupOfQuestions, conditional, question } = post; + + const { + group_of_questions: groupOfQuestions, + conditional, + question, + } = post; const canPredict = canPredictQuestion(post, user); const predictionMessage = ;