Files
Pay2Gateway/app/admin/settings/page.tsx

189 lines
9.8 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.
'use client';
import React, { useState, useEffect } from 'react';
import {
Zap,
ShieldCheck,
Save,
RefreshCcw,
Wallet,
Settings,
Server,
Key,
AlertCircle
} from 'lucide-react';
export default function AdminSettingsPage() {
const [settings, setSettings] = useState({
sol_platform_address: '',
evm_platform_address: ''
});
const [isLoading, setIsLoading] = useState(true);
const [isSaving, setIsSaving] = useState(false);
const [message, setMessage] = useState({ type: '', text: '' });
useEffect(() => {
fetchSettings();
}, []);
const fetchSettings = async () => {
setIsLoading(true);
try {
const res = await fetch('/api/admin/settings');
const data = await res.json();
if (data.error) throw new Error(data.error);
setSettings({
sol_platform_address: data.sol_platform_address || '',
evm_platform_address: data.evm_platform_address || ''
});
} catch (err: any) {
setMessage({ type: 'error', text: 'Ayarlar yüklenemedi: ' + err.message });
} finally {
setIsLoading(false);
}
};
const handleSave = async (e: React.FormEvent) => {
e.preventDefault();
setIsSaving(true);
setMessage({ type: '', text: '' });
try {
const res = await fetch('/api/admin/settings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(settings)
});
const data = await res.json();
if (data.error) throw new Error(data.error);
setMessage({ type: 'success', text: 'Ayarlar başarıyla güncellendi.' });
} catch (err: any) {
setMessage({ type: 'error', text: 'Kaydetme hatası: ' + err.message });
} finally {
setIsSaving(false);
}
};
return (
<div className="max-w-4xl mx-auto space-y-10 animate-in fade-in slide-in-from-bottom-4 duration-700">
{/* Header */}
<div className="flex flex-col md:flex-row md:items-center justify-between gap-6">
<div>
<h1 className="text-3xl font-black text-gray-900 tracking-tight italic">Platform Ayarları</h1>
<p className="text-xs text-gray-400 font-bold uppercase tracking-widest mt-2 px-1">Sistem Genel Yapılandırması</p>
</div>
<div className="flex items-center gap-3 px-6 py-2 bg-blue-50 rounded-full border border-blue-100">
<ShieldCheck size={14} className="text-blue-600" />
<span className="text-[10px] font-black text-blue-600 uppercase tracking-widest">Global Kontrol Ünitesi</span>
</div>
</div>
{/* Main Form */}
<form onSubmit={handleSave} className="space-y-8">
{/* Platform Addresses Card */}
<div className="bg-white p-10 rounded-[48px] border border-gray-100 shadow-sm space-y-10">
<div className="flex items-center gap-4">
<div className="w-12 h-12 bg-gray-50 rounded-2xl flex items-center justify-center text-gray-900 group-hover:bg-blue-600 group-hover:text-white transition-all">
<Wallet size={24} />
</div>
<div>
<h3 className="text-xl font-black text-gray-900">Merkezi Cüzdanlar (Platform)</h3>
<p className="text-xs text-gray-400 font-bold uppercase tracking-widest mt-1">Süpürülen tüm fonların toplanacağı ana adresler</p>
</div>
</div>
<div className="grid grid-cols-1 gap-8">
<div className="space-y-3">
<label className="text-[10px] font-black text-gray-400 uppercase tracking-[0.2em] ml-1">Solana Platform Adresi</label>
<div className="relative">
<Server className="absolute left-5 top-1/2 -translate-y-1/2 text-gray-300" size={20} />
<input
type="text"
required
value={settings.sol_platform_address}
onChange={(e) => setSettings({ ...settings, sol_platform_address: e.target.value })}
placeholder="Solana Wallet Address"
className="w-full pl-14 pr-6 py-5 bg-gray-50 border-2 border-transparent focus:border-purple-500 focus:bg-white rounded-[24px] outline-none transition-all font-bold text-gray-900 font-mono text-sm"
/>
</div>
</div>
<div className="space-y-3">
<label className="text-[10px] font-black text-gray-400 uppercase tracking-[0.2em] ml-1">EVM Platform Adresi (Polygon/BSC/ETH)</label>
<div className="relative">
<Server className="absolute left-5 top-1/2 -translate-y-1/2 text-gray-300" size={20} />
<input
type="text"
required
value={settings.evm_platform_address}
onChange={(e) => setSettings({ ...settings, evm_platform_address: e.target.value })}
placeholder="0x..."
className="w-full pl-14 pr-6 py-5 bg-gray-50 border-2 border-transparent focus:border-blue-500 focus:bg-white rounded-[24px] outline-none transition-all font-bold text-gray-900 font-mono text-sm"
/>
</div>
</div>
</div>
<div className="p-6 bg-blue-50 rounded-3xl border border-blue-100 flex gap-4 items-start">
<AlertCircle className="text-blue-600 mt-1 shrink-0" size={20} />
<p className="text-xs text-blue-600 font-medium leading-relaxed">
Bu adresler, merchant'ların yaptığı tahsilatların (komisyonunuz kesildikten sonra kalan kısmın değil, platforma ait ana kesintinin veya tüm fonların) toplanacağı ana havuzunuzdur. Lütfen adreslerin doğruluğunu iki kez kontrol edin.
</p>
</div>
</div>
{/* Info Card: Gas Tank Secrets */}
<div className="bg-gray-900 p-10 rounded-[48px] shadow-2xl space-y-8 relative overflow-hidden group">
<div className="absolute top-0 right-0 p-10 opacity-5 group-hover:scale-110 transition-transform">
<Key size={120} className="text-white" />
</div>
<div className="space-y-4 relative">
<div className="w-12 h-12 bg-white/10 rounded-2xl flex items-center justify-center text-white">
<Zap size={24} />
</div>
<h3 className="text-2xl font-black text-white italic">Kritik Güvenlik: Gas Tank Private Key</h3>
<p className="text-gray-400 font-medium leading-relaxed max-w-2xl">
Süpürme (Sweep) işlemlerinin blokzinciri ücretlerini ödeyen "Gaz Tankı" cüzdanınızın Private Key'i, en yüksek güvenlik için veritabanında değil, sunucu tarafında <strong>Coolify Environment Variables</strong> (`CRYPTO_GAS_TANK_KEY`) olarak saklanmalıdır.
</p>
</div>
<div className="flex gap-4 p-6 bg-white/5 rounded-3xl border border-white/10 items-center">
<div className="w-2 h-2 rounded-full bg-emerald-500"></div>
<span className="text-[10px] font-black text-gray-500 uppercase tracking-widest">Coolify Panelden Yönetildi</span>
</div>
</div>
{/* Status and Action */}
{message.text && (
<div className={`p-6 rounded-[30px] border flex items-center gap-4 animate-in slide-in-from-top-2 duration-300 ${
message.type === 'success' ? 'bg-emerald-50 border-emerald-100 text-emerald-700' : 'bg-red-50 border-red-100 text-red-700'
}`}>
{message.type === 'success' ? <ShieldCheck size={20} /> : <AlertCircle size={20} />}
<span className="text-xs font-black uppercase tracking-widest italic">{message.text}</span>
</div>
)}
<div className="flex justify-end gap-6 pt-4">
<button
type="button"
onClick={fetchSettings}
className="p-5 text-gray-400 hover:text-gray-900 transition-colors"
title="Yenile"
>
<RefreshCcw size={24} />
</button>
<button
type="submit"
disabled={isSaving || isLoading}
className="px-14 py-6 bg-blue-600 text-white rounded-[28px] font-black text-sm uppercase tracking-[0.2em] hover:bg-blue-700 transition shadow-2xl shadow-blue-200 disabled:opacity-50 flex items-center gap-3 italic"
>
{isSaving ? 'Kaydediliyor...' : 'Konfigurasyonu Güncelle'}
<Save size={18} />
</button>
</div>
</form>
</div>
);
}