forked from maik/IPFS-portal
109 lines
4.4 KiB
TypeScript
109 lines
4.4 KiB
TypeScript
|
|
'use client';
|
||
|
|
|
||
|
|
import type { TokenInfo } from '@/lib/payment';
|
||
|
|
import { formatWeiToETH } from '@/lib/wallet';
|
||
|
|
|
||
|
|
/* ── Props ── */
|
||
|
|
interface OverviewProps {
|
||
|
|
totalUploads: bigint;
|
||
|
|
tokens: TokenInfo[];
|
||
|
|
revenues: Record<string, bigint>;
|
||
|
|
contractBalance: Record<string, string>;
|
||
|
|
contractAddress: string;
|
||
|
|
owner: string | null;
|
||
|
|
isOwner: boolean;
|
||
|
|
address: string | null;
|
||
|
|
deployed: boolean;
|
||
|
|
onNavigate: (view: string) => void;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ════════════════════════════ Component ════════════════════════════ */
|
||
|
|
|
||
|
|
export default function Overview({
|
||
|
|
totalUploads, tokens, revenues, contractBalance,
|
||
|
|
contractAddress, owner, isOwner, address, deployed, onNavigate,
|
||
|
|
}: OverviewProps) {
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="space-y-6">
|
||
|
|
{/* Stats grid */}
|
||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
||
|
|
<div className="glass rounded-xl p-4">
|
||
|
|
<div className="text-xs text-surface-400 mb-1">Total Uploads</div>
|
||
|
|
<div className="text-2xl font-bold text-white">{totalUploads.toString()}</div>
|
||
|
|
</div>
|
||
|
|
{tokens.filter(t => t.enabled).map(tk => {
|
||
|
|
const rev = revenues[tk.symbol] || BigInt(0);
|
||
|
|
const bal = contractBalance[tk.symbol];
|
||
|
|
return (
|
||
|
|
<div key={tk.symbol} className="glass rounded-xl p-4">
|
||
|
|
<div className="text-xs text-surface-400 mb-1">{tk.symbol} Revenue</div>
|
||
|
|
<div className="text-2xl font-bold text-white">
|
||
|
|
{tk.symbol === 'ETH' ? formatWeiToETH(rev, 6) : rev.toString()}
|
||
|
|
</div>
|
||
|
|
{bal && (
|
||
|
|
<div className="text-[10px] text-surface-500 mt-1">
|
||
|
|
Balance: {tk.symbol === 'ETH' ? formatWeiToETH(bal, 6) : bal} {tk.symbol}
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
})}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Contract info */}
|
||
|
|
<div className="glass rounded-xl p-5 space-y-3">
|
||
|
|
<h3 className="text-sm font-semibold text-white">Contract</h3>
|
||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs">
|
||
|
|
<div className="flex justify-between py-1.5 px-3 rounded bg-surface-800/30">
|
||
|
|
<span className="text-surface-400">Address</span>
|
||
|
|
<span className="font-mono text-surface-200">
|
||
|
|
{contractAddress.slice(0, 10)}...
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
<div className="flex justify-between py-1.5 px-3 rounded bg-surface-800/30">
|
||
|
|
<span className="text-surface-400">Owner</span>
|
||
|
|
<span className="font-mono text-surface-200">
|
||
|
|
{owner ? `${owner.slice(0, 8)}...${owner.slice(-6)}` : '-'}
|
||
|
|
{isOwner && <span className="ml-1 text-accent-green">✓</span>}
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
<div className="flex justify-between py-1.5 px-3 rounded bg-surface-800/30">
|
||
|
|
<span className="text-surface-400">Deployed</span>
|
||
|
|
<span className={deployed ? 'text-accent-green' : 'text-accent-rose'}>
|
||
|
|
{deployed ? 'Yes' : 'No'}
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
<div className="flex justify-between py-1.5 px-3 rounded bg-surface-800/30">
|
||
|
|
<span className="text-surface-400">Connected</span>
|
||
|
|
<span className="text-surface-200 font-mono">
|
||
|
|
{address ? `${address.slice(0, 6)}...${address.slice(-4)}` : '-'}
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* If owner — quick actions */}
|
||
|
|
{isOwner && (
|
||
|
|
<div className="glass rounded-xl p-5 space-y-3">
|
||
|
|
<h3 className="text-sm font-semibold text-white">Quick Actions</h3>
|
||
|
|
<div className="flex flex-wrap gap-2">
|
||
|
|
<button onClick={() => onNavigate('pricing')}
|
||
|
|
className="px-3 py-1.5 rounded-lg bg-surface-800 hover:bg-surface-700 text-surface-300 text-xs transition-colors">
|
||
|
|
Update Pricing
|
||
|
|
</button>
|
||
|
|
<button onClick={() => onNavigate('tokens')}
|
||
|
|
className="px-3 py-1.5 rounded-lg bg-surface-800 hover:bg-surface-700 text-surface-300 text-xs transition-colors">
|
||
|
|
Manage Tokens
|
||
|
|
</button>
|
||
|
|
<button onClick={() => onNavigate('tiers')}
|
||
|
|
className="px-3 py-1.5 rounded-lg bg-surface-800 hover:bg-surface-700 text-surface-300 text-xs transition-colors">
|
||
|
|
Discount Tiers
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|