Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import DateForecastCard from "@/components/consumer_post_card/group_forecast_car
import NumericForecastCard from "@/components/consumer_post_card/group_forecast_card/numeric_forecast_card";
import PercentageForecastCard from "@/components/consumer_post_card/group_forecast_card/percentage_forecast_card";
import TimeSeriesChart from "@/components/consumer_post_card/time_series_chart";
import { useHideCP } from "@/contexts/cp_context";
import { GroupOfQuestionsGraphType, PostWithForecasts } from "@/types/post";
import { QuestionType } from "@/types/question";
import { getGroupForecastAvailability } from "@/utils/questions/forecastAvailability";
Expand All @@ -16,6 +17,7 @@ type Props = {
};

const GroupOfQuestionsPrediction: React.FC<Props> = ({ postData }) => {
const { hideCP } = useHideCP();
let content: React.ReactNode | null = null;

if (
Expand All @@ -35,8 +37,9 @@ const GroupOfQuestionsPrediction: React.FC<Props> = ({ postData }) => {

// Hide chart if no forecasts or CP not yet revealed
const shouldHideChart =
forecastAvailability &&
(forecastAvailability.isEmpty || !!forecastAvailability.cpRevealsOn);
hideCP ||
(forecastAvailability &&
(forecastAvailability.isEmpty || !!forecastAvailability.cpRevealsOn));

if (!shouldHideChart) {
const sortedQuestions = sortGroupPredictionOptions(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { getContinuousAreaChartData } from "@/components/charts/continuous_area_chart";
import MinifiedContinuousAreaChart from "@/components/charts/minified_continuous_area_chart";
import ConsumerContinuousTile from "@/components/consumer_post_card/consumer_question_tile/consumer_continuous_tile";
import { useHideCP } from "@/contexts/cp_context";
import { QuestionStatus } from "@/types/post";
import { QuestionWithNumericForecasts } from "@/types/question";
import { getQuestionForecastAvailability } from "@/utils/questions/forecastAvailability";
Expand All @@ -12,6 +13,7 @@ type Props = {
};

const ContinuousQuestionPrediction: React.FC<Props> = ({ question }) => {
const { hideCP } = useHideCP();
const forecastAvailability = getQuestionForecastAvailability(question);

// Hide chart if no forecasts or CP not yet revealed
Expand Down Expand Up @@ -40,6 +42,7 @@ const ContinuousQuestionPrediction: React.FC<Props> = ({ question }) => {
height={50}
forceTickCount={2}
variant="question"
hideCP={hideCP}
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ const MinifiedContinuousAreaChart: FC<Props> = ({
const discrete = question.type === QuestionType.Discrete;

const charts = useMemo(() => {
const parsedData = hideCP ? [] : data;
const parsedData = hideCP
? [...data].filter((el) => el.type === "user")
: data;

const chartData: NumericPredictionGraph[] = [];
for (const datum of parsedData) {
Expand Down Expand Up @@ -235,11 +237,14 @@ const MinifiedContinuousAreaChart: FC<Props> = ({
// However, if there's a resolution point, we need extra padding to prevent clipping
const hasResolution =
!isNil(question.resolution) && question.resolution !== "";
const wantsAnyXLabels = !hideCP && (!hideLabels || minMaxLabelsOnly);
const hasVisibleData = hideCP
? data.some((el) => el.type === "user")
: true;
const wantsAnyXLabels = hasVisibleData && (!hideLabels || minMaxLabelsOnly);
if (wantsAnyXLabels) return BOTTOM_PADDING;
const baseMinimalPadding = hasResolution ? 8 : 3; // Extra padding for resolution diamond
return baseMinimalPadding;
}, [hideCP, hideLabels, minMaxLabelsOnly, question.resolution]);
}, [data, hideCP, hideLabels, minMaxLabelsOnly, question.resolution]);

return (
<div ref={chartContainerRef} className="h-full w-full" style={{ height }}>
Expand Down Expand Up @@ -391,7 +396,7 @@ const MinifiedContinuousAreaChart: FC<Props> = ({
<VictoryAxis
tickValues={xScale.ticks}
tickFormat={(tick: number, index?: number, ticks?: number[]) => {
if (hideCP) return "";
if (hideCP && !data.some((el) => el.type === "user")) return "";

if (hideLabels && !minMaxLabelsOnly) return "";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { FC } from "react";

import ContinuousCPBar from "@/components/consumer_post_card/consumer_question_tile/continuous_cp_bar";
import QuestionContinuousResolutionChip from "@/components/consumer_post_card/question_continuous_resolution_chip";
import { useHideCP } from "@/contexts/cp_context";
import { QuestionStatus } from "@/types/post";
import { ForecastAvailability, QuestionWithForecasts } from "@/types/question";
import { getPredictionDisplayValue } from "@/utils/formatters/prediction";
Expand All @@ -19,6 +20,7 @@ const ConsumerContinuousTile: FC<Props> = ({
forecastAvailability,
variant = "feed",
}) => {
const { hideCP } = useHideCP();
const locale = useLocale();

const latest =
Expand Down Expand Up @@ -55,7 +57,9 @@ const ConsumerContinuousTile: FC<Props> = ({
return (
<div className="flex max-w-[200px] flex-col items-center justify-center gap-3">
<ContinuousCPBar
communityPredictionDisplayValue={communityPredictionDisplayValue}
communityPredictionDisplayValue={
hideCP ? "-/-" : communityPredictionDisplayValue
}
isClosed={question.status === QuestionStatus.CLOSED}
forecastAvailability={forecastAvailability}
variant={variant}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FC } from "react";

import { getContinuousAreaChartData } from "@/components/charts/continuous_area_chart";
import MinifiedContinuousAreaChart from "@/components/charts/minified_continuous_area_chart";
import { useHideCP } from "@/contexts/cp_context";
import { QuestionStatus } from "@/types/post";
import { QuestionType, QuestionWithForecasts } from "@/types/question";
import { getQuestionForecastAvailability } from "@/utils/questions/forecastAvailability";
Expand All @@ -13,11 +14,14 @@ type Props = {
};

const ConsumerQuestionTile: FC<Props> = ({ question }) => {
const { hideCP } = useHideCP();
const forecastAvailability = getQuestionForecastAvailability(question);

// Hide chart if no forecasts or CP not yet revealed
const shouldHideChart =
forecastAvailability.isEmpty || !!forecastAvailability.cpRevealsOn;
hideCP ||
forecastAvailability.isEmpty ||
!!forecastAvailability.cpRevealsOn;

// Open/Closed - delegate to specific tile components based on question type
switch (question.type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import NumericForecastCard from "@/components/consumer_post_card/group_forecast_card/numeric_forecast_card";
import { darkTheme, lightTheme } from "@/constants/chart_theme";
import { METAC_COLORS } from "@/constants/colors";
import { useHideCP } from "@/contexts/cp_context";
import useAppTheme from "@/hooks/use_app_theme";
import useContainerSize from "@/hooks/use_container_size";
import { ChoiceItem } from "@/types/choices";
Expand Down Expand Up @@ -53,6 +54,7 @@ const DateForecastCard: FC<Props> = ({
questionsGroup,
height = 100,
}) => {
const { hideCP } = useHideCP();
const { questions } = questionsGroup;
const locale = useLocale();
const t = useTranslations();
Expand Down Expand Up @@ -86,8 +88,8 @@ const DateForecastCard: FC<Props> = ({
});
};

if (points.length === 0) {
// Render empty state taken from the Numeric representation
if (points.length === 0 || hideCP) {
// Render list representation (with hidden values when hideCP)
return <NumericForecastCard post={post} />;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FC } from "react";

import { useHideCP } from "@/contexts/cp_context";
import { GroupOfQuestionsGraphType, PostWithForecasts } from "@/types/post";
import { QuestionType } from "@/types/question";
import { getGroupForecastAvailability } from "@/utils/questions/forecastAvailability";
Expand All @@ -19,15 +20,18 @@ type Props = {
};

const GroupForecastCard: FC<Props> = ({ post }) => {
const { hideCP } = useHideCP();

// Check forecast availability for group posts
const forecastAvailability = post.group_of_questions
? getGroupForecastAvailability(post.group_of_questions.questions)
: null;

// Hide chart if no forecasts or CP not yet revealed
const shouldHideChart =
forecastAvailability &&
(forecastAvailability.isEmpty || !!forecastAvailability.cpRevealsOn);
hideCP ||
(forecastAvailability &&
(forecastAvailability.isEmpty || !!forecastAvailability.cpRevealsOn));

if (
post.group_of_questions?.graph_type === GroupOfQuestionsGraphType.FanGraph
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { isNil } from "lodash";
import { useLocale, useTranslations } from "next-intl";
import { FC, useState } from "react";

import { useHideCP } from "@/contexts/cp_context";
import { PostStatus, PostWithForecasts } from "@/types/post";
import { QuestionType, Scaling } from "@/types/question";
import { getPredictionDisplayValue } from "@/utils/formatters/prediction";
Expand All @@ -26,6 +27,7 @@ const NumericForecastCard: FC<Props> = ({ post, forceColorful }) => {
const visibleChoicesCount = 3;
const locale = useLocale();
const t = useTranslations();
const { hideCP } = useHideCP();
const [expanded, setExpanded] = useState(false);

if (!isGroupOfQuestionsPost(post)) {
Expand Down Expand Up @@ -104,29 +106,32 @@ const NumericForecastCard: FC<Props> = ({ post, forceColorful }) => {
range_max: scaling?.range_max ?? 1,
zero_point: scaling?.zero_point ?? null,
};
const formattedChoiceValue = getPredictionDisplayValue(
rawChoiceValue,
{
questionType: isDateGroup
? QuestionType.Date
: QuestionType.Numeric,
scaling: normalizedScaling,
actual_resolve_time: actual_resolve_time ?? null,
emptyLabel: t("Upcoming"),
}
);
const formattedChoiceValue =
hideCP && isNil(resolution)
? "—"
: getPredictionDisplayValue(rawChoiceValue, {
questionType: isDateGroup
? QuestionType.Date
: QuestionType.Numeric,
scaling: normalizedScaling,
actual_resolve_time: actual_resolve_time ?? null,
emptyLabel: t("Upcoming"),
});

const scaledChoiceValue = !isNil(rawChoiceValue)
? scaleInternalLocation(rawChoiceValue, normalizedScaling)
: NaN;

const relativeWidth = !isNil(resolution)
? 100
: calculateRelativeWidth({
scaledChoiceValue,
maxScaledValue,
minScaledValue,
});
const relativeWidth =
hideCP && isNil(resolution)
? 0
: !isNil(resolution)
? 100
: calculateRelativeWidth({
scaledChoiceValue,
maxScaledValue,
minScaledValue,
});

return (
<ForecastChoiceBar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { useLocale, useTranslations } from "next-intl";
import { FC, useMemo, useState } from "react";

import { useHideCP } from "@/contexts/cp_context";
import { PostStatus, PostWithForecasts } from "@/types/post";
import { QuestionType } from "@/types/question";
import { getPredictionDisplayValue } from "@/utils/formatters/prediction";
Expand All @@ -27,6 +28,7 @@ const PercentageForecastCard: FC<Props> = ({ post, forceColorful }) => {
const visibleChoicesCount = 3;
const locale = useLocale();
const t = useTranslations();
const { hideCP } = useHideCP();
const [expanded, setExpanded] = useState(false);

const isMC = isMultipleChoicePost(post);
Expand All @@ -44,19 +46,21 @@ const PercentageForecastCard: FC<Props> = ({ post, forceColorful }) => {
const allChoices = useMemo(() => {
const raw = generateChoiceItems(post, visibleChoicesCount, locale, t);
return raw.map((choice) => {
const valueStr = getPredictionDisplayValue(
choice.aggregationValues.at(-1),
{
questionType: QuestionType.Binary,
scaling: choice.scaling,
actual_resolve_time: choice.actual_resolve_time ?? null,
emptyLabel,
}
);
const valueStr =
hideCP && !choice.resolution
? "—"
: getPredictionDisplayValue(choice.aggregationValues.at(-1), {
questionType: QuestionType.Binary,
scaling: choice.scaling,
actual_resolve_time: choice.actual_resolve_time ?? null,
emptyLabel,
});
const percent =
typeof valueStr === "string"
? Number(valueStr.replace("%", "")) || 0
: 0;
hideCP && !choice.resolution
? 0
: typeof valueStr === "string"
? Number(valueStr.replace("%", "")) || 0
: 0;

const isChoiceClosed = choice.closeTime
? choice.closeTime < Date.now()
Expand All @@ -69,7 +73,7 @@ const PercentageForecastCard: FC<Props> = ({ post, forceColorful }) => {
isChoiceClosed,
};
});
}, [post, locale, t, emptyLabel]);
}, [post, locale, t, emptyLabel, hideCP]);

if (!isMC && !isGroupOfQuestionsPost(post)) return null;

Expand Down
Loading