diff --git a/front_end/messages/cs.json b/front_end/messages/cs.json index a8c40d43da..b4c5c8cdef 100644 --- a/front_end/messages/cs.json +++ b/front_end/messages/cs.json @@ -1847,10 +1847,10 @@ "hostPrivateInstances": "Hostujte soukromé instance", "hostPrivateInstancesDescription": "Objevte poznatky z vaší organizace", "whatsMetaculus": "Co je Metaculus?", - "metaculusDescription": "Metaculus je online platforma pro předpovídání a agregační nástroj, který pracuje na zlepšení lidského uvažování a koordinace v tématech globálního významu.", + "metaculusDescription": "Metaculus je online platforma pro předpovídání zaměřená na témata globálního významu.", "openQuestions": "Otevřené otázky", "forecastsSubmitted": "Odeslaných předpovědí", - "yearsOfPrediction": "Let předpovídání", + "yearsOfPrediction": "let předpovědí", "featuredIn": "Zmíněno v", "popular": "Populární", "exploreAll": "Prozkoumat vše", diff --git a/front_end/messages/en.json b/front_end/messages/en.json index 6669e673e7..e9660cc08b 100644 --- a/front_end/messages/en.json +++ b/front_end/messages/en.json @@ -4,10 +4,10 @@ "exploreAll": "Explore all", "thousandsOfOpenQuestions": "20,000+ open questions", "whatsMetaculus": "What's Metaculus?", - "metaculusDescription": "Metaculus is an online forecasting platform and aggregation engine working to improve human reasoning and coordination on topics of global importance.", - "openQuestions": "Open questions", - "forecastsSubmitted": "Forecasts submitted", - "yearsOfPrediction": "Years of prediction", + "metaculusDescription": "Metaculus is an online forecasting platform focusing on topics of global importance.", + "openQuestions": "open questions", + "forecastsSubmitted": "forecasts submitted", + "yearsOfPrediction": "years of predictions", "featuredIn": "Featured in", "hero1TopTitle": "Metaculus Platform", "heroIndividualsTitle": "Make decisions based on trusted community forecasts", diff --git a/front_end/messages/es.json b/front_end/messages/es.json index db4d78a446..b5c7591329 100644 --- a/front_end/messages/es.json +++ b/front_end/messages/es.json @@ -1847,10 +1847,10 @@ "hostPrivateInstances": "Aloja instancias privadas", "hostPrivateInstancesDescription": "Descubre información desde dentro de tu organización", "whatsMetaculus": "¿Qué es Metaculus?", - "metaculusDescription": "Metaculus es una plataforma de pronósticos en línea y motor de agregación que trabaja para mejorar el razonamiento humano y la coordinación en temas de importancia global.", + "metaculusDescription": "Metaculus es una plataforma de pronósticos en línea enfocada en temas de importancia global.", "openQuestions": "Preguntas abiertas", "forecastsSubmitted": "Pronósticos enviados", - "yearsOfPrediction": "Años de predicción", + "yearsOfPrediction": "años de predicciones", "featuredIn": "Destacado en", "popular": "Popular", "exploreAll": "Explorar todo", diff --git a/front_end/messages/pt.json b/front_end/messages/pt.json index 4cde38ede3..173e7f4344 100644 --- a/front_end/messages/pt.json +++ b/front_end/messages/pt.json @@ -1845,10 +1845,10 @@ "hostPrivateInstances": "Hospede instâncias privadas", "hostPrivateInstancesDescription": "Descubra insights de dentro da sua organização", "whatsMetaculus": "O que é Metaculus?", - "metaculusDescription": "Metaculus é uma plataforma de previsões online e motor de agregação que trabalha para melhorar o raciocínio humano e a coordenação em temas de importância global.", + "metaculusDescription": "Metaculus é uma plataforma de previsões online focada em temas de importância global.", "openQuestions": "Perguntas abertas", "forecastsSubmitted": "Previsões enviadas", - "yearsOfPrediction": "Anos de previsão", + "yearsOfPrediction": "anos de previsões", "featuredIn": "Destaque em", "popular": "Popular", "exploreAll": "Explorar tudo", diff --git a/front_end/messages/zh-TW.json b/front_end/messages/zh-TW.json index 7c07770efa..0db0d9b67e 100644 --- a/front_end/messages/zh-TW.json +++ b/front_end/messages/zh-TW.json @@ -1844,10 +1844,10 @@ "hostPrivateInstances": "託管私有實例", "hostPrivateInstancesDescription": "從您的組織內部發掘見解", "whatsMetaculus": "什麼是 Metaculus?", - "metaculusDescription": "Metaculus 是一個線上預測平台和聚合引擎,致力於改善人類在全球重要議題上的推理和協調能力。", + "metaculusDescription": "Metaculus 是一個專注於全球重要議題的線上預測平台。", "openQuestions": "開放問題", "forecastsSubmitted": "已提交預測", - "yearsOfPrediction": "預測年數", + "yearsOfPrediction": "年預測歷史", "featuredIn": "媒體報導", "popular": "熱門", "exploreAll": "探索全部", diff --git a/front_end/messages/zh.json b/front_end/messages/zh.json index feb50e70b1..0ac411daee 100644 --- a/front_end/messages/zh.json +++ b/front_end/messages/zh.json @@ -1849,10 +1849,10 @@ "hostPrivateInstances": "托管私有实例", "hostPrivateInstancesDescription": "从您的组织内部发掘见解", "whatsMetaculus": "什么是 Metaculus?", - "metaculusDescription": "Metaculus 是一个在线预测平台和聚合引擎,致力于改善人类在全球重要议题上的推理和协调能力。", + "metaculusDescription": "Metaculus 是一个专注于全球重要议题的在线预测平台。", "openQuestions": "开放问题", "forecastsSubmitted": "已提交预测", - "yearsOfPrediction": "预测年数", + "yearsOfPrediction": "年预测历史", "featuredIn": "媒体报道", "popular": "热门", "exploreAll": "探索全部", diff --git a/front_end/src/app/(main)/(home)/components/homepage_filters.ts b/front_end/src/app/(main)/(home)/components/homepage_filters.ts index 5f957315d9..04f0de9d1d 100644 --- a/front_end/src/app/(main)/(home)/components/homepage_filters.ts +++ b/front_end/src/app/(main)/(home)/components/homepage_filters.ts @@ -2,11 +2,11 @@ import { PostsParams } from "@/services/api/posts/posts.shared"; import { PostForecastType } from "@/types/post"; import { QuestionType } from "@/types/question"; -export type TabId = "popular" | "news" | "new"; +export type TabId = "news" | "popular" | "new"; export const TABS: { id: TabId; label: string }[] = [ - { id: "popular", label: "Popular" }, { id: "news", label: "In the news" }, + { id: "popular", label: "Popular" }, { id: "new", label: "New" }, ]; diff --git a/front_end/src/app/(main)/(home)/components/homepage_forecasts.tsx b/front_end/src/app/(main)/(home)/components/homepage_forecasts.tsx index c380914c2d..d2b4abef01 100644 --- a/front_end/src/app/(main)/(home)/components/homepage_forecasts.tsx +++ b/front_end/src/app/(main)/(home)/components/homepage_forecasts.tsx @@ -4,53 +4,54 @@ import Link from "next/link"; import { useTranslations } from "next-intl"; import { FC, useState, useTransition } from "react"; -import PostCard from "@/components/post_card"; +import { Tabs, TabsList, TabsTab } from "@/components/ui/tabs"; import { useBreakpoint } from "@/hooks/tailwind"; import ClientPostsApi from "@/services/api/posts/posts.client"; import { PostWithForecasts } from "@/types/post"; import cn from "@/utils/core/cn"; -import { ExploreImagesGrid } from "./ExploreImagesGrid"; import { FILTERS, TABS, TabId } from "./homepage_filters"; +import HomepagePostCard from "./homepage_post_card"; type Props = { - initialPopularPosts: PostWithForecasts[]; + initialPosts: PostWithForecasts[]; className?: string; }; -const HomePageForecasts: FC = ({ initialPopularPosts, className }) => { +const HomePageForecasts: FC = ({ initialPosts, className }) => { const t = useTranslations(); - const [activeTab, setActiveTab] = useState("popular"); - const [posts, setPosts] = useState(initialPopularPosts); + const [activeTab, setActiveTab] = useState("news"); + const [posts, setPosts] = useState(initialPosts); const [isPending, startTransition] = useTransition(); const [cachedPosts, setCachedPosts] = useState< Partial> >({ - popular: initialPopularPosts, + news: initialPosts, }); const tabLabels: Record = { - popular: t("popular"), news: t("inTheNews"), + popular: t("popular"), new: t("new"), }; - const handleTabChange = (tabId: TabId) => { - if (tabId === activeTab) return; + const handleTabChange = (tabId: string) => { + const id = tabId as TabId; + if (id === activeTab) return; - setActiveTab(tabId); + setActiveTab(id); - if (cachedPosts[tabId]) { - setPosts(cachedPosts[tabId] ?? []); + if (cachedPosts[id]) { + setPosts(cachedPosts[id] ?? []); return; } startTransition(async () => { const response = await ClientPostsApi.getPostsWithCPForHomepage( - FILTERS[tabId] + FILTERS[id] ); const newPosts = response.results; - setCachedPosts((prev) => ({ ...prev, [tabId]: newPosts })); + setCachedPosts((prev) => ({ ...prev, [id]: newPosts })); setPosts(newPosts); }); }; @@ -60,37 +61,39 @@ const HomePageForecasts: FC = ({ initialPopularPosts, className }) => { return (
-

- {t("forecasts")} -

- -
- {TABS.map((tab) => ( - - ))} -
+ + + {TABS.map((tab) => ( + + !isActive + ? "hover:bg-blue-400 dark:hover:bg-blue-400-dark text-blue-800 dark:text-blue-800-dark" + : "" + } + scrollOnSelect={false} + > + {tabLabels[tab.id]} + + ))} + +
{visiblePosts.map((post) => ( -
- -
+ ))} @@ -104,21 +107,17 @@ const ExploreAllCard: FC = () => { return (
{t("exploreAll")}
-

+

{t("thousandsOfOpenQuestions")}

- -
- -
); }; diff --git a/front_end/src/app/(main)/(home)/components/homepage_post_card.tsx b/front_end/src/app/(main)/(home)/components/homepage_post_card.tsx new file mode 100644 index 0000000000..2695c9518d --- /dev/null +++ b/front_end/src/app/(main)/(home)/components/homepage_post_card.tsx @@ -0,0 +1,72 @@ +"use client"; + +import Link from "next/link"; +import { FC } from "react"; + +import ForecastersCounter from "@/app/(main)/questions/components/forecaster_counter"; +import ConsumerQuestionTile from "@/components/consumer_post_card/consumer_question_tile"; +import GroupForecastCard from "@/components/consumer_post_card/group_forecast_card"; +import CommentStatus from "@/components/post_card/basic_post_card/comment_status"; +import PostCardErrorBoundary from "@/components/post_card/error_boundary"; +import HideCPProvider from "@/contexts/cp_context"; +import { PostWithForecasts } from "@/types/post"; +import cn from "@/utils/core/cn"; +import { getPostLink } from "@/utils/navigation"; +import { + isGroupOfQuestionsPost, + isMultipleChoicePost, + isQuestionPost, +} from "@/utils/questions/helpers"; + +type Props = { + post: PostWithForecasts; + className?: string; +}; + +const HomepagePostCard: FC = ({ post, className }) => { + const { title } = post; + + return ( + +
+
+
+ + +
+
+

+ {title} +

+ + {isQuestionPost(post) && !isMultipleChoicePost(post) && ( + + )} + + {(isGroupOfQuestionsPost(post) || isMultipleChoicePost(post)) && ( + + )} + +
+ +
+
+
+ ); +}; + +export default HomepagePostCard; diff --git a/front_end/src/app/(main)/(home)/components/why_metaculus.tsx b/front_end/src/app/(main)/(home)/components/why_metaculus.tsx index 032bbea1cd..17f2ffc6a8 100644 --- a/front_end/src/app/(main)/(home)/components/why_metaculus.tsx +++ b/front_end/src/app/(main)/(home)/components/why_metaculus.tsx @@ -5,6 +5,7 @@ import React, { FC, useEffect, useState } from "react"; import ClientMiscApi from "@/services/api/misc/misc.client"; import cn from "@/utils/core/cn"; +import { abbreviatedNumber } from "@/utils/formatters/number"; import { NasdaqLogo, @@ -20,40 +21,40 @@ const FEATURED_IN = [ href: "https://www.nasdaq.com/articles/how-crypto-can-help-secure-ai", label: "Nasdaq", component: ( - + ), }, { href: "https://www.forbes.com/sites/stevenwolfepereira/2025/12/08/building-a-one-person-unicorn-this-startup-just-raised-87m-to-help/", label: "Forbes", component: ( - + ), }, { href: "https://archive.is/0O588", label: "The Atlantic", component: ( - + ), }, { href: "https://www.aei.org/articles/the-great-ai-forecasting-divide/1", label: "AEI", component: ( - + ), }, { href: "https://www.economist.com/finance-and-economics/2023/05/23/what-would-humans-do-in-a-world-of-super-ai", label: "The Economist", - component: , + component: , }, { href: "https://www.bloomberg.com/opinion/articles/2024-03-24/can-sam-altman-make-ai-smart-enough-to-answer-these-6-questions", label: "Bloomberg", component: ( - + ), }, ]; @@ -62,7 +63,7 @@ const fetchSiteStats = async () => { try { return await ClientMiscApi.getSiteStats(); } catch { - // silenty fail + // silently fail return null; } }; @@ -92,66 +93,61 @@ const WhyMetaculus: FC<{ className?: string }> = ({ className }) => { return (
-

- {t("whatsMetaculus")} -

- - {/* Divider */} -
- -
- {/* Description & Stats */} -
-

- {t("metaculusDescription")} -

- -
- - - -
+ {/* Left Column: Description & Stats */} +
+

+ + Metaculus + {" "} + is an{" "} + + online forecasting platform + {" "} + focusing on{" "} + + topics of global importance + + . +

+ +
+ + +
+
- {/* Divider 2 */} -
- - {/* Featured In */} -
- - {t("featuredIn")} - -
- {[0, 3].map((startIdx) => ( -
- {FEATURED_IN.slice(startIdx, startIdx + 3).map((item) => ( - - {item.component} - - ))} -
- ))} -
+ {/* Right Column: Featured In */} +
+ + {t("featuredIn")} + +
+ {FEATURED_IN.map((item) => ( + + {item.component} + + ))}
@@ -159,8 +155,10 @@ const WhyMetaculus: FC<{ className?: string }> = ({ className }) => { }; const Stat: FC<{ number: string; label: string }> = ({ number, label }) => ( -
- {number} +
+ + {number} + {label}
); diff --git a/front_end/src/app/(main)/(home)/page.tsx b/front_end/src/app/(main)/(home)/page.tsx index 088c329bc0..c0fee29a2c 100644 --- a/front_end/src/app/(main)/(home)/page.tsx +++ b/front_end/src/app/(main)/(home)/page.tsx @@ -27,12 +27,12 @@ export default async function Home() { return redirect(PUBLIC_LANDING_PAGE_URL); } - const [sidebarItems, homepagePosts, categories, initialPopularPosts] = + const [sidebarItems, homepagePosts, categories, initialNewsPosts] = await Promise.all([ serverMiscApi.getSidebarItems(), ServerPostsApi.getPostsForHomepage(), ServerProjectsApi.getHomepageCategories(), - ServerPostsApi.getPostsWithCP(FILTERS.popular), + ServerPostsApi.getPostsWithCP(FILTERS.news), ]); const postNotebooks = homepagePosts.filter( @@ -57,14 +57,18 @@ export default async function Home() { } />
- - + +
+
+
+ +
}> -
+
diff --git a/front_end/src/components/consumer_post_card/basic_consumer_post_card.tsx b/front_end/src/components/consumer_post_card/basic_consumer_post_card.tsx index da1a4a73c1..ee5689656e 100644 --- a/front_end/src/components/consumer_post_card/basic_consumer_post_card.tsx +++ b/front_end/src/components/consumer_post_card/basic_consumer_post_card.tsx @@ -74,8 +74,8 @@ const BasicConsumerPostCard: FC> = ({ className={cn( "m-0 max-w-xl text-center", isNotebook - ? "text-sm font-medium text-purple-900 dark:text-purple-900-dark md:text-base" // Add your notebook title styles here - : "text-base font-medium md:text-lg" // Add your regular title styles here + ? "text-sm font-medium text-purple-900 dark:text-purple-900-dark md:text-base" + : "text-base font-medium md:text-lg" )} > {title} diff --git a/front_end/src/components/ui/tabs/index.tsx b/front_end/src/components/ui/tabs/index.tsx index a66a734dcf..2dfafbe611 100644 --- a/front_end/src/components/ui/tabs/index.tsx +++ b/front_end/src/components/ui/tabs/index.tsx @@ -80,17 +80,24 @@ export const Tabs = ({ export const TabsList = ({ children, className, + contained = false, }: { children: ReactNode; className?: string; + contained?: boolean; }) => { const ctx = useTabsContext(); return (