Skip to content

Commit ad9b7c1

Browse files
committed
fix: wire hideCP, cpRevealsOn, and isEmpty states into all question-type left panels for the side-by-side layout
1 parent 845a72e commit ad9b7c1

10 files changed

Lines changed: 185 additions & 96 deletions

File tree

front_end/src/app/(main)/questions/[id]/components/key_factors/key_factors_question_consumer_section.tsx

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ import { useCommentsFeed } from "@/app/(main)/components/comments_feed_provider"
77
import { openKeyFactorsSectionAndScrollTo } from "@/app/(main)/questions/[id]/components/key_factors/utils";
88
import { PostStatus, PostWithForecasts } from "@/types/post";
99
import { sendAnalyticsEvent } from "@/utils/analytics";
10+
import { getQuestionForecastAvailability } from "@/utils/questions/forecastAvailability";
11+
import { isQuestionPost } from "@/utils/questions/helpers";
1012

1113
import {
1214
MAX_TOP_KEY_FACTORS,
1315
useTopKeyFactorsCarouselItems,
1416
} from "./hooks/use_top_key_factors_carousel_items";
1517
import KeyFactorDetailOverlay from "./key_factor_detail_overlay";
18+
import KeyFactorsCarousel from "./key_factors_carousel";
1619
import KeyFactorsConsumerCarousel from "./key_factors_consumer_carousel";
1720
import { useShouldHideKeyFactors } from "./use_should_hide_key_factors";
1821
import { useQuestionLayout } from "../question_layout/question_layout_context";
@@ -41,14 +44,21 @@ const KeyFactorsQuestionConsumerSection: FC<Props> = ({ post }) => {
4144

4245
if (post.status === PostStatus.RESOLVED) return null;
4346

47+
const postForecastAvailability = isQuestionPost(post)
48+
? getQuestionForecastAvailability(post.question)
49+
: null;
50+
const forecastIsEmpty =
51+
!!postForecastAvailability?.isEmpty &&
52+
!postForecastAvailability?.cpRevealsOn;
53+
54+
if (topItems.length === 0 && !forecastIsEmpty) return null;
55+
4456
const openKeyFactorsElement = (selector: string) => {
4557
requestKeyFactorsExpand?.();
4658
openKeyFactorsSectionAndScrollTo({ selector, mobileOnly: false });
4759
sendAnalyticsEvent("KeyFactorClick", { event_label: "fromTopList" });
4860
};
4961

50-
if (topItems.length === 0) return null;
51-
5262
return (
5363
<div
5464
className="-ml-4 flex w-[calc(100%+32px)] flex-col pb-4 sm:ml-0 sm:mt-8 sm:w-full"
@@ -58,18 +68,33 @@ const KeyFactorsQuestionConsumerSection: FC<Props> = ({ post }) => {
5868
<div className="text-sm text-blue-800 dark:text-blue-800-dark">
5969
{t("topKeyFactors")}
6070
</div>
61-
<button
62-
onClick={() => {
63-
openKeyFactorsElement("[id='key-factors']");
64-
sendAnalyticsEvent("KeyFactorViewAllClick");
65-
}}
66-
className="text-center text-sm font-normal leading-5 text-blue-600 hover:text-blue-700 dark:text-blue-600-dark dark:hover:text-blue-700-dark"
67-
>
68-
{t("viewAll", { count: totalCount })}
69-
</button>
71+
{!forecastIsEmpty && (
72+
<button
73+
onClick={() => {
74+
openKeyFactorsElement("[id='key-factors']");
75+
sendAnalyticsEvent("KeyFactorViewAllClick");
76+
}}
77+
className="text-center text-sm font-normal leading-5 text-blue-600 hover:text-blue-700 dark:text-blue-600-dark dark:hover:text-blue-700-dark"
78+
>
79+
{t("viewAll", { count: totalCount })}
80+
</button>
81+
)}
7082
</div>
7183

72-
<KeyFactorsConsumerCarousel post={post} items={topItems} />
84+
{forecastIsEmpty ? (
85+
<KeyFactorsCarousel
86+
listClassName="pb-0 [&>:first-child]:pl-4 [&>:last-child]:pr-4 sm:[&>:first-child]:pl-0 sm:[&>:last-child]:pr-0"
87+
items={Array.from({ length: 5 })}
88+
renderItem={(_, i) => (
89+
<div
90+
key={i}
91+
className="h-[196px] w-[160px] shrink-0 rounded-xl bg-blue-200 dark:bg-blue-200-dark sm:w-[200px]"
92+
/>
93+
)}
94+
/>
95+
) : (
96+
<KeyFactorsConsumerCarousel post={post} items={topItems} />
97+
)}
7398

7499
{keyFactorOverlay?.kind === "keyFactor" && (
75100
<KeyFactorDetailOverlay

front_end/src/app/(main)/questions/[id]/components/multiple_choices_chart_view/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,10 +319,11 @@ const MultiChoicesChartView: FC<Props> = ({
319319
)}
320320

321321
{isTooltipActive &&
322+
!hideCP &&
323+
!forecastAvailability?.cpRevealsOn &&
322324
!activeTimelineMarkerId &&
323325
(tooltipChoices.length > 0 ||
324326
!!tooltipUserChoices?.length ||
325-
!!forecastAvailability?.cpRevealsOn ||
326327
!!forecastAvailability?.isEmpty) && (
327328
<FloatingPortal>
328329
<div

front_end/src/app/(main)/questions/[id]/components/question_page_shell/index.tsx

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,14 @@ export const ConsumerShell: FC<{
179179
aggregateCoherenceLinks?.data.filter(isDisplayableQuestionLink) ?? [];
180180
const hasKeyFactors = (postData.key_factors?.length ?? 0) > 0;
181181
const hasQuestionLinks = questionLinkAggregates.length > 0;
182-
const shouldShowKeyFactorsSection = hasKeyFactors || hasQuestionLinks;
182+
const questionForecastAvailability = isQuestionPost(postData)
183+
? getQuestionForecastAvailability(postData.question)
184+
: null;
185+
const isForecastEmpty =
186+
!!questionForecastAvailability?.isEmpty &&
187+
!questionForecastAvailability?.cpRevealsOn;
188+
const shouldShowKeyFactorsSection =
189+
hasKeyFactors || hasQuestionLinks || isForecastEmpty;
183190

184191
return (
185192
<div className="flex flex-col gap-1.5 md:gap-4">
@@ -243,10 +250,22 @@ export const ConsumerShell: FC<{
243250
<div
244251
className={cn(
245252
showSideBySide && !isDateGroup ? "order-1" : undefined,
246-
isContinuousSingleQuestion && "md:hidden"
253+
isContinuousSingleQuestion && "md:hidden",
254+
showSideBySide &&
255+
!isDateGroup &&
256+
!isContinuousSingleQuestion &&
257+
"sm:max-w-[200px]",
258+
hideCP &&
259+
!isContinuousSingleQuestion &&
260+
(isDateGroup || isFanGraph) &&
261+
"flex w-full justify-center"
247262
)}
248263
>
249-
<ConsumerQuestionPrediction postData={postData} />
264+
{hideCP && !isContinuousSingleQuestion ? (
265+
<RevealCPButton />
266+
) : (
267+
<ConsumerQuestionPrediction postData={postData} />
268+
)}
250269
</div>
251270
)}
252271
{!isFanGraph && !isDateGroup && (

front_end/src/app/(main)/questions/[id]/components/question_page_shell/title_row.tsx

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@ import { FC } from "react";
44

55
import QuestionHeaderCPStatus from "@/app/(main)/questions/[id]/components/question_view/forecaster_question_view/question_header/question_header_cp_status";
66
import QuestionTitle from "@/app/(main)/questions/[id]/components/question_view/shared/question_title";
7+
import RevealCPButton from "@/app/(main)/questions/[id]/components/reveal_cp_button";
78
import ConditionalTile from "@/components/conditional_tile";
89
import { useHideCP } from "@/contexts/cp_context";
910
import { PostWithForecasts } from "@/types/post";
10-
import { QuestionWithForecasts } from "@/types/question";
11+
import { QuestionType, QuestionWithForecasts } from "@/types/question";
1112
import cn from "@/utils/core/cn";
1213
import {
1314
isConditionalPost,
1415
isContinuousQuestion,
16+
isGroupOfQuestionsPost,
1517
isQuestionPost,
1618
} from "@/utils/questions/helpers";
1719

@@ -35,6 +37,9 @@ const TitleRow: FC<Props> = ({ post, variant, className }) => {
3537
}
3638

3739
if (variant === "forecaster" && isQuestionPost(post)) {
40+
const isMultipleChoice = post.question.type === QuestionType.MultipleChoice;
41+
const isContinuous = isContinuousQuestion(post.question);
42+
3843
return (
3944
<div
4045
className={cn(
@@ -53,20 +58,62 @@ const TitleRow: FC<Props> = ({ post, variant, className }) => {
5358
{post.title}
5459
</QuestionTitle>
5560
<div className="shrink-0 self-center md:hidden">
61+
{isMultipleChoice ? (
62+
hideCP && <RevealCPButton className="whitespace-nowrap" />
63+
) : (
64+
<QuestionHeaderCPStatus
65+
question={post.question as QuestionWithForecasts}
66+
size="md"
67+
hideLabel={isContinuous}
68+
/>
69+
)}
70+
</div>
71+
</div>
72+
</div>
73+
{!isContinuous && (
74+
<div className="hidden shrink-0 md:block">
75+
{isMultipleChoice && hideCP ? (
76+
<RevealCPButton className="whitespace-nowrap" />
77+
) : (
5678
<QuestionHeaderCPStatus
5779
question={post.question as QuestionWithForecasts}
58-
size="md"
59-
hideLabel={isContinuousQuestion(post.question)}
80+
size="lg"
6081
/>
61-
</div>
82+
)}
83+
</div>
84+
)}
85+
</div>
86+
);
87+
}
88+
89+
if (variant === "forecaster" && isGroupOfQuestionsPost(post)) {
90+
return (
91+
<div
92+
className={cn(
93+
"flex w-full items-stretch justify-between gap-2 xs:gap-4 sm:gap-8",
94+
className
95+
)}
96+
>
97+
<div className="flex min-w-0 flex-1 flex-col">
98+
<div
99+
className={cn(
100+
"lg:order-0 order-1 flex gap-2",
101+
hideCP ? "flex-col" : "items-center"
102+
)}
103+
>
104+
<QuestionTitle className="min-w-0 break-words text-xl font-bold leading-tight tracking-[-0.4px] text-blue-800 dark:text-blue-800-dark sm:text-3xl sm:tracking-tight lg:text-4xl">
105+
{post.title}
106+
</QuestionTitle>
107+
{hideCP && (
108+
<div className="shrink-0 self-center md:hidden">
109+
<RevealCPButton className="whitespace-nowrap" />
110+
</div>
111+
)}
62112
</div>
63113
</div>
64-
{!isContinuousQuestion(post.question) && (
114+
{hideCP && (
65115
<div className="hidden shrink-0 md:block">
66-
<QuestionHeaderCPStatus
67-
question={post.question as QuestionWithForecasts}
68-
size="lg"
69-
/>
116+
<RevealCPButton className="whitespace-nowrap" />
70117
</div>
71118
)}
72119
</div>

front_end/src/app/(main)/questions/[id]/components/question_view/forecaster_question_view/question_header/question_header_cp_status.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ const QuestionHeaderCPStatus: FC<Props> = ({
113113
"min-h-full w-[200px]": size === "lg" && hideLabel,
114114
"w-max max-w-[200px]": size === "lg" && !hideLabel,
115115
"max-w-[130px]":
116-
size === "md" || (isEmbed && !isEmbedBelow376 && !isEmbedWide),
116+
!forecastAvailability.cpRevealsOn &&
117+
(size === "md" || (isEmbed && !isEmbedBelow376 && !isEmbedWide)),
117118
"gap-1": !hideLabel && size === "lg",
118119
"gap-0": size === "md",
119120
"-gap-2": size === "md" && hideLabel,
@@ -144,7 +145,10 @@ const QuestionHeaderCPStatus: FC<Props> = ({
144145
style={borderStyle}
145146
className={cn(containerClassName, "items-center justify-center")}
146147
>
147-
<UpcomingCP cpRevealsOn={forecastAvailability.cpRevealsOn} />
148+
<UpcomingCP
149+
cpRevealsOn={forecastAvailability.cpRevealsOn}
150+
className="whitespace-nowrap"
151+
/>
148152
</div>
149153
);
150154
}
@@ -293,7 +297,7 @@ const QuestionHeaderCPStatus: FC<Props> = ({
293297
{!!forecastAvailability.cpRevealsOn && !isEmbed && (
294298
<UpcomingCP
295299
cpRevealsOn={forecastAvailability.cpRevealsOn}
296-
className="mt-2"
300+
className="mt-2 whitespace-nowrap"
297301
/>
298302
)}
299303
</div>

front_end/src/components/charts/fan_chart.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ const FanChart: FC<Props> = ({
452452
domainPadding={v.domainPadding(variantArgs)}
453453
padding={chartPadding}
454454
containerComponent={
455-
withTooltip ? (
455+
withTooltip && !hideCP && !forecastAvailability?.cpRevealsOn ? (
456456
containerWithTooltip
457457
) : (
458458
<VictoryContainer

front_end/src/components/charts/group_chart.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,9 @@ const GroupChart: FC<Props> = ({
386386
},
387387
]}
388388
containerComponent={
389-
onCursorChange ? (
389+
onCursorChange &&
390+
!hideCP &&
391+
!forecastAvailability?.cpRevealsOn ? (
390392
CursorContainer
391393
) : (
392394
<VictoryContainer

front_end/src/components/charts/multiple_choice_chart.tsx

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ import { scaleInternalLocation, unscaleNominalLocation } from "@/utils/math";
5151

5252
import ChartContainer from "./primitives/chart_container";
5353
import ChartCursorLabel from "./primitives/chart_cursor_label";
54+
import SvgWrapper from "./primitives/svg_wrapper";
5455
import XTickLabel from "./primitives/x_tick_label";
5556
import ForecastAvailabilityChartOverflow from "../post_card/chart_overflow";
56-
import SvgWrapper from "./primitives/svg_wrapper";
5757
import YTickLabel from "./primitives/y_tick_label";
5858

5959
type ColoredLinePoint = {
@@ -321,7 +321,9 @@ const MultipleChoiceChart: FC<Props> = ({
321321
},
322322
]}
323323
containerComponent={
324-
onCursorChange ? (
324+
onCursorChange &&
325+
!hideCP &&
326+
!forecastAvailability?.cpRevealsOn ? (
325327
CursorContainer
326328
) : (
327329
<VictoryContainer
@@ -395,15 +397,16 @@ const MultipleChoiceChart: FC<Props> = ({
395397
axis: {
396398
stroke: "transparent",
397399
},
398-
grid: isEmptyDomain
399-
? {
400-
stroke: getThemeColor(METAC_COLORS.gray["300"]),
401-
strokeWidth: 1,
402-
strokeDasharray: "2, 5",
403-
}
404-
: {
405-
stroke: "transparent",
406-
},
400+
grid:
401+
isEmptyDomain || hideCP
402+
? {
403+
stroke: getThemeColor(METAC_COLORS.gray["300"]),
404+
strokeWidth: 1,
405+
strokeDasharray: "2, 5",
406+
}
407+
: {
408+
stroke: "transparent",
409+
},
407410
}}
408411
label={yLabel}
409412
offsetX={

0 commit comments

Comments
 (0)