Skip to content

Instantly share code, notes, and snippets.

@DistractionBoy
Last active May 17, 2023 14:22
Show Gist options
  • Save DistractionBoy/916a1663d0a38526b8ba6ffc603f48eb to your computer and use it in GitHub Desktop.
Save DistractionBoy/916a1663d0a38526b8ba6ffc603f48eb to your computer and use it in GitHub Desktop.
import type { NextPage } from "next";
import {
HeadMeta,
LeftSidebar,
RightSidebar,
PortfolioSummary,
MainContentSection,
} from "../components";
const Home: NextPage = () => {
return (
<>
<HeadMeta />
<div className="py-10 flex flex-col">
<div className="w-screen flex flex-col justify-start items-stretch px-4 md:mx-auto md:px-6 lg:max-w-7xl lg:grid lg:grid-cols-12 lg:gap-8">
<LeftSidebar />
<section className="flex flex-col lg:col-span-9 xl:col-span-10">
<PortfolioSummary />
<main className="mt-4 lg:grid lg:grid-cols-12 lg:gap-4">
<div className="col-span-12 lg:col-span-8">
<MainContentSection />
</div>
<RightSidebar />
</main>
</section>
</div>
</div>
</>
);
};
export default Home;
import {
HomeIcon,
FireIcon,
UserGroupIcon,
TrendingUpIcon,
} from "@heroicons/react/outline";
import { useRouter } from "next/router";
import React, { useEffect, useState } from "react";
import { NavLink } from "../lib";
import { classNames } from "../lib/helpers";
const navDefaultState: NavLink[] = [
{ name: "Profile", href: "/", Icon: HomeIcon, current: false },
{
name: "For Creators",
href: "/creators",
Icon: UserGroupIcon,
current: false,
},
{ name: "Bundles", href: "/bundles", Icon: FireIcon, current: false },
{
name: "Profit Loss",
href: "/profit-loss",
Icon: TrendingUpIcon,
current: false,
},
];
export interface LeftSidebarProps {
mainNavigation?: NavLink[];
bottomHalfLabel?: string;
bottomHalfItems?: NavLink[];
}
// const bottomHalfLabelSample = "Bottom Items";
// const bottomLinksSample = [
// { name: "item 1", href: "#" },
// { name: "item 2", href: "#" },
// { name: "item 3", href: "#" },
// { name: "item 4", href: "#" },
// { name: "item 5", href: "#" },
// { name: "item 6", href: "#" },
// { name: "item 7", href: "#" },
// { name: "item 8", href: "#" },
// ];
export default function LeftSidebar({
bottomHalfItems,
bottomHalfLabel,
}: LeftSidebarProps) {
const router = useRouter();
const [navigation, setNavigation] = useState<NavLink[]>(navDefaultState);
const [bottomLinks, setBottomLinks] = useState<NavLink[] | null>(
bottomHalfItems || null
);
const [bottomLabel, setBottomLabel] = useState<string | null>(
bottomHalfLabel || null
);
useEffect(() => {
if (router.isReady) {
setNavigation((prevState) => {
return prevState.map((navLink) => {
let link = navLink;
const pathPartToMatch = router.pathname.split("/")[1];
const linkPartToMatch = link.href?.split("/")[1];
if (pathPartToMatch === linkPartToMatch) {
link.current = true;
}
return link;
});
});
}
}, [router]);
return (
<div className="hidden sticky top-20 lg:block lg:col-span-3 xl:col-span-2">
<nav aria-label="Sidebar" className="top-4 divide-y divide-gray-300">
<div className="pb-8 space-y-1">
{navigation.map(({ name, href, Icon, current }) => (
<a
key={name}
href={href}
className={classNames(
current
? "bg-gray-200 text-gray-900"
: "text-gray-600 hover:bg-gray-50",
"group flex items-center px-3 py-2 text-sm font-medium rounded-md"
)}
aria-current={current ? "page" : undefined}
>
{Icon && (
<Icon
className={classNames(
current
? "text-gray-500"
: "text-gray-400 group-hover:text-gray-500",
"flex-shrink-0 -ml-1 mr-3 h-6 w-6"
)}
aria-hidden="true"
/>
)}
<span className="truncate">{name}</span>
</a>
))}
</div>
{bottomLinks && (
<div className="pt-10">
{bottomLabel && (
<p
className="px-3 text-xs font-semibold text-gray-500 uppercase tracking-wider"
id="communities-headline"
>
{`${bottomLabel}`}
</p>
)}
<div
className="mt-3 space-y-2"
aria-labelledby="communities-headline"
>
{bottomLinks.map((community) => (
<a
key={community.name}
href={community.href}
className="group flex items-center px-3 py-2 text-sm font-medium text-gray-600 rounded-md hover:text-gray-900 hover:bg-gray-50"
>
<span className="truncate">{community.name}</span>
</a>
))}
</div>
</div>
)}
</nav>
</div>
);
}
import { useWeb3React } from "@web3-react/core";
import Image from "next/image";
import React from "react";
import useSWR from "swr";
import { WalletValueResponseType } from "../lib";
import { getBaseUrl } from "../lib/helpers";
import { RightSidebarProps } from "./RightSidebar";
export default function LiquidIlliquid({ searchAddress }: RightSidebarProps) {
const { account } = useWeb3React();
const baseUrl = getBaseUrl();
const walletValueUrl = `${baseUrl}/api/walletValue/${
searchAddress || account
}`;
const { data, error, isValidating } = useSWR<WalletValueResponseType, Error>(
walletValueUrl
);
const loading = !data && !error && isValidating;
if (error) {
return (
<section aria-labelledby="liquid-illiquid-heading">
<div className="bg-white rounded-lg shadow">
<div className="p-6">
<h2
id="liquid-illiquid-heading"
className="text-base font-medium text-gray-900"
>
{error.message}
</h2>
</div>
</div>
</section>
);
}
return !!data?.liquidIlliquid ? (
<section aria-labelledby="liquid-illiquid-heading">
<div className="bg-primary bg-gradient-to-tr via-secondary from-secondary rounded-lg shadow">
<div className="pt-6">
<h2
id="liquid-illiquid-heading"
className="px-6 text-xl font-extrabold text-white"
>
Liquid / Illiquid Supply
</h2>
<div className="mt-6 flex flex-row font-extrabold text-lg text-white">
<div className="p-6">
Liquid Value: <br />${data?.liquidIlliquid?.liquidAmountUsd}
</div>
<div className="p-6">
Illiquid Value: <br />${data?.liquidIlliquid?.illiquidAmountUsd}
</div>
</div>
<ul role="list" className="p-6 bg-white grid grid-cols-2 mx-auto">
{Object.values(data?.liquidIlliquid?.liquidBreakdown).map(
(collectionTotals, idx) => (
<div className="flex flex-col items-start even:pl-4" key={idx}>
<div className="h-24 w-24">
<Image
className="rounded-lg shadow-lg"
src={collectionTotals.imageUrl ?? "/images/icon.png"}
width={50}
height={50}
alt=""
layout="responsive"
/>
</div>
<div className="text-sm pt-1 line-clamp-2">
{collectionTotals.collectionName}
</div>
<div className="text-xs mb-4">
${collectionTotals.liquidAmountUsd.toFixed(2)}
</div>
</div>
)
)}
</ul>
</div>
</div>
</section>
) : null;
}
import React from "react";
import WalletDiversity from "./WalletDiversity";
import LiquidIlliquid from "./LiquidIlliquid";
export interface RightSidebarProps {
searchAddress?: string;
}
export default function RightSidebar(props: RightSidebarProps) {
return (
<aside className="block mt-4 lg:mt-0 col-span-12 lg:col-span-4 space-y-4">
<WalletDiversity {...props} />
<LiquidIlliquid {...props} />
</aside>
);
}
import { useWeb3React } from "@web3-react/core";
import React, { useState } from "react";
import useSWR from "swr";
import { WalletValueResponseType } from "../lib";
import { getBaseUrl } from "../lib/helpers";
import { RightSidebarProps } from "./RightSidebar";
import WalletAsset from "./WalletAsset";
const emptyState = [{}, {}, {}, {}, {}, {}];
const EmptyWalletAsset = () => {
return (
<div className="flex flex-row items-center justify-center py-2 space-x-3">
<div className="bg-gray-300 w-10 h-8 animate-pulse rounded-md shadow"></div>
<div className="h-9 flex flex-col w-full justify-between">
<div className="text-sm font-medium bg-gray-200 w-8"></div>
<div className="mt-1 bg-gray-100 h-3 rounded-lg">
<div
className="bg-gray-400 h-3 rounded-lg animate-pulse"
style={{
width: `${Math.random() * 100}%`,
}}
/>
</div>
</div>
<div className="min-w-0 flex flex-col justify-between items-center space-y-1 pt-1"></div>
</div>
);
};
export default function WalletDiversity({ searchAddress }: RightSidebarProps) {
const { account } = useWeb3React();
const baseUrl = getBaseUrl();
const [expanded, setExpanded] = useState<boolean>();
const walletValueUrl = `${baseUrl}/api/walletValue/${
searchAddress || account
}`;
const { data, error, isValidating } = useSWR<WalletValueResponseType, Error>(
walletValueUrl
);
const loading = !data && !error && isValidating;
if (loading) {
return (
<section aria-labelledby="wallet-value-heading">
<div className="bg-white rounded-lg shadow">
<div className="p-6">
<h2
id="wallet-value-heading"
className="text-base font-medium text-gray-900"
>
Wallet Diversity
</h2>
<div className="mt-6 flow-root">
<ul role="list" className="-my-4 divide-y divide-gray-200">
{Object.values(emptyState).map((_, idx) => (
<EmptyWalletAsset key={idx} />
))}
</ul>
</div>
</div>
</div>
</section>
);
}
if (error) {
return (
<section aria-labelledby="wallet-value-heading">
<div className="bg-white rounded-lg shadow">
<div className="p-6">
<h2
id="wallet-value-heading"
className="text-base font-medium text-gray-900"
>
{error.message}
</h2>
</div>
</div>
</section>
);
}
return (
<section aria-labelledby="wallet-value-heading">
<div className="bg-white rounded-lg shadow">
<div className="p-6">
<h2
id="wallet-value-heading"
className="text-base font-medium text-gray-900"
>
Wallet Diversity
</h2>
<div className="mt-6 flow-root">
<ul role="list" className="-my-4 divide-y divide-gray-200">
{Object.values(data?.portfolio ?? {})
.sort((a, b) => b.percentage - a.percentage)
.map(
(asset, idx) =>
(idx < 7 || expanded) && (
<WalletAsset key={idx} asset={asset} />
)
)}
{!expanded && (
<div className="flex flex-row-reverse">
<button
className="my-3 hover:text-secondary"
onClick={() => setExpanded(true)}
>
Expand All
</button>
</div>
)}
</ul>
</div>
</div>
</div>
</section>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment