+
+ Build your Web3 project with Fuse
+
+
+ Easily access affordable Web3 payment & loyalty infrastructure
+ without development hurdles or vendor dependencies.
+
+
amplitude.track("Home: Create project")}
+ >
+ Create your project
+
+
Developer tools
diff --git a/app/points/Home.tsx b/app/points/Home.tsx
new file mode 100644
index 00000000..56e02539
--- /dev/null
+++ b/app/points/Home.tsx
@@ -0,0 +1,369 @@
+import Image from "next/image";
+import { useAccount } from "wagmi";
+import { useRef, useEffect } from 'react';
+import { useRouter } from "next/navigation";
+
+import { setIsWalletModalOpen } from "@/store/navbarSlice";
+import { useAppDispatch, useAppSelector } from "@/store/store";
+import { selectAirdropSlice } from "@/store/airdropSlice";
+import Spinner from "@/components/ui/Spinner";
+import { path } from "@/lib/helpers";
+
+import RightCaret from "@/assets/RightCaret";
+import rightCaret from "@/assets/right-caret-black.svg";
+import airdrop from "@/assets/airdrop-right.svg";
+import fuseFoundation from "@/assets/fuse-foundation.svg";
+import fuseFounders from "@/assets/fuse-founders.png";
+import fuseFlash from "@/assets/fuse-flash.svg";
+import fuseEmber from "@/assets/fuse-ember.svg";
+import Link from "next/link";
+
+const Hero = () => {
+ const dispatch = useAppDispatch();
+ const airdropSlice = useAppSelector(selectAirdropSlice);
+ const { isConnecting, isConnected } = useAccount();
+ const router = useRouter();
+
+ const isLoading = isConnecting || airdropSlice.isAuthenticating || airdropSlice.isCreating || airdropSlice.isRetrieving;
+
+ return (
+
+
+
+ Welcome to
+
+
+ Ember Points
+
+
+
+ Fuse is building the Stripe of Layer 2, powered by zkEVM technology. We invite you to be part of this revolutionary journey
+
+
+
+
+
+
+
+ Learn more
+
+
+
+
+ );
+};
+
+const FloatingParachute = () => {
+ const parachuteRef = useRef
(null);
+
+ useEffect(() => {
+ let frameId: number;
+ let startTime: number;
+
+ const animate = (time: number) => {
+ if (!startTime) startTime = time;
+ const elapsed = time - startTime;
+
+ const translateY = Math.sin(elapsed / 1000) * 30;
+ const rotateZ = Math.sin(elapsed / 2000) * 12;
+
+ if (parachuteRef.current) {
+ parachuteRef.current.style.transform = `translateY(${translateY}px) rotateZ(${rotateZ}deg)`;
+ }
+
+ frameId = requestAnimationFrame(animate);
+ };
+
+ frameId = requestAnimationFrame(animate);
+
+ return () => cancelAnimationFrame(frameId);
+ }, []);
+
+ return (
+
+ );
+};
+
+const Giveaway = () => {
+ return (
+
+
+
+ Giving away
+
+
+
+
+ 10,400,000 FUSE
+
+
+
+ Phase 1 is live now!
+
+
+
+
+
+
+
+
+
+
+
+ Ecosystem
+
+
+ Builders Grant
+
+
+ Flash
+
+
+ Ember
+
+
+
+
+
+ );
+};
+
+const Phases = () => {
+ const dispatch = useAppDispatch();
+ const { isConnected } = useAccount();
+ const router = useRouter();
+
+ return (
+
+
+
+
+
+
+
+
+ Phase 1
+
+
+ Live
+
+
+
+ Fuse Ecosystem
+
+
+ Complete various quests to explore the Fuse ecosystem, find new ways to earn and always be the first to receive the latest news.
+
+
+
+
+ Learn more
+
+
+
+
+
+
+
+
+
+
+
+
+ Phase 2
+
+
+ Coming soon
+
+
+
+ Builder Grants
+
+
+ {"If you're a developer, start building an app on the new testnet today to get support and a grant from the Fuse team to help grow your project."}
+
+
+
+ Learn more
+
+
+
+
+
+
+
+
+
+
+
+
+ Phase 3
+
+
+ Coming soon
+
+
+
+ Fuse Flash
+
+
+ By playing games on the Fuse Flash testnet, you will help us verify that the network is stable and reliable, and we will be happy to reward you for being with us!
+
+
+ Learn more
+
+
+
+
+
+
+
+
+
+
+
+ Phase 4
+
+
+ Coming soon
+
+
+
+ Fuse Ember
+
+
+ Migrate all your funds from old L1 Fuse Network mainnet to L2 Fuse Ember mainnet and earn airdrop points. The more funds you migrate, the more points you get.
+
+
+ Learn more
+
+
+
+
+
+
+ );
+};
+
+const Home = () => {
+ return (
+
+ );
+};
+
+export default Home;
diff --git a/app/points/ecosystem/Home.tsx b/app/points/ecosystem/Home.tsx
new file mode 100644
index 00000000..5aa0cb87
--- /dev/null
+++ b/app/points/ecosystem/Home.tsx
@@ -0,0 +1,512 @@
+import { useEffect, useState } from "react";
+import Image from "next/image";
+import { useRouter, useSearchParams } from "next/navigation";
+import Link from "next/link";
+
+import Copy from "@/components/ui/Copy";
+import { convertTimestampToUTC, IS_SERVER, isFloat, isSocialFollowed, path } from "@/lib/helpers";
+import { useAppDispatch, useAppSelector } from "@/store/store";
+import { selectAirdropSlice, setIsClaimTestnetFuseModalOpen, setIsQuestModalOpen, setSelectedQuest } from "@/store/airdropSlice";
+import Avatar from "@/components/ui/Avatar";
+import { CardBody, CardContainer, CardItem } from "@/components/ui/Card3D";
+import Quest from "@/components/airdrop/Quest";
+import { AirdropQuests } from "@/lib/types";
+
+import copyIcon from "@/assets/copy-gray.svg";
+import rightCaret from "@/assets/right-caret.svg";
+import rightCaretBlack from "@/assets/right-caret-black.svg";
+import leftArrow from "@/assets/left-arrow.svg";
+import questionMark from "@/assets/questionmark-border.svg";
+import pointHexagon from "@/assets/fuse-foundation-point-hexagon.svg";
+import fuseAirdropPhase from "@/assets/fuse-foundation.svg";
+import bridgeFuse from "@/assets/bridge-fuse.svg";
+import followX from "@/assets/twitter-x-green.svg";
+import verifyDiscord from "@/assets/verify-discord-green.svg";
+import joinTelegram from "@/assets/join-telegram-green.svg";
+import volt from "@/assets/volt-wallet-green.svg";
+import artrific from "@/assets/artrific-green.svg";
+import meridian from "@/assets/meridian-green.svg";
+import meridianYellow from "@/assets/meridian-yellow.svg";
+import voltageLiquidityYellow from "@/assets/voltage-liquidity-yellow.svg";
+import gooddollarYellow from "@/assets/gooddollar-yellow.svg";
+
+const Home = () => {
+ const dispatch = useAppDispatch();
+ const { user, twitterAuthUrl } = useAppSelector(selectAirdropSlice);
+ const router = useRouter();
+ const searchParams = useSearchParams();
+ const twitterConnected = searchParams.get('twitter-connected');
+
+ const [quests, setQuests] = useState([
+ {
+ id: "followFuseOnTwitter",
+ title: "Follow @Fuse_network on X",
+ description: "Get 50 point for following an official Fuse Network X account",
+ point: "50 Points",
+ frequency: "One-time",
+ image: followX,
+ buttons: [
+ {
+ text: "Go to X",
+ isFunction: true,
+ }
+ ]
+ },
+ {
+ id: "telegramSubscription",
+ title: "Join Fuse Telegram",
+ description: "Get 50 point for joining an official Fuse Network Telegram channel \n**Verify the quest 1 hour after completing it on Layer3**",
+ point: "50 Points",
+ frequency: "One-time",
+ image: joinTelegram,
+ buttons: [
+ {
+ text: "Go to Quest",
+ link: "https://app.layer3.xyz/quests/join-fuse-telegram",
+ },
+ {
+ text: "Verify Quest",
+ isFunction: true,
+ }
+ ]
+ },
+ {
+ id: "joinFuseDiscord",
+ title: "Join Fuse Discord",
+ description: "Get 50 point for joining an official Fuse network Discord channel \n**Verify the quest 1 hour after completing it on Layer3**",
+ point: "50 Points",
+ frequency: "One-time",
+ image: verifyDiscord,
+ buttons: [
+ {
+ text: "Go to Quest",
+ link: "https://app.layer3.xyz/quests/join-fuse-discord",
+ },
+ {
+ text: "Verify Quest",
+ isFunction: true,
+ }
+ ]
+ },
+ {
+ id: "exploreVoltageDex",
+ title: "Explore Voltage Finance",
+ description: "Trade, invest, and earn with just a few clicks. \n**Verify the quest 1 hour after completing it on Layer3**",
+ point: "125 Points",
+ frequency: "One-time",
+ image: volt,
+ buttons: [
+ {
+ text: "Go to Quest",
+ link: "https://app.layer3.xyz/quests/voltage-on-fuse-network",
+ },
+ {
+ text: "Verify Quest",
+ isFunction: true,
+ }
+ ]
+ },
+ {
+ id: "liquidityVoltage",
+ title: "Provide Liquidity to Voltage",
+ point: "Up to 8 points per $1 in pool daily",
+ image: voltageLiquidityYellow,
+ buttons: [
+ {
+ text: "Go to Voltage",
+ link: "https://voltage.finance/pool",
+ },
+ ]
+ },
+ {
+ id: "exploreVoltWallet",
+ title: "Install the Volt wallet",
+ description: "The Volt wallet is the best mobile solution for interacting with the Fuse network, as it is built and developed by the Fuse team. Explore its features and get 200 points. \n**Verify the quest 1 hour after completing it on Layer3**",
+ point: "200 Points",
+ frequency: "One-time",
+ image: volt,
+ buttons: [
+ {
+ text: "Go to Quest",
+ link: "https://app.layer3.xyz/quests/explore-volt-wallet",
+ },
+ {
+ text: "Verify Quest",
+ isFunction: true,
+ }
+ ]
+ },
+ {
+ id: "exploreMeridian",
+ title: "Explore Meridian Finance",
+ description: "The All-in-one DeFi Hub for EVM-Compatible Networks. \n**Verify the quest 1 hour after completing it on Layer3**\n",
+ point: "175 Points",
+ frequency: "One-time",
+ image: meridian,
+ buttons: [
+ {
+ text: "Go to Quest",
+ link: "https://app.layer3.xyz/quests/explore-meridian-finance",
+ },
+ {
+ text: "Verify Quest",
+ isFunction: true,
+ }
+ ]
+ },
+ {
+ id: "provideMeridianLiquidity",
+ title: "Lend on Meridian",
+ point: "Up to 8 points per $1 in pool daily",
+ image: meridianYellow,
+ buttons: [
+ {
+ text: "Go to Meridian Lend",
+ link: "https://lend.meridianfinance.net/markets/",
+ },
+ ]
+ },
+ {
+ id: "borrowOnMeridian",
+ title: "Borrow on Meridian",
+ description: "Borrow any asset on Meridian to get 12 points per $1 borrowed every day. \n**Points will begin to accrue 24 hours after the borrow transaction.**",
+ point: "12 points per $1 borrowed daily",
+ image: meridianYellow,
+ buttons: [
+ {
+ text: "Go to Meridian Borrow",
+ link: "https://lend.meridianfinance.net/borrow/",
+ },
+ ]
+ },
+ {
+ id: "exploreArtrificOnFuse",
+ title: "Create an NFT on Artrific",
+ description: "Create an NFT on the leading NFT marketplace on Fuse Network and get 300 points \n**Verify the quest 1 hour after completing it on Layer3**\n",
+ point: "300 Points",
+ frequency: "One-time",
+ image: artrific,
+ buttons: [
+ {
+ text: "Go to Quest",
+ link: "https://app.layer3.xyz/quests/explore-artrific-nft-marketplace-on-fuse-network",
+ },
+ {
+ text: "Verify Quest",
+ isFunction: true,
+ }
+ ]
+ },
+ {
+ id: "g$Claim",
+ title: "Claim G$ on GoodDapp",
+ description: "To get 30 points daily, you need to take 6 steps: \n**Step 1:**\nGo to quest on the Layer3 platform \n**Step 2:**\nConnect to Layer3 a wallet participating in the airdrop \n**Step 3:**\nGo to GoodDapp \n**Step 4:**\nClaim G$ token on Fuse Network \n**Step 5:**\nVerify quest completion on the Layer3 \n**Step 6:**\nRepeat every day. After 5 claims, the quest will renew automatically and allow you to claim more and more. \n**Verify the quest 1 hour after completing it on Layer3**",
+ point: "30 Points per claim",
+ frequency: "Once a day",
+ image: gooddollarYellow,
+ buttons: [
+ {
+ text: "Go to Quest",
+ link: "https://app.layer3.xyz/streaks/claim-dollarg",
+ },
+ {
+ text: "Verify Quest",
+ isFunction: true,
+ endpoint: "gooddollar",
+ }
+ ]
+ },
+ ])
+
+ function referralLink() {
+ const host = !IS_SERVER ? window?.location?.host : ""
+ return `${host}/airdrop?ref=${user.referralCode}`
+ }
+
+ useEffect(() => {
+ setQuests((prevQuests) => {
+ const newQuests = [...prevQuests];
+ newQuests.map((newQuest) => {
+ if (newQuest.frequency !== "One-time") {
+ return newQuest;
+ }
+
+ user.completedQuests?.map((completedQuest) => {
+ let completedQuestId = completedQuest.type;
+ if (completedQuest.stakingType) {
+ completedQuestId = `${completedQuest.type}-${completedQuest.stakingType}`;
+ }
+ if (newQuest.id === completedQuestId) {
+ newQuest.completed = true;
+ }
+ })
+ return newQuest;
+ });
+ return newQuests;
+ })
+ }, [user.completedQuests])
+
+ useEffect(() => {
+ if (twitterConnected === "true") {
+ if (localStorage.getItem("airdrop-isClaimTestnetFuse")) {
+ dispatch(setIsClaimTestnetFuseModalOpen(true));
+ localStorage.removeItem("airdrop-isClaimTestnetFuse");
+ }
+ }
+ }, [dispatch, router, twitterConnected])
+
+ useEffect(() => {
+ if (twitterAuthUrl) {
+ router.push(twitterAuthUrl);
+ }
+ }, [router, twitterAuthUrl])
+
+ return (
+
+
+
+
+ Points
+
+
+
+
+ Explore the Ecosystem
+
+
+
+
+
+
+
+ My points
+
+
+
+
+ {isFloat(user.points) ? user.points.toFixed(2) : user.points}
+
+
+ {user.pointsLastUpdatedAt ? (
+
+
+ Last update {convertTimestampToUTC(user.pointsLastUpdatedAt)}
+
+
+
+
+
+ Points calculation updated every 24 hours. Next update {convertTimestampToUTC(user.nextRewardDistributionTime)}
+
+
+
+
+ ) :
}
+
+
+
+
+ Your Rank
+
+
+ {new Intl.NumberFormat().format(user.leaderboardPosition)}
+
+
+ View Leaderboard
+
+
+
+
+
+
+
+ Fuse is migrating to a zkEvm L2 (Fuse Ember) and taking its robust comunity with it
+
+
+ Learn more
+
+
+
+
+
+
+
+ Start earning points
+
+
+
+
+
+
+
+ Bridge FUSE
+
+
+ Get 4 points daily on every $1 you bridge to Fuse
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Invite friends
+
+
+ {"Get 20% of your friend's total points"}
+
+
+
+
+ Invite link
+
+
+
+ {referralLink()}
+
+
+
+
+
+
+
+
+
+
+
+
+ {isSocialFollowed(user) ? "Join our Socials and explore the Ecosystem" : "Follow Fuse on X to unlock quests"}
+
+
+ {quests.filter((quest) => quest.frequency === "One-time").map((quest) => (
+
+ ))}
+
+
+
+
+ {isSocialFollowed(user) ? "Get multipliers for your points!" : "Follow Fuse on X to unlock multiplier quests"}
+
+
+ {quests.filter((quest) => quest.frequency !== "One-time").map((quest) => (
+
+ ))}
+
+
+
+ )
+}
+
+export default Home;
diff --git a/app/points/ecosystem/layout.tsx b/app/points/ecosystem/layout.tsx
new file mode 100644
index 00000000..ca3118a6
--- /dev/null
+++ b/app/points/ecosystem/layout.tsx
@@ -0,0 +1,14 @@
+import type { Metadata } from 'next'
+
+export const metadata: Metadata = {
+ title: 'Ecosystem - Fuse Console Points',
+ description: 'Complete quests and invite friends to earn XP',
+}
+
+export default function AirdropEcosystemLayout({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return
+}
diff --git a/app/points/ecosystem/page.tsx b/app/points/ecosystem/page.tsx
new file mode 100644
index 00000000..3f397071
--- /dev/null
+++ b/app/points/ecosystem/page.tsx
@@ -0,0 +1,45 @@
+"use client";
+
+import { useEffect } from "react";
+import { useRouter } from "next/navigation";
+
+import { path } from "@/lib/helpers";
+import { useAppDispatch, useAppSelector } from "@/store/store";
+import { setSelectedNavbar } from "@/store/navbarSlice";
+import Home from "./Home";
+import Footer from "@/components/Footer";
+import Topbar from "@/components/Topbar";
+import WaitlistModal from "@/components/airdrop/WaitlistModal";
+import { retrieveAirdropUser, selectAirdropSlice } from "@/store/airdropSlice";
+import QuestModal from "@/components/airdrop/QuestModal";
+import ClaimTestnetFuseModal from "@/components/airdrop/ClaimTestnetFuseModal";
+
+const AirdropEcosystem = () => {
+ const dispatch = useAppDispatch();
+ const airdropSlice = useAppSelector(selectAirdropSlice);
+ const router = useRouter();
+
+ useEffect(() => {
+ dispatch(setSelectedNavbar("points"));
+ dispatch(retrieveAirdropUser());
+ }, [dispatch])
+
+ useEffect(() => {
+ if (airdropSlice.isHydrated && !airdropSlice.isUser) {
+ router.push(path.AIRDROP)
+ }
+ }, [airdropSlice.isHydrated, airdropSlice.isUser, router]);
+
+ return (
+
+
+
+
+
+
+
+
+ );
+};
+
+export default AirdropEcosystem;
diff --git a/app/points/grant/Home.tsx b/app/points/grant/Home.tsx
new file mode 100644
index 00000000..19a9c20a
--- /dev/null
+++ b/app/points/grant/Home.tsx
@@ -0,0 +1,231 @@
+import Image from "next/image";
+import Link from "next/link";
+
+import FAQ from "@/components/FAQ";
+
+import prizePool from "@/assets/airdrop-grant-prize-background.svg";
+import wallet from "@/assets/wallet.svg";
+import paid from "@/assets/paid.svg";
+import agriculture from "@/assets/agriculture.svg";
+import esports from "@/assets/esports.svg";
+import build from "@/assets/build.svg";
+import mintmark from "@/assets/mintmark.svg";
+import currencyExchange from "@/assets/currency-exchange.svg";
+import group from "@/assets/group.svg";
+import smartToy from "@/assets/smart-toy.svg";
+import article from "@/assets/article.svg";
+import uploadFile from "@/assets/upload-file.svg";
+
+const bounties = [
+ {
+ title: "Payments",
+ description: "Debit cards supporting FUSE and USDC.",
+ icon: wallet,
+ },
+ {
+ title: "Stablecoins",
+ description: "CDP stablecoins, yield-bearing stablecoins, RWA-backed stablecoins.",
+ icon: paid,
+ },
+ {
+ title: "Yield",
+ description: "Fixed yield, yield aggregators, cross-chain yield tokenization.",
+ icon: agriculture,
+ },
+ {
+ title: "Gaming",
+ description: "Prediction markets, single-click games, gamified NFT games.",
+ icon: esports,
+ },
+ {
+ title: "Tooling",
+ description: "Vote incentive markets, liquid locker protocols.",
+ icon: build,
+ },
+ {
+ title: "Lending",
+ description: "Simple lending markets, isolated lending markets.",
+ icon: mintmark,
+ },
+ {
+ title: "Exchanges",
+ description: "Perpetual markets, options markets, AMMs, CLOB exchanges.",
+ icon: currencyExchange,
+ },
+ {
+ title: "Community Movements",
+ description: "Brand ambassador campaigns, user-engagement campaigns.",
+ icon: group,
+ },
+ {
+ title: "DePIN & AI",
+ description: "Wireless networks, energy grids, computation, storage.",
+ icon: smartToy,
+ },
+];
+
+const joins = [
+ {
+ title: "Explore the Developer Docs",
+ description: "Dive into our comprehensive documentation to understand the Ember platform and its capabilities.",
+ icon: article,
+ button: {
+ title: "Start building",
+ link: "#"
+ },
+ },
+ {
+ title: "Submit Your Application",
+ description: "Once your app is ready, apply for the bounty program to showcase your work and earn rewards.",
+ icon: uploadFile,
+ button: {
+ title: "Apply Now",
+ link: "https://docs.google.com/forms/d/e/1FAIpQLServsLcjBhksX0bGXsE9jwf8qixP4HlKq2jEiJmwEjFxPxX8w/viewform"
+ },
+ },
+];
+
+const questions = [
+ "What is Fuse Ember?",
+ "How do I apply to Fuse Ember bounty program?",
+ "Who can participate in the Fuse Ember bounty program?",
+ "What types of projects can be submitted?",
+ "How are winners selected?",
+ "How much bounty will each winner get?",
+ "When will the Fuse Ember bounty be distributed?",
+ "What support is available for participants?",
+ "Can existing projects participate?",
+ "?"
+]
+
+const answers = [
+ "Fuse Nodes are devices (computers or servers) that run the Fuse blockchain's protocol software and connect to its network. They participate in the Fuse Network by maintaining a copy of the ",
+ "Fuse Nodes are devices (computers or servers) that run the Fuse blockchain's protocol software and connect to its network. They participate in the Fuse Network by maintaining a copy of the ",
+ "Fuse Nodes are devices (computers or servers) that run the Fuse blockchain's protocol software and connect to its network. They participate in the Fuse Network by maintaining a copy of the ",
+ "Fuse Nodes are devices (computers or servers) that run the Fuse blockchain's protocol software and connect to its network. They participate in the Fuse Network by maintaining a copy of the ",
+ "Fuse Nodes are devices (computers or servers) that run the Fuse blockchain's protocol software and connect to its network. They participate in the Fuse Network by maintaining a copy of the ",
+ "Fuse Nodes are devices (computers or servers) that run the Fuse blockchain's protocol software and connect to its network. They participate in the Fuse Network by maintaining a copy of the ",
+ "Fuse Nodes are devices (computers or servers) that run the Fuse blockchain's protocol software and connect to its network. They participate in the Fuse Network by maintaining a copy of the ",
+ "Fuse Nodes are devices (computers or servers) that run the Fuse blockchain's protocol software and connect to its network. They participate in the Fuse Network by maintaining a copy of the ",
+ "Fuse Nodes are devices (computers or servers) that run the Fuse blockchain's protocol software and connect to its network. They participate in the Fuse Network by maintaining a copy of the ",
+ "Fuse Nodes are devices (computers or servers) that run the Fuse blockchain's protocol software and connect to its network. They participate in the Fuse Network by maintaining a copy of the ",
+]
+
+const Hero = () => {
+ return (
+
+
+ Builder Grants
+
+
+ A bounty program rewarding developers for building apps on Ember.
+
+
+
+ Prize pool
+
+
+ 3,900,000 FUSE
+
+
+
+
+ );
+};
+
+const Bounty = () => {
+ return (
+
+
+ {bounties.map((bounty) => (
+
+
+ {bounty.title}
+
+
+ ))}
+
+
+
+ Bounty list
+
+
+ The bounty program covers a wide range of categories to encourage diverse and innovative apps. Multiple winners can be selected in each category. To qualify, your app must fit into one of the following categories:
+
+
+
+ );
+};
+
+const Winner = () => {
+ return (
+
+
+
+
+ Be a Winner!
+
+
+ At least 3 best projects will be selected and awarded. But if there are more amazing projects, everyone will get a bounty!
+
+
+
+
+ );
+};
+
+const Join = () => {
+ return (
+
+
+
+ Build and Apply
+
+
+ Join us in building the next generation of Ember apps. Start building right now on Flash testnet
+
+
+
+ {joins.map((join) => (
+
+
+
+ {join.title}
+
+
+ {join.description}
+
+
+ {join.button.title}
+
+
+ ))}
+
+
+ );
+};
+
+const Home = () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+};
+
+export default Home;
diff --git a/app/points/grant/layout.tsx b/app/points/grant/layout.tsx
new file mode 100644
index 00000000..6acf6e57
--- /dev/null
+++ b/app/points/grant/layout.tsx
@@ -0,0 +1,14 @@
+import type { Metadata } from 'next'
+
+export const metadata: Metadata = {
+ title: 'Builder Grants - Fuse Console Points',
+ description: 'A bounty program rewarding developers for building apps on Ember',
+}
+
+export default function AirdropGrantLayout({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return
+}
diff --git a/app/points/grant/page.tsx b/app/points/grant/page.tsx
new file mode 100644
index 00000000..dc1e0777
--- /dev/null
+++ b/app/points/grant/page.tsx
@@ -0,0 +1,40 @@
+"use client";
+
+import { useEffect } from "react";
+import { useRouter } from "next/navigation";
+
+import { path } from "@/lib/helpers";
+import { useAppDispatch, useAppSelector } from "@/store/store";
+import { setSelectedNavbar } from "@/store/navbarSlice";
+import Home from "./Home";
+import Footer from "@/components/Footer";
+import Topbar from "@/components/Topbar";
+import { retrieveAirdropUser, selectAirdropSlice } from "@/store/airdropSlice";
+
+const AirdropGrant = () => {
+ const dispatch = useAppDispatch();
+ const airdropSlice = useAppSelector(selectAirdropSlice);
+ const router = useRouter();
+
+ useEffect(() => {
+ dispatch(setSelectedNavbar("points"));
+ dispatch(retrieveAirdropUser());
+ }, [dispatch])
+
+ useEffect(() => {
+ if (airdropSlice.isHydrated && !airdropSlice.isUser) {
+ router.push(path.AIRDROP)
+ }
+ }, [airdropSlice.isHydrated, airdropSlice.isUser, router]);
+
+ return (
+
+ );
+};
+
+export default AirdropGrant;
diff --git a/app/points/layout.tsx b/app/points/layout.tsx
new file mode 100644
index 00000000..f0612cd1
--- /dev/null
+++ b/app/points/layout.tsx
@@ -0,0 +1,14 @@
+import type { Metadata } from 'next'
+
+export const metadata: Metadata = {
+ title: 'Points - Fuse Console',
+ description: 'Join the Fuse Points! Get into the Fuse, connect your wallet and earn Rewards with ease',
+}
+
+export default function AirdropLayout({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return
+}
diff --git a/app/points/leaderboard/Home.tsx b/app/points/leaderboard/Home.tsx
new file mode 100644
index 00000000..a0a89aac
--- /dev/null
+++ b/app/points/leaderboard/Home.tsx
@@ -0,0 +1,172 @@
+import Image from "next/image";
+import { motion } from "framer-motion";
+
+import { useAppDispatch, useAppSelector } from "@/store/store";
+import { fetchAirdropLeaderboardUsers, selectAirdropSlice } from "@/store/airdropSlice";
+import { eclipseAddress } from "@/lib/helpers";
+import Avatar from "@/components/ui/Avatar";
+
+import star from "@/assets/star.svg";
+import starGold from "@/assets/star-gold.svg";
+import starSilver from "@/assets/star-silver.svg";
+import starBronze from "@/assets/star-bronze.svg";
+
+type PositionStar = {
+ name: string;
+ icon: string;
+}
+
+type PositionStars = {
+ [key: number]: PositionStar
+}
+
+const PAGE_SIZE = "30";
+
+const leaderboardVariants = {
+ hidden: {
+ opacity: 0,
+ y: 50,
+ transition: { ease: [0.78, 0.14, 0.15, 0.86] }
+ },
+ show: {
+ opacity: 1,
+ y: 0,
+ transition: { ease: [0.78, 0.14, 0.15, 0.86] },
+ }
+};
+
+const positionStars: PositionStars = {
+ 1: {
+ name: "Gold",
+ icon: starGold
+ },
+ 2: {
+ name: "Silver",
+ icon: starSilver
+ },
+ 3: {
+ name: "Bronze",
+ icon: starBronze
+ }
+}
+
+const Home = () => {
+ const dispatch = useAppDispatch();
+ const { isLeaderboardUsersLoading, leaderboardUsers, lastLeaderboardUserId, isLeaderboardUsersFinished, user } = useAppSelector(selectAirdropSlice);
+
+ return (
+
+
+ Leaderboard
+
+
+ Your Ranking
+
+
+
+
+ {new Intl.NumberFormat().format(user.leaderboardPosition)}
+
+
+
+
+
+ {eclipseAddress(user.walletAddress)}
+
+
+ {user.walletAddress}
+
+
+
+
+
+ {user.points % 1 === 0 ? user.points : user.points.toFixed(2)}
+
+
+
+
+ Top users of all-time
+
+
+ {leaderboardUsers.map((leaderboardUser, index) =>
+
+
+ {positionStars[index + 1] &&
+
+ }
+
+ {new Intl.NumberFormat().format(index + 1)}
+
+
+
+
+
+ {leaderboardUser.walletAddress}
+
+
+ {eclipseAddress(leaderboardUser.walletAddress)}
+
+
+
+
+
+ {leaderboardUser.points % 1 === 0 ? leaderboardUser.points : leaderboardUser.points.toFixed(2)}
+
+
+
+ )}
+ {!isLeaderboardUsersFinished &&
+
{
+ dispatch(fetchAirdropLeaderboardUsers({
+ queryParams: {
+ pageSize: PAGE_SIZE,
+ userIdToStartAfter: lastLeaderboardUserId
+ }
+ }))
+ }}
+ >
+ {isLeaderboardUsersLoading &&
+
+ }
+
+ }
+
+
+ )
+}
+
+export default Home;
diff --git a/app/points/leaderboard/layout.tsx b/app/points/leaderboard/layout.tsx
new file mode 100644
index 00000000..34b20c38
--- /dev/null
+++ b/app/points/leaderboard/layout.tsx
@@ -0,0 +1,14 @@
+import type { Metadata } from 'next'
+
+export const metadata: Metadata = {
+ title: 'Leaderboard - Fuse Console Points',
+ description: 'View all participants ranks in the Fuse Points Leaderboard!',
+}
+
+export default function AirdropLeaderboardLayout({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return
+}
diff --git a/app/points/leaderboard/page.tsx b/app/points/leaderboard/page.tsx
new file mode 100644
index 00000000..d7f5f0b6
--- /dev/null
+++ b/app/points/leaderboard/page.tsx
@@ -0,0 +1,38 @@
+"use client";
+
+import { useEffect } from "react";
+import { useRouter } from "next/navigation";
+
+import { path } from "@/lib/helpers";
+import { useAppDispatch, useAppSelector } from "@/store/store";
+import { setSelectedNavbar } from "@/store/navbarSlice";
+import Home from "./Home";
+import Footer from "@/components/Footer";
+import Topbar from "@/components/Topbar";
+import { selectAirdropSlice } from "@/store/airdropSlice";
+
+const AirdropLeaderboard = () => {
+ const dispatch = useAppDispatch();
+ const airdropSlice = useAppSelector(selectAirdropSlice);
+ const router = useRouter();
+
+ useEffect(() => {
+ dispatch(setSelectedNavbar("points"));
+ }, [dispatch])
+
+ useEffect(() => {
+ if (airdropSlice.isHydrated && !airdropSlice.isUser) {
+ router.push(path.AIRDROP)
+ }
+ }, [airdropSlice.isHydrated, airdropSlice.isUser, router]);
+
+ return (
+
+
+
+
+
+ );
+};
+
+export default AirdropLeaderboard;
diff --git a/app/points/page.tsx b/app/points/page.tsx
new file mode 100644
index 00000000..34922e72
--- /dev/null
+++ b/app/points/page.tsx
@@ -0,0 +1,25 @@
+"use client";
+
+import { useEffect } from "react";
+
+import { useAppDispatch } from "@/store/store";
+import { setSelectedNavbar } from "@/store/navbarSlice";
+import Home from "./Home";
+import Topbar from "@/components/Topbar";
+
+const Airdrop = () => {
+ const dispatch = useAppDispatch();
+
+ useEffect(() => {
+ dispatch(setSelectedNavbar("points"));
+ }, [dispatch])
+
+ return (
+
+
+
+
+ );
+};
+
+export default Airdrop;
diff --git a/assets/RightArrow.tsx b/assets/RightArrow.tsx
new file mode 100644
index 00000000..49005793
--- /dev/null
+++ b/assets/RightArrow.tsx
@@ -0,0 +1,5 @@
+export default function RightArrow() {
+ return (
+
+ );
+}
diff --git a/assets/RightCaret.tsx b/assets/RightCaret.tsx
new file mode 100644
index 00000000..25266fd7
--- /dev/null
+++ b/assets/RightCaret.tsx
@@ -0,0 +1,5 @@
+export default function RightCaret() {
+ return (
+
+ )
+}
diff --git a/assets/agriculture.svg b/assets/agriculture.svg
new file mode 100644
index 00000000..896b2c4c
--- /dev/null
+++ b/assets/agriculture.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/airdrop-grant-prize-background.svg b/assets/airdrop-grant-prize-background.svg
new file mode 100644
index 00000000..bc969995
--- /dev/null
+++ b/assets/airdrop-grant-prize-background.svg
@@ -0,0 +1,121 @@
+
diff --git a/assets/airdrop-right.svg b/assets/airdrop-right.svg
new file mode 100644
index 00000000..1c44ee6a
--- /dev/null
+++ b/assets/airdrop-right.svg
@@ -0,0 +1,116 @@
+
diff --git a/assets/article.svg b/assets/article.svg
new file mode 100644
index 00000000..a8b08b27
--- /dev/null
+++ b/assets/article.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/artrific-green.svg b/assets/artrific-green.svg
new file mode 100644
index 00000000..98082130
--- /dev/null
+++ b/assets/artrific-green.svg
@@ -0,0 +1,40 @@
+
diff --git a/assets/artrific.svg b/assets/artrific.svg
new file mode 100644
index 00000000..b51a39f6
--- /dev/null
+++ b/assets/artrific.svg
@@ -0,0 +1,40 @@
+
diff --git a/assets/bridge-fuse.svg b/assets/bridge-fuse.svg
new file mode 100644
index 00000000..65297f37
--- /dev/null
+++ b/assets/bridge-fuse.svg
@@ -0,0 +1,40 @@
+
diff --git a/assets/build.svg b/assets/build.svg
new file mode 100644
index 00000000..b60baa83
--- /dev/null
+++ b/assets/build.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/check-background-black.svg b/assets/check-background-black.svg
new file mode 100644
index 00000000..da12f20d
--- /dev/null
+++ b/assets/check-background-black.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/check-background.svg b/assets/check-background.svg
new file mode 100644
index 00000000..61f21844
--- /dev/null
+++ b/assets/check-background.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/checkmark-orange.svg b/assets/checkmark-orange.svg
new file mode 100644
index 00000000..a6347ab3
--- /dev/null
+++ b/assets/checkmark-orange.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/copy-gray.svg b/assets/copy-gray.svg
new file mode 100644
index 00000000..020a04f1
--- /dev/null
+++ b/assets/copy-gray.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/currency-exchange.svg b/assets/currency-exchange.svg
new file mode 100644
index 00000000..d92e7a7e
--- /dev/null
+++ b/assets/currency-exchange.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/email-orange.svg b/assets/email-orange.svg
new file mode 100644
index 00000000..bec4e037
--- /dev/null
+++ b/assets/email-orange.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/ember-icon.svg b/assets/ember-icon.svg
new file mode 100644
index 00000000..e3be1018
--- /dev/null
+++ b/assets/ember-icon.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/ember.svg b/assets/ember.svg
new file mode 100644
index 00000000..6fd60f8d
--- /dev/null
+++ b/assets/ember.svg
@@ -0,0 +1,22 @@
+
diff --git a/assets/esports.svg b/assets/esports.svg
new file mode 100644
index 00000000..f97da597
--- /dev/null
+++ b/assets/esports.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/fire.svg b/assets/fire.svg
new file mode 100644
index 00000000..3004f516
--- /dev/null
+++ b/assets/fire.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/flash-faucet.svg b/assets/flash-faucet.svg
new file mode 100644
index 00000000..b35be7bf
--- /dev/null
+++ b/assets/flash-faucet.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/friends.svg b/assets/friends.svg
new file mode 100644
index 00000000..ba604ceb
--- /dev/null
+++ b/assets/friends.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/fuse-ember.svg b/assets/fuse-ember.svg
new file mode 100644
index 00000000..eda21403
--- /dev/null
+++ b/assets/fuse-ember.svg
@@ -0,0 +1,19 @@
+
diff --git a/assets/fuse-faucet.svg b/assets/fuse-faucet.svg
new file mode 100644
index 00000000..21df3957
--- /dev/null
+++ b/assets/fuse-faucet.svg
@@ -0,0 +1,39 @@
+
diff --git a/assets/fuse-flash.svg b/assets/fuse-flash.svg
new file mode 100644
index 00000000..ca53541f
--- /dev/null
+++ b/assets/fuse-flash.svg
@@ -0,0 +1,25 @@
+
diff --git a/assets/fuse-foundation-point-hexagon.svg b/assets/fuse-foundation-point-hexagon.svg
new file mode 100644
index 00000000..71cb034c
--- /dev/null
+++ b/assets/fuse-foundation-point-hexagon.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/fuse-foundation.svg b/assets/fuse-foundation.svg
new file mode 100644
index 00000000..d5df0150
--- /dev/null
+++ b/assets/fuse-foundation.svg
@@ -0,0 +1,22 @@
+
diff --git a/assets/fuse-founders.png b/assets/fuse-founders.png
new file mode 100644
index 00000000..647f7b33
Binary files /dev/null and b/assets/fuse-founders.png differ
diff --git a/assets/gooddollar-green.svg b/assets/gooddollar-green.svg
new file mode 100644
index 00000000..617063f0
--- /dev/null
+++ b/assets/gooddollar-green.svg
@@ -0,0 +1,28 @@
+
diff --git a/assets/gooddollar-yellow.svg b/assets/gooddollar-yellow.svg
new file mode 100644
index 00000000..1c2f9f37
--- /dev/null
+++ b/assets/gooddollar-yellow.svg
@@ -0,0 +1,28 @@
+
diff --git a/assets/gooddollar.svg b/assets/gooddollar.svg
new file mode 100644
index 00000000..f1b29e8e
--- /dev/null
+++ b/assets/gooddollar.svg
@@ -0,0 +1,28 @@
+
diff --git a/assets/group.svg b/assets/group.svg
new file mode 100644
index 00000000..c2422246
--- /dev/null
+++ b/assets/group.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/join-telegram-green.svg b/assets/join-telegram-green.svg
new file mode 100644
index 00000000..b874d656
--- /dev/null
+++ b/assets/join-telegram-green.svg
@@ -0,0 +1,25 @@
+
diff --git a/assets/join-telegram.svg b/assets/join-telegram.svg
new file mode 100644
index 00000000..a2d7fcef
--- /dev/null
+++ b/assets/join-telegram.svg
@@ -0,0 +1,33 @@
+
diff --git a/assets/join-waitlist.svg b/assets/join-waitlist.svg
new file mode 100644
index 00000000..4f322b63
--- /dev/null
+++ b/assets/join-waitlist.svg
@@ -0,0 +1,19 @@
+
diff --git a/assets/meridian-green.svg b/assets/meridian-green.svg
new file mode 100644
index 00000000..21966c7b
--- /dev/null
+++ b/assets/meridian-green.svg
@@ -0,0 +1,32 @@
+
diff --git a/assets/meridian-yellow.svg b/assets/meridian-yellow.svg
new file mode 100644
index 00000000..ab7daf46
--- /dev/null
+++ b/assets/meridian-yellow.svg
@@ -0,0 +1,32 @@
+
diff --git a/assets/meridian.svg b/assets/meridian.svg
new file mode 100644
index 00000000..5dc5b1b3
--- /dev/null
+++ b/assets/meridian.svg
@@ -0,0 +1,26 @@
+
diff --git a/assets/mintmark.svg b/assets/mintmark.svg
new file mode 100644
index 00000000..1c3fcf67
--- /dev/null
+++ b/assets/mintmark.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/paid.svg b/assets/paid.svg
new file mode 100644
index 00000000..80eb9e35
--- /dev/null
+++ b/assets/paid.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/point-hexagon-yellow.svg b/assets/point-hexagon-yellow.svg
new file mode 100644
index 00000000..fc5c031a
--- /dev/null
+++ b/assets/point-hexagon-yellow.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/points-phases.png b/assets/points-phases.png
new file mode 100644
index 00000000..e049d9ff
Binary files /dev/null and b/assets/points-phases.png differ
diff --git a/assets/questionmark-border.svg b/assets/questionmark-border.svg
new file mode 100644
index 00000000..e35ed6f9
--- /dev/null
+++ b/assets/questionmark-border.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/right-caret-black.svg b/assets/right-caret-black.svg
new file mode 100644
index 00000000..9bd6b191
--- /dev/null
+++ b/assets/right-caret-black.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/right-caret.svg b/assets/right-caret.svg
new file mode 100644
index 00000000..f1e3d726
--- /dev/null
+++ b/assets/right-caret.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/roulette-game.svg b/assets/roulette-game.svg
new file mode 100644
index 00000000..907a3a36
--- /dev/null
+++ b/assets/roulette-game.svg
@@ -0,0 +1,19 @@
+
diff --git a/assets/shoebill-green.svg b/assets/shoebill-green.svg
new file mode 100644
index 00000000..025b5103
--- /dev/null
+++ b/assets/shoebill-green.svg
@@ -0,0 +1,126 @@
+
diff --git a/assets/shoebill.svg b/assets/shoebill.svg
new file mode 100644
index 00000000..dd5808f7
--- /dev/null
+++ b/assets/shoebill.svg
@@ -0,0 +1,126 @@
+
diff --git a/assets/smart-toy.svg b/assets/smart-toy.svg
new file mode 100644
index 00000000..4f5001fe
--- /dev/null
+++ b/assets/smart-toy.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/star-bronze.svg b/assets/star-bronze.svg
new file mode 100644
index 00000000..197746ba
--- /dev/null
+++ b/assets/star-bronze.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/star-gold.svg b/assets/star-gold.svg
new file mode 100644
index 00000000..823a3f53
--- /dev/null
+++ b/assets/star-gold.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/star-silver.svg b/assets/star-silver.svg
new file mode 100644
index 00000000..e0412f22
--- /dev/null
+++ b/assets/star-silver.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/star.svg b/assets/star.svg
new file mode 100644
index 00000000..a775aa84
--- /dev/null
+++ b/assets/star.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/twitter-x-green.svg b/assets/twitter-x-green.svg
new file mode 100644
index 00000000..7c3366a2
--- /dev/null
+++ b/assets/twitter-x-green.svg
@@ -0,0 +1,19 @@
+
diff --git a/assets/twitter-x-logo.svg b/assets/twitter-x-logo.svg
new file mode 100644
index 00000000..8005c0f9
--- /dev/null
+++ b/assets/twitter-x-logo.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/twitter-x.svg b/assets/twitter-x.svg
new file mode 100644
index 00000000..5797df72
--- /dev/null
+++ b/assets/twitter-x.svg
@@ -0,0 +1,19 @@
+
diff --git a/assets/upload-file.svg b/assets/upload-file.svg
new file mode 100644
index 00000000..c8a3a1d7
--- /dev/null
+++ b/assets/upload-file.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/verify-discord-green.svg b/assets/verify-discord-green.svg
new file mode 100644
index 00000000..c7e74776
--- /dev/null
+++ b/assets/verify-discord-green.svg
@@ -0,0 +1,28 @@
+
diff --git a/assets/verify-discord.svg b/assets/verify-discord.svg
new file mode 100644
index 00000000..c562abfa
--- /dev/null
+++ b/assets/verify-discord.svg
@@ -0,0 +1,28 @@
+
diff --git a/assets/volt-wallet-green.svg b/assets/volt-wallet-green.svg
new file mode 100644
index 00000000..47be292e
--- /dev/null
+++ b/assets/volt-wallet-green.svg
@@ -0,0 +1,24 @@
+
diff --git a/assets/volt-wallet-yellow.svg b/assets/volt-wallet-yellow.svg
new file mode 100644
index 00000000..e4dfba4a
--- /dev/null
+++ b/assets/volt-wallet-yellow.svg
@@ -0,0 +1,24 @@
+
diff --git a/assets/volt-wallet.svg b/assets/volt-wallet.svg
new file mode 100644
index 00000000..f7b49f81
--- /dev/null
+++ b/assets/volt-wallet.svg
@@ -0,0 +1,24 @@
+
diff --git a/assets/voltage-liquidity-yellow.svg b/assets/voltage-liquidity-yellow.svg
new file mode 100644
index 00000000..b4aa53fb
--- /dev/null
+++ b/assets/voltage-liquidity-yellow.svg
@@ -0,0 +1,64 @@
+
diff --git a/assets/voltage-liquidity.svg b/assets/voltage-liquidity.svg
new file mode 100644
index 00000000..987c63d8
--- /dev/null
+++ b/assets/voltage-liquidity.svg
@@ -0,0 +1,64 @@
+
diff --git a/assets/wallet.svg b/assets/wallet.svg
new file mode 100644
index 00000000..f4d9d2c4
--- /dev/null
+++ b/assets/wallet.svg
@@ -0,0 +1,8 @@
+
diff --git a/components/FAQ.tsx b/components/FAQ.tsx
index aa9ff58f..13f8ffd6 100644
--- a/components/FAQ.tsx
+++ b/components/FAQ.tsx
@@ -3,7 +3,7 @@ import FaqQuestion from "./FaqQuestion";
type FAQProps = {
questions: string[];
- answers: JSX.Element[];
+ answers: JSX.Element[] | string[];
className?: string;
};
diff --git a/components/FaqQuestion.tsx b/components/FaqQuestion.tsx
index 3ea59429..2d5a77b8 100644
--- a/components/FaqQuestion.tsx
+++ b/components/FaqQuestion.tsx
@@ -6,7 +6,7 @@ import Image from "next/image";
type FaqQuestionProps = {
question: string;
- answer: JSX.Element;
+ answer: JSX.Element | string;
className?: string;
};
diff --git a/components/NavMenu.tsx b/components/NavMenu.tsx
index c7ab8320..19910fec 100644
--- a/components/NavMenu.tsx
+++ b/components/NavMenu.tsx
@@ -7,6 +7,10 @@ import { path, walletType } from "@/lib/helpers";
import { useAccount } from "wagmi";
import { selectOperatorSlice } from "@/store/operatorSlice";
import Link from "next/link";
+import { motion, Variants } from "framer-motion";
+import { useState } from "react";
+import Image from "next/image";
+import rightCaret from "@/assets/right-caret-black.svg";
type NavMenuProps = {
menuItems?: MenuItems;
@@ -26,17 +30,43 @@ const openMenuItemEvent: OpenMenuItemEvent = {
"Bridge": "Go to Bridge"
}
+const menu: Variants = {
+ closed: (isCenter) => ({
+ opacity: 0,
+ transition: {
+ delay: 0.15,
+ duration: 0.3,
+ },
+ y: -10,
+ x: isCenter ? "-50%" : 0,
+ transitionEnd: {
+ display: "none",
+ },
+ }),
+ open: (isCenter) => ({
+ opacity: 1,
+ display: "block",
+ transition: {
+ type: "spring",
+ duration: 0.5,
+ },
+ y: 0,
+ x: isCenter ? "-50%" : 0,
+ }),
+};
+
const NavMenu = ({
menuItems = [],
isOpen = false,
selected = "",
isResponsive = false,
className = `items-center justify-between w-auto order-1 absolute left-[50%] -translate-x-[50%] rounded-md ${isResponsive ? "md:w-full md:translate-y-8 md:top-1/2 md:bg-black" : ""}`,
- liClassName = "w-20",
+ liClassName = "w-fit",
}: NavMenuProps) => {
const matches = useMediaQuery("(min-width: 768px)");
const { address, connector } = useAccount();
const { isAuthenticated } = useAppSelector(selectOperatorSlice);
+ const [isHover, setIsHover] = useState(-1);
return (
<>
@@ -44,26 +74,62 @@ const NavMenu = ({
{menuItems.map((item, index) => (
- {
- amplitude.track(openMenuItemEvent[item.title], {
- walletType: connector ? walletType[connector.id] : undefined,
- walletAddress: address
- });
- }}
+ className="relative md:w-full"
>
-
+ {
+ amplitude.track(openMenuItemEvent[item.title], {
+ walletType: connector ? walletType[connector.id] : undefined,
+ walletAddress: address
+ });
+ }}
+ onMouseEnter={() => setIsHover(index)}
+ onMouseLeave={() => setIsHover(-1)}
+ >
{item.title}
-
-
+ {item.submenu && (
+
+ )}
+
+ {item.submenu && (
+ setIsHover(index)}
+ onMouseLeave={() => setIsHover(-1)}
+ >
+
+ {item.submenu.map((subItem, subIndex) => (
+
+ {subItem.title}
+
+ ))}
+
+
+ )}
+
))}
diff --git a/components/Topbar.tsx b/components/Topbar.tsx
index 3f9108dc..637a78b2 100644
--- a/components/Topbar.tsx
+++ b/components/Topbar.tsx
@@ -8,16 +8,33 @@ import { selectNavbarSlice } from "@/store/navbarSlice";
import { selectOperatorSlice } from "@/store/operatorSlice";
import { path } from "@/lib/helpers";
import Image from "next/image";
+import { selectAirdropSlice } from "@/store/airdropSlice";
+
+const AirdropSubmenu = [
+ {
+ title: "Leaderboard",
+ link: path.AIRDROP_LEADERBOARD,
+ },
+ {
+ title: "Fuse Ecosystem",
+ link: path.AIRDROP_ECOSYSTEM,
+ },
+]
const Topbar = () => {
const [isOpen, setOpen] = useState