Files
solace-bg-dubai/frontend/app/activity/page.tsx
defiQUG c94eb595f8
Some checks failed
CI / lint-and-test (push) Has been cancelled
Initial commit: add .gitignore and README
2026-02-09 21:51:53 -08:00

142 lines
4.8 KiB
TypeScript

"use client";
import { useState } from "react";
import { useAccount } from "wagmi";
import { WalletConnect } from "@/components/web3/WalletConnect";
import { formatAddress } from "@/lib/utils";
import { format } from "date-fns";
import { formatEther } from "viem";
interface Transaction {
id: string;
proposalId: number;
to: string;
value: string;
status: "pending" | "executed" | "rejected";
createdAt: Date | string;
}
export default function ActivityPage() {
const { isConnected } = useAccount();
const [filter, setFilter] = useState<"all" | "pending" | "executed">("all");
// TODO: Fetch transactions from backend
const transactions: Transaction[] = [];
if (!isConnected) {
return (
<div className="min-h-screen p-8">
<div className="max-w-6xl mx-auto">
<WalletConnect />
</div>
</div>
);
}
const filteredTransactions = transactions.filter((tx) => {
if (filter === "all") return true;
return tx.status === filter;
});
const handleExport = async () => {
// TODO: Fetch CSV from backend API
const csv = ""; // Placeholder
const blob = new Blob([csv], { type: "text/csv" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `transactions-${Date.now()}.csv`;
a.click();
URL.revokeObjectURL(url);
};
return (
<div className="min-h-screen p-8">
<div className="max-w-6xl mx-auto">
<header className="flex justify-between items-center mb-8">
<h1 className="text-3xl font-bold">Transaction History</h1>
<div className="flex gap-4 items-center">
<WalletConnect />
<button
onClick={handleExport}
className="px-4 py-2 bg-green-600 hover:bg-green-700 rounded-lg transition-colors"
>
Export CSV
</button>
</div>
</header>
<div className="bg-gray-900 rounded-xl p-6">
{/* Filters */}
<div className="flex gap-4 mb-6">
{(["all", "pending", "executed"] as const).map((status) => (
<button
key={status}
onClick={() => setFilter(status)}
className={`px-4 py-2 rounded-lg transition-colors ${
filter === status
? "bg-blue-600 text-white"
: "bg-gray-800 text-gray-300 hover:bg-gray-700"
}`}
>
{status.charAt(0).toUpperCase() + status.slice(1)}
</button>
))}
</div>
{/* Transaction List */}
{filteredTransactions.length === 0 ? (
<div className="text-center py-12 text-gray-400">
No transactions found
</div>
) : (
<div className="space-y-4">
{filteredTransactions.map((tx) => (
<div
key={tx.id}
className="bg-gray-800 rounded-lg p-6 border border-gray-700"
>
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<div>
<div className="text-sm text-gray-400 mb-1">Proposal ID</div>
<div className="font-mono">#{tx.proposalId}</div>
</div>
<div>
<div className="text-sm text-gray-400 mb-1">To</div>
<div className="font-mono text-sm">{formatAddress(tx.to)}</div>
</div>
<div>
<div className="text-sm text-gray-400 mb-1">Amount</div>
<div className="font-semibold">{formatEther(BigInt(tx.value))} ETH</div>
</div>
<div>
<div className="text-sm text-gray-400 mb-1">Status</div>
<span
className={`inline-block px-3 py-1 rounded text-sm font-semibold ${
tx.status === "executed"
? "bg-green-900/30 text-green-400"
: tx.status === "pending"
? "bg-yellow-900/30 text-yellow-400"
: "bg-red-900/30 text-red-400"
}`}
>
{tx.status}
</span>
</div>
</div>
<div className="mt-4 pt-4 border-t border-gray-700">
<div className="text-sm text-gray-400">
Created: {format(new Date(tx.createdAt), "MMM dd, yyyy HH:mm:ss")}
</div>
</div>
</div>
))}
</div>
)}
</div>
</div>
</div>
);
}