Skip to content
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
25 changes: 9 additions & 16 deletions app/(home)/stats/l1/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,20 @@ import l1ChainsData from "@/constants/l1-chains.json";
import { Metadata } from "next";
import { L1Chain } from "@/types/stats";

// Helper function to find chain by slug
function findChainBySlug(slug?: string): L1Chain | null {
if (!slug) return null;
return l1ChainsData.find((c) => c.slug === slug) as L1Chain || null;
}

export async function generateMetadata({
params,
}: {
params: Promise<{ slug?: string[] }>;
}): Promise<Metadata> {
const resolvedParams = await params;
const slug = Array.isArray(resolvedParams.slug) ? resolvedParams.slug[0] : resolvedParams.slug;
const currentChain = l1ChainsData.find((c) => c.slug === slug) as L1Chain;
const currentChain = findChainBySlug(slug);

if (!currentChain) { return notFound(); }

Expand Down Expand Up @@ -52,22 +58,9 @@ export default async function L1Metrics({

if (!slug) { notFound(); }

const currentChain = l1ChainsData.find((c) => c.slug === slug) as L1Chain;
const currentChain = findChainBySlug(slug);

if (!currentChain) { notFound(); }

return (
<ChainMetricsPage
chainId={currentChain.chainId}
chainName={currentChain.chainName}
description={
currentChain.description ||
`Real-time insights into ${currentChain.chainName} L1 activity and network usage`
}
themeColor={currentChain.color || "#E57373"}
chainLogoURI={currentChain.chainLogoURI}
website={currentChain.website}
socials={currentChain.socials}
/>
);
return <ChainMetricsPage chain={currentChain} />;
}
7 changes: 0 additions & 7 deletions app/docs/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -359,13 +359,6 @@ body[data-layout="docs"] [data-sidebar="sidebar"] {
}
}

/* Sidebar content area - DOCS ONLY */
body[data-layout="docs"] #nd-sidebar > div,
body[data-layout="docs"] [data-sidebar="sidebar"] > div {
/*padding-left: 0.25rem !important;
padding-right: 0.25rem !important;*/
}

/* Reduce sidebar header spacing - DOCS ONLY */
body[data-layout="docs"] #nd-sidebar > div:first-child {
padding-bottom: 0.5rem !important;
Expand Down
173 changes: 80 additions & 93 deletions components/stats/ChainMetricsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import {Users, Activity, FileText, MessageSquare, TrendingUp, UserPlus, Hash, Code2, Gauge, DollarSign, Clock, Fuel, ArrowUpRight, Twitter, Linkedin } from "lucide-react";
import { StatsBubbleNav } from "@/components/stats/stats-bubble.config";
import { ChartSkeletonLoader } from "@/components/ui/chart-skeleton";
import { ExplorerDropdown } from "@/components/stats/ExplorerDropdown";
import { AvalancheLogo } from "@/components/navigation/avalanche-logo";
import l1ChainsData from "@/constants/l1-chains.json";
import { L1Chain } from "@/types/stats";

interface TimeSeriesDataPoint {
Expand Down Expand Up @@ -60,35 +58,26 @@ interface CChainMetrics {
}

interface ChainMetricsPageProps {
chainId?: string;
chainName?: string;
description?: string;
themeColor?: string;
chainLogoURI?: string;
website?: string;
socials?: {
twitter?: string;
linkedin?: string;
};
chain: L1Chain;
}

export default function ChainMetricsPage({
chainId = "43114",
chainName = "Avalanche C-Chain",
description = "Real-time metrics and analytics for the Avalanche C-Chain",
themeColor = "#E57373",
chainLogoURI,
website,
socials,
}: ChainMetricsPageProps) {
export default function ChainMetricsPage({ chain }: ChainMetricsPageProps) {
const [metrics, setMetrics] = useState<CChainMetrics | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);

// Find the current chain to get explorers
const currentChain = useMemo(() => {
return l1ChainsData.find((chain) => chain.chainId === chainId) as L1Chain | undefined;
}, [chainId]);
// Destructure chain properties for cleaner code
const {
chainId,
chainName,
chainLogoURI,
color: themeColor = "#E57373",
description = `Real-time insights into ${chainName} L1 activity and network usage`,
website,
socials,
category,
explorers
} = chain;

const fetchData = async () => {
try {
Expand Down Expand Up @@ -658,7 +647,7 @@ export default function ChainMetricsPage({
{description}
</p>
</div>
{currentChain?.category && (
{category && (
<div className="mt-3">
<span
className="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium"
Expand All @@ -667,83 +656,81 @@ export default function ChainMetricsPage({
color: themeColor,
}}
>
{currentChain.category}
{category}
</span>
</div>
)}
</div>
</div>

{!chainName.includes("C-Chain") && (
<div className="flex flex-col sm:flex-row items-end gap-2">
{/* Main action buttons */}
<div className="flex items-center gap-2">
{website && (
<Button
variant="outline"
size="sm"
asChild
className="border-zinc-300 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400 hover:border-zinc-400 dark:hover:border-zinc-600"
>
<a href={website} target="_blank" rel="noopener noreferrer" className="flex items-center gap-2">
Website
<ArrowUpRight className="h-4 w-4" />
</a>
</Button>
)}

{/* Social buttons */}
{currentChain?.socials && (currentChain.socials.twitter || currentChain.socials.linkedin) && (
<>
{currentChain.socials.twitter && (
<Button
variant="outline"
size="sm"
asChild
className="border-zinc-300 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400 hover:border-zinc-400 dark:hover:border-zinc-600 px-2"
>
<a
href={`https://x.com/${currentChain.socials.twitter}`}
target="_blank"
rel="noopener noreferrer"
aria-label="Twitter"
>
<Twitter className="h-4 w-4" />
</a>
</Button>
)}
{currentChain.socials.linkedin && (
<Button
variant="outline"
size="sm"
asChild
className="border-zinc-300 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400 hover:border-zinc-400 dark:hover:border-zinc-600 px-2"
<div className="flex flex-col sm:flex-row items-end gap-2">
{/* Main action buttons */}
<div className="flex items-center gap-2">
{website && (
<Button
variant="outline"
size="sm"
asChild
className="border-zinc-300 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400 hover:border-zinc-400 dark:hover:border-zinc-600"
>
<a href={website} target="_blank" rel="noopener noreferrer" className="flex items-center gap-2">
Website
<ArrowUpRight className="h-4 w-4" />
</a>
</Button>
)}

{/* Social buttons */}
{socials && (socials.twitter || socials.linkedin) && (
<>
{socials.twitter && (
<Button
variant="outline"
size="sm"
asChild
className="border-zinc-300 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400 hover:border-zinc-400 dark:hover:border-zinc-600 px-2"
>
<a
href={`https://x.com/${socials.twitter}`}
target="_blank"
rel="noopener noreferrer"
aria-label="Twitter"
>
<a
href={`https://linkedin.com/company/${currentChain.socials.linkedin}`}
target="_blank"
rel="noopener noreferrer"
aria-label="LinkedIn"
>
<Linkedin className="h-4 w-4" />
</a>
</Button>
)}
</>
)}

{currentChain?.explorers && (
<div className="[&_button]:border-zinc-300 dark:[&_button]:border-zinc-700 [&_button]:text-zinc-600 dark:[&_button]:text-zinc-400 [&_button]:hover:border-zinc-400 dark:[&_button]:hover:border-zinc-600">
<ExplorerDropdown
explorers={currentChain.explorers}
<Twitter className="h-4 w-4" />
</a>
</Button>
)}
{socials.linkedin && (
<Button
variant="outline"
size="sm"
/>
</div>
)}
</div>
asChild
className="border-zinc-300 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400 hover:border-zinc-400 dark:hover:border-zinc-600 px-2"
>
<a
href={`https://linkedin.com/company/${socials.linkedin}`}
target="_blank"
rel="noopener noreferrer"
aria-label="LinkedIn"
>
<Linkedin className="h-4 w-4" />
</a>
</Button>
)}
</>
)}

{explorers && (
<div className="[&_button]:border-zinc-300 dark:[&_button]:border-zinc-700 [&_button]:text-zinc-600 dark:[&_button]:text-zinc-400 [&_button]:hover:border-zinc-400 dark:[&_button]:hover:border-zinc-600">
<ExplorerDropdown
explorers={explorers}
variant="outline"
size="sm"
/>
</div>
)}
</div>
)}
</div>
</div>
</div>
</div>
Expand Down
7 changes: 7 additions & 0 deletions constants/l1-chains.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@
{
"chainId": "43114",
"chainName": "Avalanche C-Chain",
"description": "The Avalanche C-Chain is the EVM chain of the Primary L1. It is the liquidity hub of the Avalanche ecosystem and is validated by a large permissionless validator set.",
"website": "https://avax.network/",
"socials": {
"twitter": "avax",
"linkedin": "avalancheavax"
},
"chainLogoURI": "https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/3e4b8ff10b69bfa31e70080a4b142cd0/avalanche-avax-logo.svg",
"subnetId": "11111111111111111111111111111111LpoYY",
"slug": "c-chain",
Expand Down Expand Up @@ -135,6 +141,7 @@
"description": "The Binary Holdings is a Web3 infrastructure firm powers loyalty programs for telcos in South East Asia, has officially deployed its native Avalanche L1, giving TBH the foundation to accelerate user adoption through its unique telco-powered distribution network.",
"website": "https://www.thebinaryholdings.com/",
"socials": {
"twitter": "thebinaryhldgs",
"linkedin": "the-binary-holdings"
},
"explorers": [
Expand Down