Skip to content

Commit

Permalink
Merge pull request #154 from penumbra-zone/landing-page-update
Browse files Browse the repository at this point in the history
Updated landing page to match redesign
  • Loading branch information
ejmg authored Jul 30, 2024
2 parents da21912 + 4995b22 commit 6ab549f
Show file tree
Hide file tree
Showing 9 changed files with 284 additions and 106 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "next dev --turbo",
"build": "next build",
"start": "next start",
"lint": "next lint",
Expand Down
4 changes: 2 additions & 2 deletions src/app/api/blocks/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { sql } from "@pgtyped/runtime";
import { IGetBlocksByDescQuery, IGetBlocksCountQuery} from "./route.types";
import { getPgClient } from "@/lib/db";

export async function POST(req: Request) {
console.log("POST req on /api/blocks/");
export async function GET(req: Request) {
console.log("GET req on /api/blocks/");
try {
const url = new URL(req.url);
const pageParam = url.searchParams.get("page")?.trim() ?? "";
Expand Down
16 changes: 7 additions & 9 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,16 @@ export default function RootLayout({
<body className="bg-gradient-repeat-radial min-w-full min-h-screen">
<Providers>
<Navbar />
<div className="flex flex-col container xs-container justify-start min-h-[640px]">
<div className="p-1 sm:p-2 mb-auto">
{children}
</div>
<div className="self-center py-5">
<Link href="https://github.com/penumbra-zone/cuiloa">
<CodeIcon className="w-4" />
</Link>
</div>
<div className="container xs-container justify-start min-h-[640px]">
{children}
</div>
<ReactQueryDevtools initialIsOpen={false} />
</Providers>
<div className="flex flex-col justify-center items-center h-full">
<Link href="https://github.com/penumbra-zone/cuiloa">
<CodeIcon className="w-4" />
</Link>
</div>
</body>
</html>
);
Expand Down
169 changes: 127 additions & 42 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,140 @@ import Link from "next/link";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";

import { Button } from "@/components/ui/button";
import { FC } from "react";
import { getQueryClient } from "@/lib/utils";

import { dehydrate, HydrationBoundary } from "@tanstack/react-query";
import { PreviewTable } from "@/components/PreviewTable";
import { getBlocks } from "@/components/BlocksTable/getBlocks";
import { getTransactions } from "@/components/TransactionsTable/getTransactions";


interface CardProps {
buttonText: string,
buttonLink: string,
children?: React.ReactNode,
className?: string,
heading: string,
}

const LandingCard: FC<CardProps> = ({ heading, children, className, buttonText, buttonLink }) => {
return (
<Card className={className}>
<CardHeader>
<CardTitle className="text-lg font-medium">{heading}</CardTitle>
</CardHeader>
<CardContent className="flex flex-col gap-1 items-center">
{children}
<Button className="w-full" asChild>
<Link href={buttonLink}>{buttonText}</Link>
</Button>
</CardContent>
</Card>
);
};

export default function Home() {
const queryClient = getQueryClient();

const blocksQuery = "previewBlocks";
const transactionsQuery = "previewTransactions";
const blocksEndpoint = "api/blocks";
const transactionEndpoint = "api/transactions";
const errorMessage = "Problems were encountered while trying to query explorer data for the main page, please try again.";

Promise.all([
queryClient.prefetchQuery({
queryFn: () => getTransactions({ endpoint: transactionEndpoint, pageIndex: 0 }),
queryKey: [transactionsQuery],
meta: {
errorMessage,
},
}),
queryClient.prefetchQuery({
queryFn: () => getBlocks({ endpoint: blocksEndpoint, pageIndex: 0 }),
queryKey: [blocksQuery],
meta: {
errorMessage,
},
}),
]);

export default async function Home() {
// Idea: break out the buttons to their own cards where each uses the description to help describe the data to users.
return (
<div className="flex gap-5 items-center justify-center py-5">
<div>
<Card>
<CardHeader className="">
<CardTitle className="text-center text-lg sm:text-2xl">
Penumbra is constantly evolving...
</CardTitle>
<CardDescription className="text-center">
Navigate and explore public chain data with the links below.
</CardDescription>
</CardHeader>
<CardContent className="flex flex-col gap-1 items-center">
<Button className="sm:w-2/3 w-full" asChild>
<Link href="/transactions">Recent Transactions</Link>
</Button>
<Button className="sm:w-2/3 w-full" asChild>
<Link href="/blocks">Recent Blocks</Link>
</Button>
<Button className="sm:w-2/3 w-full" asChild>
<Link href="/ibc/clients">IBC Clients</Link>
</Button>
<Button className="sm:w-2/3 w-full" asChild>
<Link href="/ibc/channels">IBC Channels</Link>
</Button>
<Button className="sm:w-2/3 w-full" asChild>
<Link href="/ibc/connections">IBC Connections</Link>
</Button>
<Button className="sm:w-2/3 w-full" asChild>
<Link href="/staking">Staking</Link>
</Button>
<Button className="sm:w-2/3 w-full" asChild>
<Link href="/dex">Dex</Link>
</Button>
<Button className="sm:w-2/3 w-full" asChild>
<Link href="/governance">Governance</Link>
</Button>
</CardContent>
</Card>
</div>
<div className="flex flex-wrap gap-3 items-center justify-between py-5">
<LandingCard
heading="Transactions"
buttonLink="/transactions"
buttonText="Explore Transactions"
className="basis-[45%] w-full max-w-screen-sm"
children={
<HydrationBoundary state={dehydrate(queryClient)}>
<PreviewTable
className="w-full"
queryName={transactionsQuery}
pageIndex={0}
endpoint={transactionEndpoint}
errorMessage={errorMessage}/>
</HydrationBoundary>
}
/>
<LandingCard
heading="Blocks"
buttonLink="/blocks"
buttonText="Explore Blocks"
className="basis-[50%] w-full max-w-screen-sm"
children={
<HydrationBoundary state={dehydrate(queryClient)}>
<PreviewTable
className="w-full"
queryName={blocksQuery}
pageIndex={0}
endpoint={blocksEndpoint}
errorMessage={errorMessage}/>
</HydrationBoundary>
}
/>
<LandingCard
heading="IBC Clients"
buttonLink="/ibc/clients"
buttonText="Explore Clients"
className="w-[380px]"
/>
<LandingCard
heading="IBC Connections"
buttonLink="/ibc/connections"
buttonText="Explore Connections"
className="w-[380px]"
/>
<LandingCard
heading="IBC Channels"
buttonLink="/ibc/channels"
buttonText="Explore Channels"
className="w-[380px]"
/>
<LandingCard
heading="Staking"
buttonLink="/staking"
buttonText="Explore Staking"
className="w-[380px]"
/>
<LandingCard
heading="Dex"
buttonLink="/dex"
buttonText="Explore Dex"
className="w-[380px]"
/>
<LandingCard
heading="Governance"
buttonLink="/governance"
buttonText="Explore Governance"
className="w-[380px]"
/>
</div>
);
}
4 changes: 2 additions & 2 deletions src/components/BlocksTable/getBlocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { BlocksTableQuery } from "@/lib/validators/table";

export async function getBlocks ({ endpoint, pageIndex } : ({ endpoint: string, pageIndex: number })) {
const baseUrl = getBaseURL();
console.log(`Fetching: POST ${baseUrl}/?page=${pageIndex}`);
const res = await fetch(`${baseUrl}/${endpoint}?page=${pageIndex}`, { method: "POST" });
console.log(`Fetching: GET ${baseUrl}/${endpoint}/?page=${pageIndex}`);
const res = await fetch(`${baseUrl}/${endpoint}?page=${pageIndex}`, { method: "GET" });
const json = await res.json();

console.log("Fetched result:", json);
Expand Down
16 changes: 13 additions & 3 deletions src/components/Navbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Link from "next/link";
import Image from "next/image";
import { ThemeToggleButton } from "../ThemeToggleButton";
import radiantLogoRainbow from "./radiant-logo-rainbow.png";
import radiantLogoBw from "./radiant-logo-bw.png";
import { workSans } from "@/app/fonts";

const RadiantLogoRainbow = ({ width, height, className } : { width: number, height: number, className?: string }) => {
Expand All @@ -16,12 +17,21 @@ const RadiantLogoRainbow = ({ width, height, className } : { width: number, heig
);
};

const RadiantLogoBw = ({ width, height, className } : { width: number, height: number, className?: string }) => {
return (
<div className={className}>
<Image src={radiantLogoBw} alt="RadiantCommons.com Logo" width={width} height={height}/>
</div>
);
};

export const Navbar : FC = () => {
return (
<div className="flex justify-between items-center py-8 max-w-[1200px] mx-auto">
<div className="flex-grow flex flex-wrap items-baseline">
<div className="flex justify-between items-center p-8 max-w-[1400px] mx-auto">
<div className="flex-grow flex flex-wrap items-center">
<Link href="https://radiantcommons.com" className="self-center" >
<RadiantLogoRainbow height={24} width={24}/>
<RadiantLogoRainbow height={48} width={48} className="dark:block hidden"/>
<RadiantLogoBw height={48} width={48} className="dark:hidden "/>
</Link>
<h1 className={`font-semibold text-2xl ml-1 mr-3 ${workSans.className}`}><Link href="/">Cuiloa</Link></h1>
<Link className={`text-link font-medium font-display ${workSans.className}`} href="https://penumbra.zone/">
Expand Down
89 changes: 89 additions & 0 deletions src/components/PreviewTable/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"use client";

import { columns as blocksColumns} from "@/components/BlocksTable/columns";
import { columns as transactionsColumns } from "@/components/TransactionsTable/columns";
import { useSuspenseQuery } from "@tanstack/react-query";
import { DataTable } from "../ui/data-table";
import { getBlocks } from "@/components/BlocksTable/getBlocks";
import { getTransactions } from "../TransactionsTable/getTransactions";
import { cn } from "@/lib/utils";

export interface QueryOptions {
pageIndex: number,
pageSize: number,
}

interface PreviewTableProps {
className?: string,
queryName: "previewBlocks" | "previewTransactions",
pageIndex: number,
endpoint: string,
errorMessage: string,
}

// TODO: Unbelievably gross stuff that needs to be parameterized later.
// TODO: It would be nice to have a tagged union type that allows narrowing instead of all the gross stuff up to this point.
// In addition to that, however, is the need to resolve the slices below. The current APIs do an integer check for offsets
// that prevent values below 10. It really shouldn't be an issue but it would be nice to do something better than this.
export function PreviewTable ({
className,
queryName,
pageIndex = 0,
endpoint,
errorMessage,
} : PreviewTableProps) {

const getFn = queryName === "previewBlocks" ? getBlocks : getTransactions;

const { data } : {
data : {
pages: number;
results: {
height: bigint;
created_at: string;
}[];
} | {
pages: number;
results: {
height: bigint;
created_at: string;
tx_hash: string;
}[];
}
} = useSuspenseQuery({
queryKey: [queryName],
queryFn: () => getFn({ endpoint, pageIndex }),
meta: {
errorMessage,
},
});

const { results } = data ?? { pages: 0, results: []};

// Checks only necessary for safely enforcing type. See todo comment above.
if (queryName === "previewBlocks") {
const tableData = results as {
height: bigint,
created_at: string,
}[];

return (
<div className={cn("", className)}>
<DataTable data={tableData.slice(0,3)} columns={blocksColumns}/>
</div>
);
} else {

const tableData = results as {
height: bigint,
created_at: string,
tx_hash: string
}[];

return (
<div className={cn("overflow-auto", className)}>
<DataTable data={tableData.slice(0,3)} columns={transactionsColumns}/>
</div>
);
}
};
3 changes: 0 additions & 3 deletions src/components/Providers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
}




const Providers = ({ children } : { children: React.ReactNode }) => {
// NOTE: there is a very explicit warning in the TanStack docs about using useState for handling QueryClient (de)hydration within the provider in the scenario where
// there is no Suspense boundary between the instantiation (here) and the context that is being wrapped; however, it is more or less considered best practice to
Expand Down
Loading

0 comments on commit 6ab549f

Please sign in to comment.