Files
Pay2Gateway/app/merchant/[id]/(dashboard)/payouts/page.tsx

182 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React from 'react';
import { db } from '@/lib/db';
import {
Wallet,
ExternalLink,
Clock,
ArrowUpRight,
Search
} from 'lucide-react';
import { format } from 'date-fns';
import { tr } from 'date-fns/locale';
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';
import Link from 'next/link';
async function getMerchantPayouts(identifier: string) {
const isUUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(identifier);
let resolvedId = identifier;
if (!isUUID) {
const result = await db.query('SELECT id FROM merchants WHERE short_id = $1 LIMIT 1', [identifier]);
const merchant = result.rows[0];
if (merchant) {
resolvedId = merchant.id;
}
}
try {
const { rows } = await db.query(`
SELECT * FROM payouts
WHERE merchant_id = $1
ORDER BY created_at DESC
`, [resolvedId]);
return { payouts: rows, merchantId: resolvedId };
} catch (error) {
console.error('Merchant payout history fetch error:', error);
return { payouts: [], merchantId: resolvedId };
}
}
export default async function MerchantPayoutsPage(props: {
params: Promise<{ id: string }>;
}) {
const resolvedParams = await props.params;
const identifier = resolvedParams.id;
const { payouts, merchantId } = await getMerchantPayouts(identifier);
const cookieStore = await cookies();
if (!cookieStore.get(`merchant_auth_${merchantId}`)) {
redirect(`/merchant/${identifier}/login`);
}
return (
<div className="space-y-10 animate-in fade-in slide-in-from-bottom-4 duration-700 pb-20 text-sans tracking-tight">
{/* Header Area */}
<div className="bg-white p-10 rounded-[40px] border border-gray-100 shadow-sm flex flex-col md:flex-row md:items-center justify-between gap-8">
<div className="flex items-center gap-6">
<div className="w-16 h-16 bg-blue-600 rounded-[24px] flex items-center justify-center text-white shadow-lg shadow-blue-100">
<Wallet size={28} />
</div>
<div>
<h1 className="text-3xl font-black text-gray-900 tracking-tight">Ödemelerim</h1>
<p className="text-[10px] text-gray-400 font-black uppercase tracking-widest mt-1">Sistemden cüzdanınıza yapılan transfer geçmişi</p>
</div>
</div>
</div>
{/* Stats Overview */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
<div className="bg-white p-8 rounded-[40px] border border-gray-100 shadow-sm flex items-center gap-6">
<div className="w-14 h-14 bg-emerald-50 rounded-2xl flex items-center justify-center text-emerald-600">
<ArrowUpRight size={24} />
</div>
<div>
<p className="text-[10px] font-black text-gray-400 uppercase tracking-widest pl-1">Toplam Çekim</p>
<p className="text-2xl font-black text-gray-900">{payouts.length}</p>
</div>
</div>
<div className="bg-white p-8 rounded-[40px] border border-gray-100 shadow-sm flex items-center gap-6">
<div className="w-14 h-14 bg-blue-50 rounded-2xl flex items-center justify-center text-blue-600">
<Clock size={24} />
</div>
<div>
<p className="text-[10px] font-black text-gray-400 uppercase tracking-widest pl-1">Son Çekim</p>
<p className="text-2xl font-black text-gray-900">
{payouts.length > 0 ? format(new Date(payouts[0].created_at), 'dd MMM', { locale: tr }) : '-'}
</p>
</div>
</div>
<div className="bg-white p-8 rounded-[40px] border border-gray-100 shadow-sm flex items-center gap-6">
<div className="w-14 h-14 bg-orange-50 rounded-2xl flex items-center justify-center text-orange-600">
<Wallet size={24} />
</div>
<div>
<p className="text-[10px] font-black text-gray-400 uppercase tracking-widest pl-1">Durum</p>
<p className="text-2xl font-black text-gray-900 uppercase">Aktif</p>
</div>
</div>
</div>
{/* Payouts Table */}
<div className="bg-white rounded-[40px] border border-gray-100 shadow-sm overflow-hidden overflow-x-auto">
<table className="w-full text-left">
<thead>
<tr className="bg-gray-50/50 text-gray-400 text-[10px] font-black uppercase tracking-[0.2em] border-b border-gray-50">
<th className="px-10 py-6">Miktar & Varlık</th>
<th className="px-10 py-6"> (Network)</th>
<th className="px-10 py-6">Hedef Adres</th>
<th className="px-10 py-6">Tarih</th>
<th className="px-10 py-6 text-center">Durum</th>
<th className="px-10 py-6 text-right">Blockchain</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-50">
{payouts.map((p: any) => (
<tr key={p.id} className="group hover:bg-gray-50/50 transition-colors">
<td className="px-10 py-8">
<div className="flex items-center gap-2">
<span className="text-lg font-black text-gray-900">{Number(p.amount).toFixed(4)}</span>
<span className="text-xs text-gray-400 font-bold uppercase">{p.currency}</span>
</div>
</td>
<td className="px-10 py-8">
<span className={`px-2 py-0.5 rounded-lg text-[10px] font-black uppercase tracking-wider ${
p.network === 'SOLANA' ? 'bg-emerald-50 text-emerald-600' :
p.network === 'TRON' ? 'bg-red-50 text-red-600' :
'bg-blue-50 text-blue-600'
}`}>
{p.network}
</span>
</td>
<td className="px-10 py-8 font-mono text-xs text-gray-500">
<div className="flex items-center gap-1.5 bg-gray-50 px-3 py-1.5 rounded-xl w-fit">
{p.destination_address.slice(0, 6)}...{p.destination_address.slice(-6)}
</div>
</td>
<td className="px-10 py-8 text-xs font-bold text-gray-500 uppercase">
{format(new Date(p.created_at), 'dd MMM yyyy, HH:mm', { locale: tr })}
</td>
<td className="px-10 py-8 text-center">
<span className={`inline-flex items-center px-4 py-1 rounded-full text-[10px] font-black uppercase tracking-widest ${p.status === 'succeeded' ? 'bg-emerald-50 text-emerald-600' : 'bg-red-50 text-red-600'}`}>
{p.status === 'succeeded' ? 'Başarılı' : 'Hatalı'}
</span>
</td>
<td className="px-10 py-8 text-right">
{p.tx_hash && p.tx_hash !== 'mock' ? (
<a
href={p.network === 'SOLANA' ? `https://explorer.solana.com/tx/${p.tx_hash}` :
p.network === 'TRON' ? `https://tronscan.org/#/transaction/${p.tx_hash}` :
`https://polygonscan.com/tx/${p.tx_hash}`}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 text-blue-600 hover:text-blue-800 font-black text-[10px] uppercase tracking-widest transition-all p-2 bg-blue-50 rounded-xl"
>
GÖRÜNTÜLE
<ExternalLink size={14} />
</a>
) : (
<span className="text-[10px] font-black text-gray-300 uppercase italic">Kayıt Yok</span>
)}
</td>
</tr>
))}
</tbody>
</table>
{payouts.length === 0 && (
<div className="p-20 text-center space-y-6">
<div className="w-20 h-20 bg-gray-50 rounded-[32px] flex items-center justify-center mx-auto text-gray-200">
<Wallet size={40} />
</div>
<div className="space-y-2">
<p className="text-gray-900 font-black uppercase tracking-tight text-lg">Henüz Ödeme Yapılmadı</p>
<p className="text-gray-400 font-bold uppercase tracking-widest text-[10px] max-w-xs mx-auto">Sistemimizden cüzdanınıza henüz bir kripto transferi gerçekleşmedi.</p>
</div>
</div>
)}
</div>
</div>
);
}