stones/src/app/token-holders/page.tsx

209 lines
7.1 KiB
TypeScript

import { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import { getUser } from "@/lib/auth";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { LogoutButton } from "@/components/auth/logout-button";
import { Input } from "@/components/ui/input";
import { prisma } from "@/lib/prisma";
export const metadata: Metadata = {
title: "Token Holders - Stones Database",
description: "Track holders of ERC20 tokens",
};
export default async function TokenHoldersPage() {
const user = await getUser();
if (!user) {
notFound();
}
// Mock token data (this would be replaced with real data from the database)
const tokens = [
{
id: "stones",
name: "Stones",
symbol: "STONES",
description: "The native token of the Stones ecosystem",
imageUrl: "https://placekitten.com/203/203",
holders: 1245,
marketCap: "$4.5M",
},
{
id: "eth",
name: "Ethereum",
symbol: "ETH",
description: "Native cryptocurrency of the Ethereum blockchain",
imageUrl: "https://placekitten.com/204/204",
holders: 52000000,
marketCap: "$367B",
},
{
id: "dai",
name: "Dai Stablecoin",
symbol: "DAI",
description: "Decentralized stablecoin pegged to the US Dollar",
imageUrl: "https://placekitten.com/205/205",
holders: 684000,
marketCap: "$5.2B",
},
];
return (
<div className="flex min-h-screen flex-col">
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container flex h-14 items-center justify-between">
<div className="mr-4 flex">
<Link href="/" className="mr-6 flex items-center space-x-2">
<span className="font-bold">Stones Database</span>
</Link>
</div>
<nav className="flex items-center space-x-4">
<Link href="/contacts" className="text-sm font-medium">
Contacts
</Link>
<Link href="/dashboard" className="text-sm font-medium">
Dashboard
</Link>
{user && (
<div className="flex items-center gap-4">
<span className="text-sm text-muted-foreground">
Hello, {user.name}
</span>
<LogoutButton />
</div>
)}
</nav>
</div>
</header>
<main className="flex-1 container py-6">
<div className="flex items-center justify-between mb-6">
<div>
<Link href="/dashboard">
<p className="text-sm text-blue-500 hover:text-blue-700 mb-2">
Back to Dashboard
</p>
</Link>
<h1 className="text-3xl font-bold">Token Holders</h1>
<p className="text-gray-500 mt-1">Track holders of ERC20 tokens</p>
</div>
<div className="flex gap-2">
<Button variant="outline">
Add New Token
</Button>
<Button>
Sync Token Data
</Button>
</div>
</div>
<div className="mb-6">
<Card>
<CardHeader>
<CardTitle>Search Tokens</CardTitle>
</CardHeader>
<CardContent>
<div className="flex gap-4">
<Input placeholder="Search by token name, symbol, or contract address" className="max-w-xl" />
<Button>Search</Button>
</div>
</CardContent>
</Card>
</div>
<div className="grid gap-6 md:grid-cols-3">
{tokens.map((token) => (
<Card key={token.id}>
<div className="p-4 flex items-center gap-4">
<img
src={token.imageUrl}
alt={token.name}
className="w-16 h-16 rounded-full"
/>
<div>
<h3 className="font-bold">{token.name}</h3>
<p className="text-sm text-gray-500">{token.symbol}</p>
</div>
</div>
<CardContent className="pt-0 space-y-4">
<p className="text-sm text-gray-500">{token.description}</p>
<div className="grid grid-cols-2 gap-4">
<div>
<p className="text-sm text-gray-500">Holders</p>
<p className="font-medium">{token.holders.toLocaleString()}</p>
</div>
<div>
<p className="text-sm text-gray-500">Market Cap</p>
<p className="font-medium">{token.marketCap}</p>
</div>
</div>
<div className="flex justify-end">
<Link href={`/token-holders/${token.id}`}>
<Button variant="secondary">
View Holders
</Button>
</Link>
</div>
</CardContent>
</Card>
))}
</div>
<div className="mt-8">
<Card>
<CardHeader>
<CardTitle>Add Token</CardTitle>
</CardHeader>
<CardContent>
<form className="space-y-4">
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
<div className="space-y-2">
<label htmlFor="token-name" className="text-sm font-medium">
Token Name
</label>
<Input
id="token-name"
placeholder="Enter token name"
/>
</div>
<div className="space-y-2">
<label htmlFor="token-symbol" className="text-sm font-medium">
Token Symbol
</label>
<Input
id="token-symbol"
placeholder="e.g., ETH"
/>
</div>
</div>
<div className="space-y-2">
<label htmlFor="contract-address" className="text-sm font-medium">
Contract Address
</label>
<Input
id="contract-address"
placeholder="0x..."
/>
</div>
<div className="flex justify-end">
<Button type="submit">
Add Token
</Button>
</div>
</form>
</CardContent>
</Card>
</div>
</main>
<footer className="w-full border-t py-6">
<div className="container flex flex-col items-center justify-between gap-4 md:flex-row">
<p className="text-center text-sm leading-loose text-muted-foreground md:text-left">
© 2025 BoilerHaus. All rights reserved.
</p>
</div>
</footer>
</div>
);
}