diff --git a/public/futarchy_kleros.png b/public/futarchy_kleros.png index 95b9995..50ae47d 100644 Binary files a/public/futarchy_kleros.png and b/public/futarchy_kleros.png differ diff --git a/public/icon1.png b/public/icon1.png index d63709d..be7a40a 100644 Binary files a/public/icon1.png and b/public/icon1.png differ diff --git a/src/app/(homepage)/components/BottomHeader.tsx b/src/app/(homepage)/components/BottomHeader.tsx new file mode 100644 index 0000000..a870b12 --- /dev/null +++ b/src/app/(homepage)/components/BottomHeader.tsx @@ -0,0 +1,29 @@ +import clsx from "clsx"; + +import EyeIcon from "@/assets/svg/eye.svg"; + +const BottomHeader: React.FC = () => { + return ( +
+ +

+ Predicting Trends. Informing Decisions. +

+

+ Anticipate Change. Act Early. +

+
+ ); +}; + +export default BottomHeader; diff --git a/src/app/(homepage)/components/ExperimentCard.tsx b/src/app/(homepage)/components/ExperimentCard.tsx new file mode 100644 index 0000000..87b6b47 --- /dev/null +++ b/src/app/(homepage)/components/ExperimentCard.tsx @@ -0,0 +1,239 @@ +"use client"; +import React, { useMemo, useState } from "react"; + +import { useTheme } from "next-themes"; + +import clsx from "clsx"; +import { AnimatePresence, motion } from "framer-motion"; +import Image from "next/image"; +import type { StaticImageData } from "next/image"; +import Link from "next/link"; +import _Countdown, { type CountdownRenderProps } from "react-countdown"; + +import MovieDarkIcon from "@/assets/experiments/movies-dark.svg"; +import MovieLightIcon from "@/assets/experiments/movies-light.svg"; +import RealtDarkIcon from "@/assets/experiments/realt-dark.svg"; +import RealtLightIcon from "@/assets/experiments/realt-light.svg"; +import MoviesBanner from "@/assets/png/movies-banner.png"; +import MoviesR2Banner from "@/assets/png/movies-r2-banner.png"; +import PropertiesBanner from "@/assets/png/properties-banner.png"; +import ArrowIcon from "@/assets/svg/arrow-right.svg"; +import TradingIcon from "@/assets/svg/chart-bar.svg"; +import CountdownIcon from "@/assets/svg/cronometer.svg"; +import TagIcon from "@/assets/svg/tag-category.svg"; + +import { type ExperimentStatus, type IExperiment } from "@/consts/experiments"; + +const IMAGE_HEIGHT_DEFAULT = 180; +const IMAGE_HEIGHT_HOVERED = 80; + +const statusStyles: Record< + ExperimentStatus, + { label: string; className: string } +> = { + live: { + label: "Live", + className: "bg-[#00c853] text-white", + }, + ended: { + label: "Ended", + className: + "bg-white/80 text-gray-700 backdrop-blur-sm dark:bg-black/60 dark:text-gray-300", + }, + "coming soon": { + label: "Coming Soon", + className: "bg-klerosUIComponentsPrimaryBlue text-white", + }, +}; + +const bannerMap: Record = { + "movies-r2-banner": MoviesR2Banner, + "movies-banner": MoviesBanner, + "properties-banner": PropertiesBanner, +}; + +const iconMap: Record< + string, + { + light: React.FC>; + dark: React.FC>; + } +> = { + movie: { light: MovieLightIcon, dark: MovieDarkIcon }, + realt: { light: RealtLightIcon, dark: RealtDarkIcon }, +}; + +const countdownRenderer = ({ + days, + hours, + minutes, + completed, +}: CountdownRenderProps) => { + if (completed) { + return ( + + Ended + + ); + } + return ( + + {days > 0 && `${days}d `} + {hours > 0 && `${hours}h:`} + {minutes > 0 && `${minutes}m `} + + ); +}; + +const ExperimentCard: React.FC = ({ + name, + question, + url, + icon, + banner, + countLabel, + tradingPeriod, + endTime, + status, +}) => { + const [hovered, setHovered] = useState(false); + const { resolvedTheme } = useTheme(); + + const Icon = useMemo(() => { + const entry = iconMap[icon]; + if (!entry) return null; + return resolvedTheme === "light" ? entry.light : entry.dark; + }, [icon, resolvedTheme]); + + const bannerSrc = bannerMap[banner]; + + return ( + setHovered(true)} + onMouseLeave={() => setHovered(false)} + > +
+ + {bannerSrc ? ( + {name} + ) : ( +
+ )} + + + {statusStyles[status].label} + + + + +
+
+

+ {name} +

+

+ {question} +

+
+
+ + + {countLabel} + +
+ + {hovered ? ( + +
+ + + Trading Period: + + + {tradingPeriod} + +
+
+ + + Countdown: + + <_Countdown + date={new Date(endTime * 1000)} + renderer={countdownRenderer} + /> +
+
+ ) : null} +
+
+ +
+ {Icon ? : null} +
+ + View + + +
+
+
+
+ + ); +}; + +export default ExperimentCard; diff --git a/src/app/(homepage)/components/Header.tsx b/src/app/(homepage)/components/Header.tsx new file mode 100644 index 0000000..b5ba082 --- /dev/null +++ b/src/app/(homepage)/components/Header.tsx @@ -0,0 +1,30 @@ +import clsx from "clsx"; + +import EyeIcon from "@/assets/svg/eye.svg"; +import ForesightLogo from "@/assets/svg/foresight-logo.svg"; +const Header: React.FC = () => { + return ( +
+ + +

+ See Further. Decide Smarter. +

+

+ EXPLORE AVAILABLE PREDICTIONS +

+
+ ); +}; + +export default Header; diff --git a/src/app/(homepage)/components/HomepageOverlay.tsx b/src/app/(homepage)/components/HomepageOverlay.tsx new file mode 100644 index 0000000..5969886 --- /dev/null +++ b/src/app/(homepage)/components/HomepageOverlay.tsx @@ -0,0 +1,17 @@ +import clsx from "clsx"; + +import HomepageOverlaySvg from "@/assets/svg/homepage-overlay.svg"; + +const HomepageOverlay: React.FC = () => { + return ( + + ); +}; + +export default HomepageOverlay; diff --git a/src/app/(homepage)/page.tsx b/src/app/(homepage)/page.tsx index 19a4413..786aba9 100644 --- a/src/app/(homepage)/page.tsx +++ b/src/app/(homepage)/page.tsx @@ -1,114 +1,32 @@ "use client"; -import React, { useEffect } from "react"; +import React from "react"; -import { Button } from "@kleros/ui-components-library"; -import clsx from "clsx"; -import { useLocalStorage, useToggle } from "react-use"; +import { experiments } from "@/consts/experiments"; -import { useReadGnosisRouterGetWinningOutcomes } from "@/generated"; -import { useMarketsStore } from "@/store/markets"; - -import MarketContextProvider from "@/context/MarketContext"; -import { TradeWalletProvider } from "@/context/TradeWalletContext"; -import { useChartData } from "@/hooks/useChartData"; -import { usePredictionMarkets } from "@/hooks/usePredictionMarkets"; - -import FirstVisitGuide from "@/components/Guides/FirstVisit"; -import Loader from "@/components/Loader"; - -import { isUndefined } from "@/utils"; - -import { markets, parentConditionId } from "@/consts/markets"; - -import AdvancedSection from "./components/AdvancedSection"; -import Chart from "./components/Chart"; +import BottomHeader from "./components/BottomHeader"; +import ExperimentCard from "./components/ExperimentCard"; import Header from "./components/Header"; -import ParticipateSection from "./components/ParticipateSection"; -import ExportPredictions from "./components/ParticipateSection/CsvUpload/ExportPredictions"; -import PredictAll from "./components/PredictAll"; -import ProjectFunding from "./components/ProjectFunding"; +import HomepageOverlay from "./components/HomepageOverlay"; export default function Home() { - const { data: chartData } = useChartData(markets); - const predictionMarkets = usePredictionMarkets(); - const resetPredictionMarkets = useMarketsStore( - (state) => state.resetPredictionMarkets, - ); - - const { data: winningOutcomes } = useReadGnosisRouterGetWinningOutcomes({ - args: [parentConditionId], - }); - - const [isOpen, toggleGuide] = useToggle(false); - const [isOnboardingDone, setOnboardingDone] = useLocalStorage( - "onboarding-done", - false, - ); - - useEffect(() => { - if (!isOnboardingDone || isUndefined(isOnboardingDone)) { - toggleGuide(true); - } - }, [isOnboardingDone, toggleGuide]); - return ( -
+
+
-
- {!isUndefined(chartData) ? ( - - ) : ( -
- -
- )} -
-
- - -
- {markets.map((market, i) => ( - - - - ))} +
+ {experiments.map((experiment) => ( +
+
- {predictionMarkets.length > 0 ? ( -
-
- ) : null} - - - - + ))}
- - { - setOnboardingDone(true); - toggleGuide(false); - }} - /> +
); diff --git a/src/app/apple-icon.png b/src/app/apple-icon.png index 5be3a9a..d8a92b5 100644 Binary files a/src/app/apple-icon.png and b/src/app/apple-icon.png differ diff --git a/src/app/favicon.ico b/src/app/favicon.ico index 64aac39..ccda0c1 100644 Binary files a/src/app/favicon.ico and b/src/app/favicon.ico differ diff --git a/src/app/globals.css b/src/app/globals.css index 05f199b..5c6230f 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -81,6 +81,7 @@ --foreground: #171717; --red-2: #f75c7b; --green-2: #3fec65; + --klerosUIComponentsPrimaryBlue: #4872ff; } :root.dark { @@ -88,6 +89,7 @@ --foreground: #ededed; --red-2: #ffd2db; --green-2: #d2ffdc; + --klerosUIComponentsPrimaryBlue: #4872ff; } body { diff --git a/src/app/icon0.svg b/src/app/icon0.svg index 2e9f294..ccdb56b 100644 --- a/src/app/icon0.svg +++ b/src/app/icon0.svg @@ -1,3 +1,11 @@ - \ No newline at end of file +RealFaviconGeneratorhttps://realfavicongenerator.net + + + + + + + + + + \ No newline at end of file diff --git a/src/app/icon1.png b/src/app/icon1.png index d63709d..fffad8e 100644 Binary files a/src/app/icon1.png and b/src/app/icon1.png differ diff --git a/src/assets/experiments/movies-dark.svg b/src/assets/experiments/movies-dark.svg new file mode 100644 index 0000000..940d754 --- /dev/null +++ b/src/assets/experiments/movies-dark.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/assets/experiments/movies-light.svg b/src/assets/experiments/movies-light.svg new file mode 100644 index 0000000..b5eb505 --- /dev/null +++ b/src/assets/experiments/movies-light.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/assets/experiments/realt-dark.svg b/src/assets/experiments/realt-dark.svg new file mode 100644 index 0000000..e491836 --- /dev/null +++ b/src/assets/experiments/realt-dark.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/experiments/realt-light.svg b/src/assets/experiments/realt-light.svg new file mode 100644 index 0000000..71513e7 --- /dev/null +++ b/src/assets/experiments/realt-light.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/png/movies-banner.png b/src/assets/png/movies-banner.png new file mode 100644 index 0000000..30a6c54 Binary files /dev/null and b/src/assets/png/movies-banner.png differ diff --git a/src/assets/png/movies-r2-banner.png b/src/assets/png/movies-r2-banner.png new file mode 100644 index 0000000..9493b75 Binary files /dev/null and b/src/assets/png/movies-r2-banner.png differ diff --git a/src/assets/png/properties-banner.png b/src/assets/png/properties-banner.png new file mode 100644 index 0000000..de5157d Binary files /dev/null and b/src/assets/png/properties-banner.png differ diff --git a/src/assets/svg/arrow-right.svg b/src/assets/svg/arrow-right.svg new file mode 100644 index 0000000..8740832 --- /dev/null +++ b/src/assets/svg/arrow-right.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svg/built-by-kleros.svg b/src/assets/svg/built-by-kleros.svg new file mode 100644 index 0000000..9ef677a --- /dev/null +++ b/src/assets/svg/built-by-kleros.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/assets/svg/eye.svg b/src/assets/svg/eye.svg new file mode 100644 index 0000000..da227c0 --- /dev/null +++ b/src/assets/svg/eye.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/assets/svg/foresight-logo-navbar.svg b/src/assets/svg/foresight-logo-navbar.svg new file mode 100644 index 0000000..283ecd0 --- /dev/null +++ b/src/assets/svg/foresight-logo-navbar.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/assets/svg/homepage-overlay.svg b/src/assets/svg/homepage-overlay.svg new file mode 100644 index 0000000..4b8cc70 --- /dev/null +++ b/src/assets/svg/homepage-overlay.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/assets/svg/tag-category.svg b/src/assets/svg/tag-category.svg new file mode 100644 index 0000000..4f2e277 --- /dev/null +++ b/src/assets/svg/tag-category.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/components/layout/Header/Logo.tsx b/src/components/layout/Header/Logo.tsx index 199e4db..4cf417c 100644 --- a/src/components/layout/Header/Logo.tsx +++ b/src/components/layout/Header/Logo.tsx @@ -1,45 +1,18 @@ "use client"; -import React, { useEffect, useState } from "react"; +import React from "react"; -import { useTheme } from "next-themes"; - -import Image from "next/image"; import Link from "next/link"; -import _LogoDark from "@/assets/png/movies-logo-dark.png"; -import _Logo from "@/assets/png/movies-logo.png"; +import BuiltByKlerosLogo from "@/assets/svg/built-by-kleros.svg"; +import ForesightLogo from "@/assets/svg/foresight-logo-navbar.svg"; const Logo: React.FC = () => { - const { resolvedTheme } = useTheme(); - const [mounted, setMounted] = useState(false); - - useEffect(() => { - setMounted(true); - }, []); - - if (!mounted) { - return ( -
- - Movies experiment logo - -
- ); - } - return ( -
- - Movies experiment logo +
+ + +
); }; diff --git a/src/consts/experiments.ts b/src/consts/experiments.ts new file mode 100644 index 0000000..0a7ac0d --- /dev/null +++ b/src/consts/experiments.ts @@ -0,0 +1,55 @@ +export type ExperimentStatus = "live" | "ended" | "coming soon"; + +export interface IExperiment { + slug: string; + name: string; + question: string; + url: string; + icon: string; + banner: string; + countLabel: string; + tradingPeriod: string; + endTime: number; + status: ExperimentStatus; +} + +export const experiments: IExperiment[] = [ + { + slug: "movies-s2", + name: "Movies Experiment - Session 2", + question: + "If watched, what percentile score would Clément give to the movie?", + url: "https://movies-r2.foresight.kleros.io", + icon: "movie", + banner: "movies-r2-banner", + countLabel: "20 Movies", + tradingPeriod: "Until Friday 3rd 18:00 UTC", + endTime: 1775239200, + status: "live", + }, + // { + // slug: "realt", + // name: "RealT Properties Prediction", + // question: "If evaluated, what is the current price of the property?", + // url: "https://realt.foresight.kleros.io", + // icon: "realt", + // banner: "properties-banner", + // countLabel: "9 Properties", + // tradingPeriod: "Until Wednesday 17th 00:00 UTC", + // endTime: 1781721000, + // status: "coming soon", + // }, + { + slug: "movies", + name: "Movies Experiment", + question: + "If watched, what percentile score would Clément give to the movie?", + url: "https://movies.foresight.kleros.io", + icon: "movie", + banner: "movies-banner", + countLabel: "16 Movies", + tradingPeriod: "Until Friday 3rd 18:00 UTC", + endTime: 1775239200, + status: "ended", + }, +];