feat: enhance merchant panel with balance breakdown, payout history, and security improvements
This commit is contained in:
@@ -8,7 +8,8 @@ import {
|
||||
CheckCircle2,
|
||||
Calendar,
|
||||
ArrowUpRight,
|
||||
Search
|
||||
Search,
|
||||
ShieldCheck
|
||||
} from 'lucide-react';
|
||||
import { format } from 'date-fns';
|
||||
import { tr } from 'date-fns/locale';
|
||||
@@ -65,6 +66,17 @@ async function getMerchantData(identifier: string) {
|
||||
}
|
||||
});
|
||||
|
||||
// Fetch merchant balances
|
||||
const bResult = await db.query(
|
||||
'SELECT network, token, balance, withdrawn FROM merchant_balances WHERE merchant_id = $1',
|
||||
[id]
|
||||
);
|
||||
const balances = bResult.rows.map(r => ({
|
||||
network: r.network,
|
||||
token: r.token,
|
||||
amount: parseFloat(r.balance) - parseFloat(r.withdrawn)
|
||||
}));
|
||||
|
||||
return {
|
||||
merchant,
|
||||
transactions,
|
||||
@@ -72,7 +84,8 @@ async function getMerchantData(identifier: string) {
|
||||
successfulCount,
|
||||
successRate,
|
||||
totalCount,
|
||||
chartData
|
||||
chartData,
|
||||
balances
|
||||
};
|
||||
}
|
||||
|
||||
@@ -105,7 +118,7 @@ export default async function MerchantDashboardPage(props: {
|
||||
redirect(`/merchant/${identifier}/login`);
|
||||
}
|
||||
|
||||
const { merchant, transactions, totalRevenue, successfulCount, successRate, totalCount, chartData } = data;
|
||||
const { merchant, transactions, totalRevenue, successfulCount, successRate, totalCount, chartData, balances } = data;
|
||||
const recentTransactions = transactions.slice(0, 8);
|
||||
|
||||
return (
|
||||
@@ -118,7 +131,12 @@ export default async function MerchantDashboardPage(props: {
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-3xl font-black text-gray-900 tracking-tight">{merchant.name}</h1>
|
||||
<p className="text-[10px] text-gray-400 font-black uppercase tracking-widest mt-1">Hoş Geldiniz, İşlemlerinizi Buradan Takip Edebilirsiniz</p>
|
||||
<div className="flex items-center gap-3 mt-1">
|
||||
<p className="text-[10px] text-gray-400 font-black uppercase tracking-widest">Firma Yönetim Paneli</p>
|
||||
<span className="px-2 py-0.5 bg-emerald-50 text-emerald-600 text-[9px] font-black rounded-lg border border-emerald-100 uppercase tracking-tight">
|
||||
Komisyon: %{merchant.fee_percent || '1.0'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
@@ -132,34 +150,80 @@ export default async function MerchantDashboardPage(props: {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* On-chain Vault Section */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div className="bg-white p-8 rounded-[40px] border border-gray-100 shadow-sm flex items-center gap-6 group hover:border-blue-500 transition-all">
|
||||
<div className="w-16 h-16 bg-blue-50 rounded-2xl flex items-center justify-center text-blue-600 shrink-0 group-hover:bg-blue-600 group-hover:text-white transition-colors">
|
||||
<Wallet size={24} />
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="text-[10px] font-black text-gray-400 uppercase tracking-widest mb-1">EVM Kasanız (Polygon/BSC/ETH)</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-mono font-bold text-gray-900 truncate">
|
||||
{merchant.evm_vault_address || 'Henüz Oluşturulmadı'}
|
||||
</span>
|
||||
<div className="px-2 py-0.5 bg-gray-100 rounded text-[9px] font-black text-gray-400 uppercase tracking-tighter">Copy</div>
|
||||
{/* Balances & Vaults Section */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
{/* Crypto Balances */}
|
||||
<div className="lg:col-span-1 bg-gray-900 rounded-[40px] p-8 shadow-2xl relative overflow-hidden flex flex-col justify-between">
|
||||
<div className="relative z-10">
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="w-10 h-10 bg-white/10 rounded-xl flex items-center justify-center text-emerald-400">
|
||||
<Wallet size={20} />
|
||||
</div>
|
||||
<h3 className="text-lg font-black text-white uppercase tracking-tight">Mevcut Bakiyeleriniz</h3>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
{balances && balances.length > 0 ? balances.map((b: any, i: number) => (
|
||||
<div key={i} className="flex items-center justify-between p-4 bg-white/5 rounded-2xl border border-white/5 group hover:bg-white/10 transition-colors">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={`w-2 h-2 rounded-full ${b.network === 'SOLANA' ? 'bg-emerald-400' : b.network === 'POLYGON' ? 'bg-purple-400' : b.network === 'TRON' ? 'bg-red-400' : 'bg-orange-400'}`}></div>
|
||||
<div>
|
||||
<p className="text-[9px] font-black text-white/40 uppercase tracking-widest">{b.network}</p>
|
||||
<p className="text-sm font-black text-white uppercase">{b.token}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className="text-lg font-black text-white tabular-nums">{b.amount.toFixed(4)}</p>
|
||||
<p className="text-[9px] font-black text-emerald-400 uppercase tracking-tighter">Çekilebilir</p>
|
||||
</div>
|
||||
</div>
|
||||
)) : (
|
||||
<div className="py-10 text-center">
|
||||
<p className="text-xs font-bold text-white/20 uppercase tracking-widest">Henüz birikmiş bakiye yok</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 pt-6 border-t border-white/10 relative z-10">
|
||||
<p className="text-[11px] font-black text-gray-500 uppercase tracking-widest mb-2">Dönüşüm Özeti</p>
|
||||
<h4 className="text-3xl font-black text-emerald-400">
|
||||
{totalRevenue.toLocaleString('tr-TR', { minimumFractionDigits: 2 })} <span className="text-base">₺</span>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-8 rounded-[40px] border border-gray-100 shadow-sm flex items-center gap-6 group hover:border-purple-500 transition-all">
|
||||
<div className="w-16 h-16 bg-purple-50 rounded-2xl flex items-center justify-center text-purple-600 shrink-0 group-hover:bg-purple-600 group-hover:text-white transition-colors">
|
||||
<Wallet size={24} />
|
||||
{/* Vault Addresses */}
|
||||
<div className="lg:col-span-2 grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div className="bg-white p-10 rounded-[40px] border border-gray-100 shadow-sm flex flex-col justify-between group hover:border-blue-500 transition-all">
|
||||
<div>
|
||||
<div className="w-16 h-16 bg-blue-50 rounded-2xl flex items-center justify-center text-blue-600 mb-6 group-hover:bg-blue-600 group-hover:text-white transition-colors">
|
||||
<ShieldCheck size={28} />
|
||||
</div>
|
||||
<h3 className="text-xl font-black text-gray-900 mb-2">EVM Kasanız</h3>
|
||||
<p className="text-xs text-gray-400 font-bold uppercase tracking-widest mb-6">Polygon / BSC / Ethereum Ödemeleri İçin</p>
|
||||
</div>
|
||||
<div className="p-4 bg-gray-50 rounded-2xl border border-gray-100">
|
||||
<p className="text-[9px] font-black text-gray-400 uppercase tracking-widest mb-2">Adres</p>
|
||||
<p className="font-mono text-xs font-bold text-gray-900 break-all leading-relaxed">
|
||||
{merchant.evm_vault_address || 'Henüz Oluşturulmadı'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="text-[10px] font-black text-gray-400 uppercase tracking-widest mb-1">Solana Kasanız</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-mono font-bold text-gray-900 truncate">
|
||||
{merchant.sol_vault_address || 'Henüz Oluşturulmadı'}
|
||||
</span>
|
||||
<div className="px-2 py-0.5 bg-gray-100 rounded text-[9px] font-black text-gray-400 uppercase tracking-tighter">Copy</div>
|
||||
|
||||
<div className="bg-white p-10 rounded-[40px] border border-gray-100 shadow-sm flex flex-col justify-between group hover:border-emerald-500 transition-all">
|
||||
<div>
|
||||
<div className="w-16 h-16 bg-emerald-50 rounded-2xl flex items-center justify-center text-emerald-600 mb-6 group-hover:bg-emerald-600 group-hover:text-white transition-colors">
|
||||
<ShieldCheck size={28} />
|
||||
</div>
|
||||
<h3 className="text-xl font-black text-gray-900 mb-2">Solana Kasanız</h3>
|
||||
<p className="text-xs text-gray-400 font-bold uppercase tracking-widest mb-6">Solana / SPL Token Ödemeleri İçin</p>
|
||||
</div>
|
||||
<div className="p-4 bg-gray-50 rounded-2xl border border-gray-100">
|
||||
<p className="text-[9px] font-black text-gray-400 uppercase tracking-widest mb-2">Adres</p>
|
||||
<p className="font-mono text-xs font-bold text-gray-900 break-all leading-relaxed">
|
||||
{merchant.sol_vault_address || 'Henüz Oluşturulmadı'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user