feat: enhance merchant panel with balance breakdown, payout history, and security improvements

This commit is contained in:
mstfyldz
2026-03-13 05:22:24 +03:00
parent 641498957c
commit d7bd2afc29
5 changed files with 382 additions and 62 deletions

View File

@@ -13,6 +13,7 @@ import {
} from 'lucide-react';
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';
import ApiKeyVisibilityToggle from '@/components/merchant/ApiKeyVisibilityToggle';
async function getMerchant(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);
@@ -116,54 +117,82 @@ export default async function MerchantIntegrationPage(props: {
<div className="grid grid-cols-1 md:grid-cols-2 gap-10">
<div className="space-y-4">
<label className="text-[10px] font-black text-gray-400 uppercase tracking-widest ml-2">Merchant ID</label>
<label className="text-[10px] font-black text-gray-400 uppercase tracking-widest ml-2">Public Merchant ID</label>
<div className="bg-gray-50 p-5 rounded-2xl border border-gray-100 flex items-center justify-between">
<code className="text-xs font-mono font-bold text-gray-600">{merchant.id}</code>
<Copy size={16} className="text-gray-300 cursor-pointer hover:text-blue-600 transition" />
<code className="text-xs font-mono font-bold text-gray-600 truncate">{merchant.id}</code>
</div>
</div>
<div className="space-y-4">
<label className="text-[10px] font-black text-gray-400 uppercase tracking-widest ml-2">API Secret Key</label>
<div className="bg-gray-50 p-5 rounded-2xl border border-gray-100 flex items-center justify-between">
<code className="text-xs font-mono font-bold text-gray-600">
{merchant.api_key.substring(0, 8)}
</code>
<button className="text-[10px] font-black text-blue-600 uppercase tracking-widest hover:underline">Anahtarı Göster</button>
</div>
<label className="text-[10px] font-black text-gray-400 uppercase tracking-widest ml-2">Secure API Secret Key</label>
<ApiKeyVisibilityToggle apiKey={merchant.api_key} />
</div>
</div>
</div>
{/* Webhook Settings */}
<div className="bg-white p-12 rounded-[48px] border border-gray-100 shadow-sm space-y-12">
<div className="flex items-center gap-6">
<div className="w-14 h-14 bg-purple-50 rounded-2xl flex items-center justify-center text-purple-600">
<Webhook size={28} />
{/* Webhook & Payout Addresses */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-10">
{/* Webhook Settings */}
<div className="bg-white p-12 rounded-[48px] border border-gray-100 shadow-sm space-y-12">
<div className="flex items-center gap-6">
<div className="w-14 h-14 bg-purple-50 rounded-2xl flex items-center justify-center text-purple-600">
<Webhook size={28} />
</div>
<div>
<h3 className="text-2xl font-black text-gray-900">Webhooks</h3>
<p className="text-xs text-gray-400 font-bold uppercase tracking-widest mt-1">Anlık Bildirimler</p>
</div>
</div>
<div>
<h3 className="text-2xl font-black text-gray-900">Olay Bildirimleri (Webhooks)</h3>
<p className="text-xs text-gray-400 font-bold uppercase tracking-widest mt-1">Ödeme sonuçlarını anlık olarak sunucunuzda karşılayın</p>
<div className="space-y-8">
<div className="p-8 bg-gray-50 rounded-[32px] border border-gray-100 space-y-6">
<div className="flex items-center justify-between">
<span className="text-[11px] font-black text-gray-400 uppercase tracking-widest ml-2">URL</span>
<span className={`text-[10px] font-black px-3 py-1 rounded-full ${merchant.webhook_url ? 'bg-emerald-100 text-emerald-700' : 'bg-red-100 text-red-700'}`}>
{merchant.webhook_url ? 'AKTİF' : 'TANIMSZ'}
</span>
</div>
<div className="bg-white p-6 rounded-2xl border border-gray-200">
<code className="text-sm font-bold text-gray-700 break-all">
{merchant.webhook_url || 'https://siteniz.com/callback'}
</code>
</div>
</div>
</div>
</div>
<div className="space-y-8">
<p className="text-gray-500 font-medium leading-relaxed max-w-2xl">
İşlem tamamlandığında sistemimiz belirttiğiniz URL'ye <code className="bg-gray-100 px-2 py-1 rounded text-blue-600 font-bold">POST</code> isteği gönderir. Bu isteğin içerisinde işlemin tüm detayları yer alır.
</p>
{/* Payout Addresses */}
<div className="bg-white p-12 rounded-[48px] border border-gray-100 shadow-sm space-y-12">
<div className="flex items-center gap-6">
<div className="w-14 h-14 bg-emerald-50 rounded-2xl flex items-center justify-center text-emerald-600">
<Zap size={28} />
</div>
<div>
<h3 className="text-2xl font-black text-gray-900">Hak Ediş Adresleriniz</h3>
<p className="text-xs text-gray-400 font-bold uppercase tracking-widest mt-1">Ödemeleriniz bu adreslere iletilir</p>
</div>
</div>
<div className="p-8 bg-gray-50 rounded-[32px] border border-gray-100 space-y-6">
<div className="flex items-center justify-between">
<span className="text-[11px] font-black text-gray-400 uppercase tracking-widest ml-2">Webhook URL</span>
<span className={`text-[10px] font-black px-3 py-1 rounded-full ${merchant.webhook_url ? 'bg-emerald-100 text-emerald-700' : 'bg-red-100 text-red-700'}`}>
{merchant.webhook_url ? 'HİZMETE HAZIR' : 'HENÜZ TANIMLANMAMIŞ'}
</span>
</div>
<div className="bg-white p-6 rounded-2xl border border-gray-200">
<code className="text-sm font-bold text-gray-700 break-all">
{merchant.webhook_url || 'https://siteniz.com/api/payment-callback'}
</code>
</div>
<div className="space-y-4">
{['EVM', 'SOLANA', 'TRON', 'BITCOIN'].map((net) => {
const addr = merchant.payout_addresses?.[net] || (net === 'EVM' ? merchant.payout_address : null);
return (
<div key={net} className="flex items-center justify-between p-4 bg-gray-50 rounded-2xl border border-gray-100 group">
<div className="flex items-center gap-3">
<div className={`w-8 h-8 rounded-xl flex items-center justify-center text-white text-[10px] font-black ${net === 'SOLANA' ? 'bg-emerald-500' : net === 'POLYGON' ? 'bg-purple-500' : net === 'TRON' ? 'bg-red-500' : 'bg-orange-500'}`}>
{net.slice(0, 1)}
</div>
<div>
<p className="text-[9px] font-black text-gray-400 uppercase tracking-[0.2em]">{net}</p>
<p className="text-[11px] font-mono font-bold text-gray-900 truncate max-w-[180px] lg:max-w-[250px]">
{addr || 'TANIMLANMAMIŞ'}
</p>
</div>
</div>
{addr && <Copy size={14} className="text-gray-300 cursor-pointer hover:text-blue-600 transition" />}
</div>
);
})}
</div>
</div>
</div>