Center copyright footer and remove placeholder pages
This commit is contained in:
parent
ee43d8bb2c
commit
530edd7e0b
|
|
@ -67,8 +67,8 @@ export default async function ImportContactsPage() {
|
||||||
</Card>
|
</Card>
|
||||||
</main>
|
</main>
|
||||||
<footer className="w-full border-t py-6">
|
<footer className="w-full border-t py-6">
|
||||||
<div className="container flex flex-col items-center justify-between gap-4 md:flex-row">
|
<div className="container flex justify-center items-center">
|
||||||
<p className="text-center text-sm leading-loose text-muted-foreground md:text-left">
|
<p className="text-center text-sm leading-loose text-muted-foreground">
|
||||||
© 2025 BoilerHaus. All rights reserved.
|
© 2025 BoilerHaus. All rights reserved.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,8 @@ export default async function NewContactPage() {
|
||||||
</Card>
|
</Card>
|
||||||
</main>
|
</main>
|
||||||
<footer className="w-full border-t py-6">
|
<footer className="w-full border-t py-6">
|
||||||
<div className="container flex flex-col items-center justify-between gap-4 md:flex-row">
|
<div className="container flex justify-center items-center">
|
||||||
<p className="text-center text-sm leading-loose text-muted-foreground md:text-left">
|
<p className="text-center text-sm leading-loose text-muted-foreground">
|
||||||
© 2025 BoilerHaus. All rights reserved.
|
© 2025 BoilerHaus. All rights reserved.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -130,8 +130,8 @@ export default async function ContactsPage({ searchParams }: ContactsPageProps)
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
<footer className="w-full border-t py-6">
|
<footer className="w-full border-t py-6">
|
||||||
<div className="container flex flex-col items-center justify-between gap-4 md:flex-row">
|
<div className="container flex justify-center items-center">
|
||||||
<p className="text-center text-sm leading-loose text-muted-foreground md:text-left">
|
<p className="text-center text-sm leading-loose text-muted-foreground">
|
||||||
© 2025 BoilerHaus. All rights reserved.
|
© 2025 BoilerHaus. All rights reserved.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,209 +0,0 @@
|
||||||
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: "DAO Members - Stones Database",
|
|
||||||
description: "Track members of Moloch DAOs",
|
|
||||||
};
|
|
||||||
|
|
||||||
export default async function DAOMembersPage() {
|
|
||||||
const user = await getUser();
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
notFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mock DAO data (this would be replaced with real data from the database)
|
|
||||||
const daos = [
|
|
||||||
{
|
|
||||||
id: "raid-guild",
|
|
||||||
name: "Raid Guild",
|
|
||||||
description: "A Decentralized Collective of Mercenaries Ready to Slay Your Web3 Product Demons",
|
|
||||||
imageUrl: "https://placekitten.com/206/206",
|
|
||||||
members: 178,
|
|
||||||
treasury: "2.5M $RAID",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "metacartel",
|
|
||||||
name: "MetaCartel",
|
|
||||||
description: "A DAO focused on funding early-stage decentralized applications",
|
|
||||||
imageUrl: "https://placekitten.com/207/207",
|
|
||||||
members: 82,
|
|
||||||
treasury: "436 ETH",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "daohaus",
|
|
||||||
name: "DAOhaus",
|
|
||||||
description: "The Shared Community DAO Infrastructure for Moloch DAOs",
|
|
||||||
imageUrl: "https://placekitten.com/208/208",
|
|
||||||
members: 120,
|
|
||||||
treasury: "320 ETH",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
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">DAO Members</h1>
|
|
||||||
<p className="text-gray-500 mt-1">Track members of Moloch DAOs</p>
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-2">
|
|
||||||
<Button variant="outline">
|
|
||||||
Add New DAO
|
|
||||||
</Button>
|
|
||||||
<Button>
|
|
||||||
Sync Members
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-6">
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Search DAOs</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div className="flex gap-4">
|
|
||||||
<Input placeholder="Search by DAO name or contract address" className="max-w-xl" />
|
|
||||||
<Button>Search</Button>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid gap-6 md:grid-cols-3">
|
|
||||||
{daos.map((dao) => (
|
|
||||||
<Card key={dao.id} className="overflow-hidden">
|
|
||||||
<div className="relative">
|
|
||||||
<img
|
|
||||||
src={dao.imageUrl}
|
|
||||||
alt={dao.name}
|
|
||||||
className="w-full h-40 object-cover"
|
|
||||||
/>
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent flex items-end p-4">
|
|
||||||
<h3 className="text-xl font-bold text-white">{dao.name}</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<CardContent className="pt-4 space-y-4">
|
|
||||||
<p className="text-sm text-gray-500">{dao.description}</p>
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
|
||||||
<div>
|
|
||||||
<p className="text-sm text-gray-500">Members</p>
|
|
||||||
<p className="font-medium">{dao.members}</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="text-sm text-gray-500">Treasury</p>
|
|
||||||
<p className="font-medium">{dao.treasury}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-end">
|
|
||||||
<Link href={`/dao-members/${dao.id}`}>
|
|
||||||
<Button variant="secondary">
|
|
||||||
View Members
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-8">
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Add DAO</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="dao-name" className="text-sm font-medium">
|
|
||||||
DAO Name
|
|
||||||
</label>
|
|
||||||
<Input
|
|
||||||
id="dao-name"
|
|
||||||
placeholder="Enter DAO name"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-2">
|
|
||||||
<label htmlFor="dao-type" className="text-sm font-medium">
|
|
||||||
DAO Type
|
|
||||||
</label>
|
|
||||||
<select
|
|
||||||
id="dao-type"
|
|
||||||
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
|
||||||
>
|
|
||||||
<option value="moloch">Moloch DAO</option>
|
|
||||||
<option value="compound">Compound Governance</option>
|
|
||||||
<option value="aragon">Aragon DAO</option>
|
|
||||||
</select>
|
|
||||||
</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 DAO
|
|
||||||
</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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -127,48 +127,10 @@ export default async function DashboardPage() {
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-8">
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Data Collection Features</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div className="grid gap-6 md:grid-cols-3">
|
|
||||||
<div className="bg-white rounded-lg shadow-sm p-6 border">
|
|
||||||
<h3 className="text-lg font-semibold mb-1">NFT Holders</h3>
|
|
||||||
<p className="text-sm text-gray-500 mb-3">Track holders of specific NFT collections</p>
|
|
||||||
<p className="text-sm mb-4">Automatically collect Ethereum addresses of NFT holders and resolve their ENS names.</p>
|
|
||||||
<Link href="/nft-holders">
|
|
||||||
<Button variant="secondary" className="w-full">View NFT Data</Button>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-white rounded-lg shadow-sm p-6 border">
|
|
||||||
<h3 className="text-lg font-semibold mb-1">Token Holders</h3>
|
|
||||||
<p className="text-sm text-gray-500 mb-3">Track holders of ERC20 tokens</p>
|
|
||||||
<p className="text-sm mb-4">Collect data on ERC20 token holders, including balance information and transaction history.</p>
|
|
||||||
<Link href="/token-holders">
|
|
||||||
<Button variant="secondary" className="w-full">View Token Data</Button>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-white rounded-lg shadow-sm p-6 border">
|
|
||||||
<h3 className="text-lg font-semibold mb-1">DAO Members</h3>
|
|
||||||
<p className="text-sm text-gray-500 mb-3">Track members of Moloch DAOs</p>
|
|
||||||
<p className="text-sm mb-4">Collect information on members of Moloch DAOs such as Raid Guild, DAOhaus, and Metacartel.</p>
|
|
||||||
<Link href="/dao-members">
|
|
||||||
<Button variant="secondary" className="w-full">View DAO Data</Button>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
</main>
|
</main>
|
||||||
<footer className="w-full border-t py-6">
|
<footer className="w-full border-t py-6">
|
||||||
<div className="container flex flex-col items-center justify-between gap-4 md:flex-row">
|
<div className="container flex justify-center items-center">
|
||||||
<p className="text-center text-sm leading-loose text-muted-foreground md:text-left">
|
<p className="text-center text-sm leading-loose text-muted-foreground">
|
||||||
© 2025 BoilerHaus. All rights reserved.
|
© 2025 BoilerHaus. All rights reserved.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,186 +0,0 @@
|
||||||
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: "NFT Holders - Stones Database",
|
|
||||||
description: "Track holders of specific NFT collections",
|
|
||||||
};
|
|
||||||
|
|
||||||
export default async function NFTHoldersPage() {
|
|
||||||
const user = await getUser();
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
notFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get NFT collection information from the database (this would be replaced with real data)
|
|
||||||
const nftCollections = [
|
|
||||||
{
|
|
||||||
id: "nouns",
|
|
||||||
name: "Nouns",
|
|
||||||
description: "One Noun, every day, forever.",
|
|
||||||
imageUrl: "https://placekitten.com/200/200",
|
|
||||||
holders: 548,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "cryptopunks",
|
|
||||||
name: "CryptoPunks",
|
|
||||||
description: "10,000 unique collectible characters with proof of ownership on Ethereum.",
|
|
||||||
imageUrl: "https://placekitten.com/201/201",
|
|
||||||
holders: 3664,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "bayc",
|
|
||||||
name: "Bored Ape Yacht Club",
|
|
||||||
description: "A collection of 10,000 Bored Ape NFTs on Ethereum.",
|
|
||||||
imageUrl: "https://placekitten.com/202/202",
|
|
||||||
holders: 6425,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
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">NFT Holders</h1>
|
|
||||||
<p className="text-gray-500 mt-1">Track holders of specific NFT collections</p>
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-2">
|
|
||||||
<Button variant="outline">
|
|
||||||
Add New Collection
|
|
||||||
</Button>
|
|
||||||
<Button>
|
|
||||||
Sync Holders
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-6">
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Search NFT Collections</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div className="flex gap-4">
|
|
||||||
<Input placeholder="Search by collection name or contract address" className="max-w-xl" />
|
|
||||||
<Button>Search</Button>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid gap-6 md:grid-cols-3">
|
|
||||||
{nftCollections.map((collection) => (
|
|
||||||
<Card key={collection.id}>
|
|
||||||
<div className="p-2">
|
|
||||||
<img
|
|
||||||
src={collection.imageUrl}
|
|
||||||
alt={collection.name}
|
|
||||||
className="w-full h-48 object-cover rounded-md"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<CardHeader className="pb-2">
|
|
||||||
<CardTitle>{collection.name}</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="space-y-4">
|
|
||||||
<p className="text-sm text-gray-500">{collection.description}</p>
|
|
||||||
<div className="flex justify-between items-center">
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{collection.holders} holders
|
|
||||||
</span>
|
|
||||||
<Link href={`/nft-holders/${collection.id}`}>
|
|
||||||
<Button variant="secondary" size="sm">
|
|
||||||
View Holders
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-8">
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Add NFT Collection</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="collection-name" className="text-sm font-medium">
|
|
||||||
Collection Name
|
|
||||||
</label>
|
|
||||||
<Input
|
|
||||||
id="collection-name"
|
|
||||||
placeholder="Enter collection name"
|
|
||||||
/>
|
|
||||||
</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>
|
|
||||||
<div className="flex justify-end">
|
|
||||||
<Button type="submit">
|
|
||||||
Add Collection
|
|
||||||
</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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,209 +0,0 @@
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue