@@ -5,6 +5,9 @@ import { FC, Fragment, ReactNode, useEffect } from "react";
55
66import useCoherenceLinksContext from "@/app/(main)/components/coherence_links_provider" ;
77import { PostStatusBox } from "@/app/(main)/questions/[id]/components/post_status_box" ;
8+ import NumericForecastCard from "@/components/consumer_post_card/group_forecast_card/numeric_forecast_card" ;
9+ import PercentageForecastCard from "@/components/consumer_post_card/group_forecast_card/percentage_forecast_card" ;
10+ import TimeSeriesChart from "@/components/consumer_post_card/time_series_chart" ;
811import UpcomingCP from "@/components/consumer_post_card/upcoming_cp" ;
912import DetailedGroupCard from "@/components/detailed_question_card/detailed_group_card" ;
1013import DetailedQuestionCard from "@/components/detailed_question_card/detailed_question_card" ;
@@ -15,14 +18,15 @@ import { useHideCP } from "@/contexts/cp_context";
1518import { useContentTranslatedBannerContext } from "@/contexts/translations_banner_context" ;
1619import {
1720 GroupOfQuestionsGraphType ,
21+ GroupOfQuestionsPost ,
1822 PostStatus ,
1923 PostWithForecasts ,
2024 QuestionStatus ,
2125} from "@/types/post" ;
2226import { TournamentType } from "@/types/projects" ;
23- import { QuestionType } from "@/types/question" ;
24- import cn from "@/utils/core/cn" ;
27+ import { QuestionType , QuestionWithNumericForecasts } from "@/types/question" ;
2528import { getQuestionForecastAvailability } from "@/utils/questions/forecastAvailability" ;
29+ import { sortGroupPredictionOptions } from "@/utils/questions/groupOrdering" ;
2630import {
2731 checkGroupOfQuestionsPostType ,
2832 isContinuousQuestion ,
@@ -40,15 +44,17 @@ import PostScoreData from "../post_score_data";
4044import { QuestionLayoutProvider } from "../question_layout/question_layout_context" ;
4145import { QuestionVariantComposer } from "../question_variant_composer" ;
4246import ActionRow from "../question_view/action_row" ;
47+ import ConsumerGroupChart from "../question_view/consumer_question_view/consumer_group_chart" ;
48+ import ConsumerListChartShell from "../question_view/consumer_question_view/consumer_list_chart_shell" ;
4349import ConsumerQuestionPrediction from "../question_view/consumer_question_view/prediction" ;
4450import QuestionTimeline from "../question_view/consumer_question_view/timeline" ;
4551import QuestionHeaderCPStatus from "../question_view/forecaster_question_view/question_header/question_header_cp_status" ;
4652import RevealCPButton from "../reveal_cp_button" ;
4753
4854const baseSectionClassName =
49- "relative z-10 flex w-[59rem] max-w-full flex-col gap-6 overflow-x-clip rounded border border-blue-400 p-4 text-gray-900 dark:border-blue-200-dark dark:text-gray-900-dark lg:p-8" ;
55+ "relative flex w-[59rem] max-w-full flex-col gap-6 overflow-x-clip rounded border border-blue-400 p-4 text-gray-900 dark:border-blue-200-dark dark:text-gray-900-dark lg:p-8" ;
5056
51- const mainSectionClassName = `${ baseSectionClassName } bg-gray-0 dark:bg-gray-0-dark` ;
57+ const mainSectionClassName = `${ baseSectionClassName } z-10 bg-gray-0 dark:bg-gray-0-dark` ;
5258const commentSectionClassName = `${ baseSectionClassName } bg-blue-100 dark:bg-gray-0-dark` ;
5359
5460type ShellProps = {
@@ -147,9 +153,6 @@ export const ConsumerShell: FC<{
147153 const isMultipleChoice = isMultipleChoicePost ( postData ) ;
148154 const isNonFanGroup = isGroupOfQuestionsPost ( postData ) && ! isFanGraph ;
149155
150- const reverseOrder =
151- ( isMultipleChoice || isGroupOfQuestionsPost ( postData ) ) && ! isDateGroup ;
152-
153156 const isContinuousSingleQuestion =
154157 isQuestionPost ( postData ) && isContinuousQuestion ( postData . question ) ;
155158
@@ -158,24 +161,36 @@ export const ConsumerShell: FC<{
158161 ! isContinuousSingleQuestion &&
159162 ! isMultipleChoice ;
160163
164+ const isNRowBody =
165+ isMultipleChoice || ( isNonFanGroup && ! isDateGroup ) || isFanGraph ;
166+
167+ const isContinuousNumericGroup =
168+ isNonFanGroup &&
169+ ! isDateGroup &&
170+ ! isMultipleChoice &&
171+ ( checkGroupOfQuestionsPostType ( postData , QuestionType . Numeric ) ||
172+ checkGroupOfQuestionsPostType ( postData , QuestionType . Discrete ) ) ;
173+
161174 const binaryForecastAvailability =
162175 isBinarySingleQuestion && isQuestionPost ( postData )
163176 ? getQuestionForecastAvailability ( postData . question )
164177 : null ;
165178
166- const showSideBySide =
167- isMultipleChoice ||
168- isNonFanGroup ||
169- isBinarySingleQuestion ||
170- isContinuousSingleQuestion ;
171-
172179 const showClosedMessageMultipleChoice =
173180 isMultipleChoicePost ( postData ) &&
174181 postData . question . status === QuestionStatus . CLOSED ;
175182
176183 const showClosedMessageFanGraph =
177184 isFanGraph && postData . status === PostStatus . CLOSED ;
178185
186+ const fanGraphQuestions = isFanGraph
187+ ? sortGroupPredictionOptions (
188+ ( postData . group_of_questions ?. questions ??
189+ [ ] ) as QuestionWithNumericForecasts [ ] ,
190+ postData . group_of_questions
191+ )
192+ : null ;
193+
179194 const questionLinkAggregates =
180195 aggregateCoherenceLinks ?. data . filter ( isDisplayableQuestionLink ) ?? [ ] ;
181196 const hasKeyFactors = ( postData . key_factors ?. length ?? 0 ) > 0 ;
@@ -218,21 +233,8 @@ export const ConsumerShell: FC<{
218233 { t ( "predictionClosedMessage" ) }
219234 </ p >
220235 ) }
221- < div
222- className = { cn (
223- "flex flex-col" ,
224- reverseOrder &&
225- ! isMultipleChoice &&
226- ! isNonFanGroup &&
227- "flex-col-reverse" ,
228- showSideBySide &&
229- cn ( "sm:flex-row sm:items-center" , {
230- "sm:gap-0 md:gap-8" : isBinarySingleQuestion ,
231- "sm:gap-8" : ! isBinarySingleQuestion ,
232- } )
233- ) }
234- >
235- { isBinarySingleQuestion && isQuestionPost ( postData ) ? (
236+ { isBinarySingleQuestion && isQuestionPost ( postData ) ? (
237+ < div className = "flex flex-col sm:flex-row sm:items-center sm:gap-0 md:gap-8" >
236238 < div className = "order-1 flex w-64 flex-col items-center justify-center gap-[18px] self-center sm:self-stretch" >
237239 { hideCP ? (
238240 < RevealCPButton />
@@ -247,47 +249,85 @@ export const ConsumerShell: FC<{
247249 />
248250 ) }
249251 </ div >
250- ) : (
251- < div
252- className = { cn (
253- showSideBySide && ! isDateGroup ? "order-1" : undefined ,
254- isContinuousSingleQuestion && "md:hidden" ,
255- showSideBySide &&
256- ! isDateGroup &&
257- ! isContinuousSingleQuestion &&
258- "sm:max-w-[200px]" ,
259- hideCP &&
260- ! isContinuousSingleQuestion &&
261- ( isDateGroup || isFanGraph ) &&
262- "flex w-full justify-center"
263- ) }
264- >
265- { hideCP && ! isContinuousSingleQuestion ? (
266- < RevealCPButton />
267- ) : (
268- < ConsumerQuestionPrediction postData = { postData } />
269- ) }
252+ < QuestionTimeline
253+ postData = { postData }
254+ keyFactors = { postData . key_factors }
255+ isConsumerView
256+ preselectedGroupQuestionId = { preselectedGroupQuestionId }
257+ className = "order-2 mt-0 hidden flex-1 sm:block"
258+ />
259+ </ div >
260+ ) : isContinuousSingleQuestion ? (
261+ < div className = "flex flex-col sm:flex-row sm:items-center sm:gap-8" >
262+ < div className = "order-1 md:hidden" >
263+ < ConsumerQuestionPrediction postData = { postData } />
270264 </ div >
271- ) }
272- { ! isFanGraph && ! isDateGroup && (
273265 < QuestionTimeline
274266 postData = { postData }
275267 keyFactors = { postData . key_factors }
276- isConsumerView = { true }
268+ isConsumerView = { false }
277269 preselectedGroupQuestionId = { preselectedGroupQuestionId }
278- className = { cn (
279- "hidden sm:block" ,
280- showSideBySide && "order-2 mt-0 flex-1" ,
281- isContinuousSingleQuestion && "mt-0"
282- ) }
270+ className = "order-2 mt-0 hidden flex-1 sm:block"
283271 />
284- ) }
285- { showClosedMessageFanGraph && (
286- < p className = "my-8 text-center text-sm leading-[20px] text-gray-700 dark:text-gray-700-dark" >
287- { t ( "predictionClosedMessage" ) }
288- </ p >
289- ) }
290- </ div >
272+ </ div >
273+ ) : isNRowBody ? (
274+ < >
275+ < ConsumerListChartShell
276+ stretchListContent = { ! hideCP && ! isFanGraph }
277+ listContent = {
278+ hideCP ? (
279+ < RevealCPButton />
280+ ) : isFanGraph && fanGraphQuestions ? (
281+ < TimeSeriesChart
282+ questions = { fanGraphQuestions }
283+ variant = "colorful"
284+ height = { 180 }
285+ />
286+ ) : isContinuousNumericGroup ? (
287+ < NumericForecastCard post = { postData } fillHeight />
288+ ) : (
289+ < PercentageForecastCard
290+ post = { postData }
291+ forceColorful
292+ fillHeight
293+ />
294+ )
295+ }
296+ chartContent = {
297+ isFanGraph ? (
298+ < DetailedGroupCard
299+ post = {
300+ postData as GroupOfQuestionsPost < QuestionWithNumericForecasts >
301+ }
302+ preselectedQuestionId = { preselectedGroupQuestionId }
303+ />
304+ ) : isContinuousNumericGroup ? (
305+ < ConsumerGroupChart
306+ post = {
307+ postData as GroupOfQuestionsPost < QuestionWithNumericForecasts >
308+ }
309+ preselectedQuestionId = { preselectedGroupQuestionId }
310+ />
311+ ) : (
312+ < QuestionTimeline
313+ postData = { postData }
314+ keyFactors = { postData . key_factors }
315+ isConsumerView
316+ preselectedGroupQuestionId = { preselectedGroupQuestionId }
317+ className = "mt-0"
318+ />
319+ )
320+ }
321+ />
322+ { showClosedMessageFanGraph && (
323+ < p className = "my-8 text-center text-sm leading-[20px] text-gray-700 dark:text-gray-700-dark" >
324+ { t ( "predictionClosedMessage" ) }
325+ </ p >
326+ ) }
327+ </ >
328+ ) : (
329+ < ConsumerQuestionPrediction postData = { postData } />
330+ ) }
291331 </ div >
292332 { shouldShowKeyFactorsSection && (
293333 < div className = "order-3 sm:order-none" >
0 commit comments