Skip to content
This repository was archived by the owner on May 15, 2025. It is now read-only.
Merged
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
Binary file modified bun.lockb
Binary file not shown.
7 changes: 6 additions & 1 deletion merkl.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
scroll,
} from "viem/chains";
import { coinbaseWallet, walletConnect } from "wagmi/connectors";
import hero from "src/customer/assets/images/hero.jpg?url";

export default createConfig({
appName: "Merkl",
Expand Down Expand Up @@ -118,8 +119,12 @@ export default createConfig({
},
},
sizing: {
width: { xs: 14, sm: 16, md: 18, lg: 20, xl: 24 },
spacing: { xs: 2, sm: 4, md: 8, lg: 12, xl: 16 },
radius: { xs: 2, sm: 4, md: 6, lg: 8, xl: 12 },
radius: { xs: 3, sm: 6, md: 9, lg: 12, xl: 15 },
},
images: {
hero: hero,
},
routes: {
homepage: {
Expand Down
59 changes: 0 additions & 59 deletions src/components/composite/Heading.tsx

This file was deleted.

199 changes: 199 additions & 0 deletions src/components/composite/Hero.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import type { Campaign } from "@angleprotocol/merkl-api";
import { useLocation } from "@remix-run/react";
import {
Box,
Container,
Divider,
Group,
Icon,
type IconProps,
Icons,
Text,
Title,
Value,
} from "dappkit";
import { Button } from "dappkit";
import {
useEffect,
useMemo,
useState,
type PropsWithChildren,
type ReactNode,
} from "react";
import config from "merkl.config";
import { formatUnits, parseUnits } from "viem";

export type HeroProps = PropsWithChildren<{
icons?: IconProps[];
title: ReactNode;
navigation?: { label: ReactNode; link: string };
description: ReactNode;
tags?: ReactNode[];
tabs?: { label: ReactNode; link: string }[];
campaigns?: Campaign[];
}>;

export default function Hero({
navigation,
icons,
title,
description,
tags,
tabs,
children,
campaigns,
}: HeroProps) {
const location = useLocation();

const totalRewards = useMemo(() => {
const amounts = campaigns?.map((campaign) => {
const duration = campaign.endTimestamp - campaign.startTimestamp;
const dayspan = BigInt(duration) / BigInt(3600 * 24);

return parseUnits(campaign.amount, 0) / BigInt(dayspan);
});

const sum = amounts?.reduce(
(accumulator, currentValue) => accumulator + currentValue,
0n
);
if (!sum) return "0.0";
return formatUnits(sum, 18);
}, [campaigns]);

return (
<>
<Group
className="flex-row justify-between aspect-[1440/440] bg-cover bg-no-repeat xl:aspect-auto xl:min-h-[400px]"
style={{ backgroundImage: `url('${config.images.hero}')` }}
>
<Container>
<Group className="flex-col h-full py-xl gap-xl lg:gap-xs">
<Group className="items-center">
{/* TODO: Build dynamic breadcrumbs */}
{/** Disabled and set invisible when undefined to preserve layout height */}
<Button
className={!navigation ? "invisible" : ""}
disabled={!navigation?.link}
to={navigation?.link}
look="soft"
size="xs"
>
Home
</Button>

{location.pathname.includes("opportunity") && (
<Button to={"/"} look="soft" size="xs">
<Icon remix="RiArrowRightSLine" />
Opportunities
</Button>
)}
{location.pathname.includes("user") && (
<Button to={"/"} look="soft" size="xs">
<Icon remix="RiArrowRightSLine" />
User
</Button>
)}

{!location.pathname.includes("user") && (
<Button look="soft" size="xs" className="!text-main-11">
<Icon remix="RiArrowRightSLine" />
{title}
</Button>
)}
</Group>
<Group className="grow items-center justify-between gap-xl lg:gap-xl*4">
<Group className="flex-col flex-1 gap-xl lg:!gap-lg*2">
<Group>
<Group className="items-center !gap-0 md:!gap-xl">
{!!icons && (
<Icons size="lg">
{icons?.length > 1
? icons?.map((icon) => (
<Icon
className="hidden md:block text-main-12 !w-lg*4 !h-lg*4"
key={`${Object.values(icon)}`}
{...icon}
/>
))
: icons?.map((icon) => (
<Icon
className="hidden md:block text-main-12 !w-xl*4 !h-xl*4"
key={`${Object.values(icon)}`}
{...icon}
/>
))}
</Icons>
)}
<Title h={1} size={2}>
{title}
</Title>
</Group>
{tags && (
<Text size="xl" className="!font-bold">
{description}
</Text>
)}
</Group>
<Divider className="border-main-11" horizontal />
{tags && <Group className="mb-lg">{tags}</Group>}
{!tags && (
<Text size="xl" className="!font-bold">
{description}
</Text>
)}
</Group>
{/* TODO: Show "Opportunities" or "Campaigns" according to the page */}
{!location?.pathname.includes("user") && (
<Group
className="w-full lg:w-auto lg:flex-col mr-xl*2"
size="xl"
>
<Group className="flex-col">
<Value
look={totalRewards === "0" ? "soft" : "base"}
format="$0,0"
size={3}
>
{totalRewards}
</Value>

<Text size="xl" className="font-bold">
Daily rewards
</Text>
</Group>
<Group className="flex-col">
<Text size={3}>todo</Text>
<Text size={"xl"} className="font-bold">
APR
</Text>
</Group>
<Group className="flex-col">
<Text size={3}>{campaigns?.length}</Text>
<Text size={"xl"} className="font-bold">
Active campaigns
</Text>
</Group>
</Group>
)}
{/* {!!tabs && (
<Box size="sm" look="base" className="flex-row mt-xl*2 w-min">
{tabs?.map((tab) => (
<Button
look={location.pathname === tab.link ? "hype" : "soft"}
to={tab.link}
key={tab.link}
>
{tab.label}
</Button>
))}
</Box>
)} */}
</Group>
</Group>
</Container>
</Group>
<div>{children}</div>
</>
);
}
Loading