feat: merchant specific fees, TRON & BTC support, coin logos, and bug fixes
This commit is contained in:
@@ -20,6 +20,7 @@ export default function NewMerchantPage() {
|
||||
const [name, setName] = useState('');
|
||||
const [webhookUrl, setWebhookUrl] = useState('');
|
||||
const [paymentProvider, setPaymentProvider] = useState('stripe');
|
||||
const [feePercent, setFeePercent] = useState('1.0');
|
||||
const [success, setSuccess] = useState(false);
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
@@ -33,7 +34,8 @@ export default function NewMerchantPage() {
|
||||
body: JSON.stringify({
|
||||
name,
|
||||
webhook_url: webhookUrl,
|
||||
payment_provider: paymentProvider
|
||||
payment_provider: paymentProvider,
|
||||
fee_percent: parseFloat(feePercent || '1.0')
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -141,6 +143,27 @@ export default function NewMerchantPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Fee Percentage Input */}
|
||||
<div className="space-y-3">
|
||||
<label className="text-[11px] font-black text-gray-400 uppercase tracking-widest ml-1">Özel Komisyon Oranı (%)</label>
|
||||
<div className="relative group max-w-[240px]">
|
||||
<div className="absolute right-6 top-1/2 -translate-y-1/2 text-gray-400 font-black">%</div>
|
||||
<input
|
||||
type="number"
|
||||
step="0.1"
|
||||
min="0"
|
||||
max="100"
|
||||
value={feePercent}
|
||||
onChange={(e) => setFeePercent(e.target.value)}
|
||||
placeholder="1.0"
|
||||
className="w-full pl-8 pr-12 py-5 bg-gray-50 border-2 border-transparent focus:border-blue-100 focus:bg-white rounded-3xl text-lg font-black text-gray-900 outline-none transition-all placeholder:text-gray-300"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-[11px] text-gray-400 font-medium px-1">
|
||||
Bu firmadan her işlemde kesilecek platform payı. (Varsayılan: %1.0)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Webhook Input */}
|
||||
<div className="space-y-3">
|
||||
<label className="text-[11px] font-black text-gray-400 uppercase tracking-widest ml-1">Geri Dönüş (Webhook) URL</label>
|
||||
|
||||
@@ -63,7 +63,8 @@ export default function MerchantsPage() {
|
||||
name: editingMerchant.name,
|
||||
webhook_url: editingMerchant.webhook_url,
|
||||
payment_provider: editingMerchant.payment_provider,
|
||||
provider_config: editingMerchant.provider_config
|
||||
provider_config: editingMerchant.provider_config,
|
||||
fee_percent: editingMerchant.fee_percent
|
||||
})
|
||||
});
|
||||
if (!response.ok) throw new Error('Güncelleme başarısız.');
|
||||
@@ -136,9 +137,11 @@ export default function MerchantsPage() {
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg font-black text-gray-900">{m.name}</h3>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-[10px] text-blue-600 font-black uppercase tracking-widest">ID: {identifier}</span>
|
||||
{m.short_id && <span className="px-1.5 py-0.5 bg-blue-50 text-blue-600 text-[8px] font-black rounded border border-blue-100 uppercase tracking-tighter transition-all group-hover:bg-blue-600 group-hover:text-white group-hover:border-blue-700">Short Link Active</span>}
|
||||
<div className="flex items-center gap-1.5 px-2 py-0.5 bg-emerald-50 text-emerald-600 text-[9px] font-black rounded-lg border border-emerald-100 uppercase tracking-tight">
|
||||
Fee: %{m.fee_percent || '1.0'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -307,6 +310,24 @@ export default function MerchantsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<label className="text-[10px] font-black text-gray-400 uppercase tracking-[0.2em] ml-1">Özel Komisyon (%)</label>
|
||||
<div className="relative">
|
||||
<div className="absolute right-5 top-1/2 -translate-y-1/2 text-gray-300 font-black text-sm">%</div>
|
||||
<input
|
||||
type="number"
|
||||
step="0.1"
|
||||
min="0"
|
||||
max="100"
|
||||
value={editingMerchant?.fee_percent || '1.0'}
|
||||
onChange={(e) => setEditingMerchant({ ...editingMerchant, fee_percent: e.target.value })}
|
||||
placeholder="1.0"
|
||||
className="w-full pl-6 pr-12 py-4 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 placeholder:text-gray-300"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-[10px] text-gray-400 font-medium px-1">Bu firmaya özel kesinti oranı. Boş bırakılırsa sistem varsayılanı kullanılır.</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<label className="text-[10px] font-black text-gray-400 uppercase tracking-[0.2em] ml-1">Webhook URL (Geri Dönüş)</label>
|
||||
<div className="relative">
|
||||
|
||||
@@ -16,7 +16,8 @@ import {
|
||||
export default function AdminSettingsPage() {
|
||||
const [settings, setSettings] = useState({
|
||||
sol_platform_address: '',
|
||||
evm_platform_address: ''
|
||||
evm_platform_address: '',
|
||||
default_fee_percent: '1.0'
|
||||
});
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
@@ -34,7 +35,8 @@ export default function AdminSettingsPage() {
|
||||
if (data.error) throw new Error(data.error);
|
||||
setSettings({
|
||||
sol_platform_address: data.sol_platform_address || '',
|
||||
evm_platform_address: data.evm_platform_address || ''
|
||||
evm_platform_address: data.evm_platform_address || '',
|
||||
default_fee_percent: data.default_fee_percent || '1.0'
|
||||
});
|
||||
} catch (err: any) {
|
||||
setMessage({ type: 'error', text: 'Ayarlar yüklenemedi: ' + err.message });
|
||||
@@ -65,7 +67,7 @@ export default function AdminSettingsPage() {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto space-y-10 animate-in fade-in slide-in-from-bottom-4 duration-700">
|
||||
<div className="max-w-4xl mx-auto space-y-10 animate-in fade-in slide-in-from-bottom-4 duration-700 pb-20">
|
||||
{/* Header */}
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-6">
|
||||
<div>
|
||||
@@ -80,6 +82,37 @@ export default function AdminSettingsPage() {
|
||||
|
||||
{/* Main Form */}
|
||||
<form onSubmit={handleSave} className="space-y-8">
|
||||
{/* Fee Setting 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-emerald-50 rounded-2xl flex items-center justify-center text-emerald-600">
|
||||
<Zap size={24} />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-black text-gray-900">Komisyon (Fee) Ayarları</h3>
|
||||
<p className="text-xs text-gray-400 font-bold uppercase tracking-widest mt-1">Sistem geneli varsayılan işlem kesintisi</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="max-w-xs space-y-3">
|
||||
<label className="text-[10px] font-black text-gray-400 uppercase tracking-[0.2em] ml-1">Yüzdelik Kesinti (%)</label>
|
||||
<div className="relative">
|
||||
<div className="absolute right-6 top-1/2 -translate-y-1/2 text-gray-400 font-black">%</div>
|
||||
<input
|
||||
type="number"
|
||||
step="0.1"
|
||||
min="0"
|
||||
max="100"
|
||||
required
|
||||
value={settings.default_fee_percent}
|
||||
onChange={(e) => setSettings({ ...settings, default_fee_percent: e.target.value })}
|
||||
className="w-full pl-8 pr-12 py-5 bg-gray-50 border-2 border-transparent focus:border-emerald-500 focus:bg-white rounded-[24px] outline-none transition-all font-black text-gray-900 text-lg"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-[10px] text-gray-400 font-medium px-1">Örn: 1.0 (Yüzde bir), 2.5 (Yüzde iki buçuk)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 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">
|
||||
|
||||
@@ -23,6 +23,7 @@ export async function GET() {
|
||||
// Fill defaults if empty
|
||||
if (!settings.sol_platform_address) settings.sol_platform_address = process.env.SOL_PLATFORM_ADDRESS || '';
|
||||
if (!settings.evm_platform_address) settings.evm_platform_address = process.env.EVM_PLATFORM_ADDRESS || '';
|
||||
if (!settings.default_fee_percent) settings.default_fee_percent = '1.0';
|
||||
|
||||
return NextResponse.json(settings);
|
||||
} catch (err: any) {
|
||||
@@ -33,11 +34,12 @@ export async function GET() {
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
const body = await req.json();
|
||||
const { sol_platform_address, evm_platform_address } = body;
|
||||
const { sol_platform_address, evm_platform_address, default_fee_percent } = body;
|
||||
|
||||
const queries = [
|
||||
{ key: 'sol_platform_address', value: sol_platform_address },
|
||||
{ key: 'evm_platform_address', value: evm_platform_address }
|
||||
{ key: 'evm_platform_address', value: evm_platform_address },
|
||||
{ key: 'default_fee_percent', value: default_fee_percent || '1.0' }
|
||||
];
|
||||
|
||||
for (const q of queries) {
|
||||
|
||||
@@ -74,10 +74,14 @@ export async function POST(req: NextRequest) {
|
||||
// 3. Generate Temporary Wallets for Crypto fallback
|
||||
const evmWallet = await CryptoEngine.createTemporaryWallet('POLYGON');
|
||||
const solWallet = await CryptoEngine.createTemporaryWallet('SOLANA');
|
||||
const tronWallet = await CryptoEngine.createTemporaryWallet('TRON');
|
||||
const btcWallet = await CryptoEngine.createTemporaryWallet('BITCOIN');
|
||||
|
||||
const cryptoWallets = {
|
||||
EVM: { address: evmWallet.address, privateKey: evmWallet.privateKey },
|
||||
SOLANA: { address: solWallet.address, privateKey: solWallet.privateKey }
|
||||
SOLANA: { address: solWallet.address, privateKey: solWallet.privateKey },
|
||||
TRON: { address: tronWallet.address, privateKey: tronWallet.privateKey },
|
||||
BITCOIN: { address: btcWallet.address, privateKey: btcWallet.privateKey }
|
||||
};
|
||||
|
||||
// 4. Log transaction in Supabase
|
||||
@@ -108,7 +112,9 @@ export async function POST(req: NextRequest) {
|
||||
provider,
|
||||
wallets: {
|
||||
EVM: evmWallet.address,
|
||||
SOLANA: solWallet.address
|
||||
SOLANA: solWallet.address,
|
||||
TRON: tronWallet.address,
|
||||
BITCOIN: btcWallet.address
|
||||
}
|
||||
});
|
||||
} catch (err: any) {
|
||||
|
||||
@@ -45,22 +45,27 @@ export async function POST(request: Request) {
|
||||
return NextResponse.json({ success: false, error: `No temporary wallet found for ${walletType}` }, { status: 500 });
|
||||
}
|
||||
|
||||
// 3. Define Platform Address (Fetch from dynamic settings)
|
||||
const platformAddresses = await (async () => {
|
||||
const result = await db.query('SELECT key, value FROM system_settings WHERE key IN (\'sol_platform_address\', \'evm_platform_address\')');
|
||||
// 3. Define Platform Address & Fee (Fetch from dynamic settings)
|
||||
const settings = await (async () => {
|
||||
const result = await db.query('SELECT key, value FROM system_settings WHERE key IN (\'sol_platform_address\', \'evm_platform_address\', \'default_fee_percent\')');
|
||||
const map: Record<string, string> = {};
|
||||
result.rows.forEach(r => map[r.key] = r.value);
|
||||
return {
|
||||
sol: map.sol_platform_address || process.env.SOL_PLATFORM_ADDRESS || "5pLH1tqZhx8p8WpZ18yr28N42KXB3FXVPzZ9ceCtpBVe",
|
||||
evm: map.evm_platform_address || process.env.EVM_PLATFORM_ADDRESS || "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
|
||||
evm: map.evm_platform_address || process.env.EVM_PLATFORM_ADDRESS || "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
|
||||
fee: parseFloat(map.default_fee_percent || '1.0')
|
||||
};
|
||||
})();
|
||||
|
||||
const platformAddress = selectedNetwork === 'SOLANA' ? platformAddresses.sol : platformAddresses.evm;
|
||||
|
||||
const platformAddress = selectedNetwork === 'SOLANA' ? settings.sol : settings.evm;
|
||||
// 4. Define Merchant Address (Fetch from transaction's merchant)
|
||||
const merchantResult = await db.query('SELECT * FROM merchants WHERE id = $1', [transaction.merchant_id]);
|
||||
const merchant = merchantResult.rows[0];
|
||||
|
||||
// Prioritize merchant's specific fee, fallback to global setting
|
||||
const feePercent = merchant?.fee_percent !== undefined && merchant?.fee_percent !== null
|
||||
? parseFloat(merchant.fee_percent)
|
||||
: settings.fee;
|
||||
|
||||
let merchantAddress = merchant?.wallet_address || platformAddress;
|
||||
|
||||
@@ -95,7 +100,8 @@ export async function POST(request: Request) {
|
||||
tempWalletConfig.privateKey,
|
||||
merchantAddress,
|
||||
platformAddress,
|
||||
selectedToken
|
||||
selectedToken,
|
||||
feePercent
|
||||
);
|
||||
|
||||
if (!sweepResult.success) {
|
||||
|
||||
@@ -29,7 +29,7 @@ export async function PATCH(
|
||||
) {
|
||||
try {
|
||||
const { id } = await context.params;
|
||||
const { name, webhook_url, payment_provider, provider_config } = await req.json();
|
||||
const { name, webhook_url, payment_provider, provider_config, fee_percent } = await req.json();
|
||||
|
||||
if (!name) {
|
||||
return NextResponse.json(
|
||||
@@ -39,8 +39,8 @@ export async function PATCH(
|
||||
}
|
||||
|
||||
const result = await db.query(
|
||||
'UPDATE merchants SET name = $1, webhook_url = $2, payment_provider = $3, provider_config = $4 WHERE id = $5 RETURNING *',
|
||||
[name, webhook_url, payment_provider, provider_config, id]
|
||||
'UPDATE merchants SET name = $1, webhook_url = $2, payment_provider = $3, provider_config = $4, fee_percent = $5 WHERE id = $6 RETURNING *',
|
||||
[name, webhook_url, payment_provider, provider_config, fee_percent || 1.0, id]
|
||||
);
|
||||
const data = result.rows[0];
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { db } from '@/lib/db';
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
const { name, webhook_url, payment_provider, provider_config } = await req.json();
|
||||
const { name, webhook_url, payment_provider, provider_config, fee_percent } = await req.json();
|
||||
|
||||
if (!name) {
|
||||
return NextResponse.json(
|
||||
@@ -27,9 +27,9 @@ export async function POST(req: NextRequest) {
|
||||
const configStr = provider_config ? JSON.stringify(provider_config) : '{}';
|
||||
|
||||
const result = await db.query(
|
||||
`INSERT INTO merchants (name, webhook_url, short_id, payment_provider, provider_config)
|
||||
VALUES ($1, $2, $3, $4, $5) RETURNING *`,
|
||||
[name, webhook_url, shortId, provider, configStr]
|
||||
`INSERT INTO merchants (name, webhook_url, short_id, payment_provider, provider_config, fee_percent)
|
||||
VALUES ($1, $2, $3, $4, $5, $6) RETURNING *`,
|
||||
[name, webhook_url, shortId, provider, configStr, fee_percent || 1.0]
|
||||
);
|
||||
|
||||
if (result.rows.length === 0) {
|
||||
|
||||
@@ -85,18 +85,15 @@ export default function MerchantLoginPage() {
|
||||
</div>
|
||||
|
||||
<div className="text-center pt-4 space-y-4">
|
||||
<button
|
||||
onClick={() => router.push('/merchant/register')}
|
||||
className="text-[10px] font-black text-blue-600 underline uppercase tracking-widest hover:text-blue-800 transition block w-full"
|
||||
>
|
||||
Henüz bir hesabınız yok mu? Şimdi Katılın
|
||||
</button>
|
||||
<button
|
||||
onClick={() => router.push('/')}
|
||||
className="text-[10px] font-black text-gray-400 uppercase tracking-widest hover:text-gray-900 transition"
|
||||
>
|
||||
Ana Sayfaya Dön
|
||||
</button>
|
||||
<p className="text-[10px] text-gray-300 font-bold uppercase tracking-widest block w-full">
|
||||
Başvuru için satış ekibiyle iletişime geçin
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -11,158 +11,52 @@ export default function MerchantRegisterPage() {
|
||||
const [success, setSuccess] = useState<any>(null);
|
||||
const router = useRouter();
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setIsLoading(true);
|
||||
setError('');
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/merchants/register', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ name })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
setSuccess(data);
|
||||
} else {
|
||||
setError(data.error || 'Kayıt sırasında bir hata oluştu.');
|
||||
}
|
||||
} catch (err) {
|
||||
setError('Bağlantı hatası. Lütfen tekrar deneyin.');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (success) {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#F8FAFC] flex flex-col items-center justify-center p-6">
|
||||
<div className="w-full max-w-2xl space-y-8 animate-in zoom-in duration-500">
|
||||
<div className="text-center space-y-4">
|
||||
<div className="w-24 h-24 bg-emerald-500 rounded-[32px] flex items-center justify-center text-white mx-auto shadow-2xl shadow-emerald-100 mb-6">
|
||||
<CheckCircle2 size={48} />
|
||||
</div>
|
||||
<h1 className="text-4xl font-black text-gray-900 tracking-tight uppercase italic">Tebrikler!</h1>
|
||||
<p className="text-gray-400 font-bold uppercase tracking-[0.3em] text-[10px]">Hesabınız Başarıyla Oluşturuldu</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-12 rounded-[50px] border border-gray-100 shadow-2xl space-y-10 relative overflow-hidden">
|
||||
<div className="absolute top-0 right-0 p-8 opacity-5">
|
||||
<Building2 size={120} />
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div className="p-8 bg-blue-50 rounded-[30px] border border-blue-100 space-y-4">
|
||||
<p className="text-[10px] font-black text-blue-600 uppercase tracking-widest text-center">Firma Yönetim Paneliniz</p>
|
||||
<div className="flex items-center justify-center gap-4">
|
||||
<code className="text-lg font-black text-gray-900 tracking-tighter">/merchant/{success.shortId}</code>
|
||||
<button
|
||||
onClick={() => navigator.clipboard.writeText(`${window.location.origin}/merchant/${success.shortId}`)}
|
||||
className="p-2 hover:bg-white rounded-lg transition-colors border border-transparent hover:border-blue-200"
|
||||
>
|
||||
<Copy size={16} className="text-blue-600" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-8 bg-red-50 rounded-[30px] border border-red-100 space-y-4">
|
||||
<div className="flex flex-col items-center text-center space-y-2">
|
||||
<p className="text-[10px] font-black text-red-600 uppercase tracking-widest italic">Kritik Güvenlik Anahtarı</p>
|
||||
<p className="text-[9px] text-red-400 font-bold uppercase leading-relaxed max-w-xs">
|
||||
Bu anahtarı güvenli bir yere kaydedin. Sisteme giriş yapmak için tek yönteminiz budur. Bir daha görüntülenemez!
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center justify-center gap-4 bg-white/50 p-4 rounded-2xl border border-red-50">
|
||||
<code className="text-sm font-mono font-bold text-gray-900 break-all text-center">{success.apiKey}</code>
|
||||
<button
|
||||
onClick={() => navigator.clipboard.writeText(success.apiKey)}
|
||||
className="p-2 hover:bg-white rounded-lg transition-colors shrink-0"
|
||||
>
|
||||
<Copy size={16} className="text-red-600" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => router.push(`/merchant/${success.shortId}/login`)}
|
||||
className="w-full py-6 bg-gray-900 text-white rounded-[24px] font-black text-xs uppercase tracking-[0.2em] hover:bg-black transition shadow-2xl flex items-center justify-center gap-3"
|
||||
>
|
||||
Paneli Aç ve Başla
|
||||
<ExternalLink size={18} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-[#F8FAFC] flex flex-col items-center justify-center p-6">
|
||||
<div className="w-full max-w-md space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-700">
|
||||
<div className="text-center space-y-4">
|
||||
<div className="w-20 h-20 bg-gray-900 rounded-[32px] flex items-center justify-center text-white mx-auto shadow-2xl shadow-gray-200 mb-6">
|
||||
<div className="mx-auto w-20 h-20 bg-blue-600 rounded-[32px] flex items-center justify-center text-white shadow-2xl shadow-blue-100 mb-6">
|
||||
<Building2 size={32} />
|
||||
</div>
|
||||
<h1 className="text-3xl font-black text-gray-900 tracking-tight uppercase italic">Firma Kaydı</h1>
|
||||
<p className="text-gray-400 font-bold uppercase tracking-widest text-[10px]">P2CGateway Merchant Network'e Katılın</p>
|
||||
<h1 className="text-3xl font-black text-gray-900 tracking-tight uppercase italic">Firma Başvurusu</h1>
|
||||
<p className="text-gray-400 font-bold uppercase tracking-widest text-[10px]">P2CGateway Merchant Network</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-10 rounded-[40px] border border-gray-100 shadow-xl shadow-gray-200/50 space-y-8">
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm font-black text-gray-900 leading-tight">Firma adınızı belirleyin</p>
|
||||
<p className="text-[10px] text-gray-400 font-bold uppercase tracking-wider leading-relaxed">
|
||||
Müşterileriniz ödeme sayfasında bu ismi görecektir.
|
||||
<div className="bg-white p-12 rounded-[48px] border border-gray-100 shadow-2xl shadow-gray-200/50 space-y-10 text-center relative overflow-hidden">
|
||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-40 h-1 bg-gradient-to-r from-transparent via-blue-600 to-transparent"></div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-2xl font-black text-gray-900 leading-tight">Kayıtlar Şuan Başvuruya Dayalıdır</h2>
|
||||
<p className="text-gray-500 font-medium leading-relaxed max-w-sm mx-auto">
|
||||
Güvenlik ve kalite standartlarımız gereği şu an için sadece ön başvurusu onaylanmış kurumsal firmaları kabul ediyoruz.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div className="space-y-3">
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
minLength={3}
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
placeholder="Örn: Ayris Teknoloji"
|
||||
className="w-full px-6 py-4 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 placeholder:text-gray-300"
|
||||
/>
|
||||
{error && <p className="text-[10px] text-red-500 font-black uppercase tracking-widest pl-2">{error}</p>}
|
||||
</div>
|
||||
<div className="p-8 bg-blue-50/50 rounded-3xl border border-blue-100 space-y-4">
|
||||
<p className="text-[10px] font-black text-blue-600 uppercase tracking-widest">Nasıl Kayıt Olurum?</p>
|
||||
<p className="text-sm font-bold text-gray-700 italic">"P2CGateway ekibiyle iletişime geçerek başvuru formunuzu talep edin."</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-blue-50/50 p-4 rounded-2xl space-y-2">
|
||||
<p className="text-[9px] text-blue-600/70 font-bold uppercase leading-relaxed">
|
||||
* Kayıt olduktan sonra size özel bir yönetim paneli ve API anahtarı tahsis edilecektir.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isLoading}
|
||||
className="w-full py-5 bg-blue-600 text-white rounded-2xl font-black text-xs uppercase tracking-[0.2em] hover:bg-blue-700 transition shadow-xl shadow-blue-100 disabled:opacity-50 flex items-center justify-center gap-2"
|
||||
<div className="pt-6 flex flex-col gap-4">
|
||||
<a
|
||||
href="mailto:sales@p2cgateway.store"
|
||||
className="w-full py-5 bg-gray-900 text-white rounded-2xl font-black text-xs uppercase tracking-[0.2em] hover:bg-black transition shadow-xl text-center"
|
||||
>
|
||||
{isLoading ? 'Kaydediliyor...' : 'Şimdi Katıl'}
|
||||
{!isLoading && <ArrowRight size={16} />}
|
||||
Satış Ekibiyle İletişime Geç
|
||||
</a>
|
||||
<button
|
||||
onClick={() => router.push('/')}
|
||||
className="text-[10px] font-black text-gray-400 uppercase tracking-widest hover:text-gray-900 transition"
|
||||
>
|
||||
Ana Sayfaya Dön
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div className="text-center pt-4">
|
||||
<button
|
||||
onClick={() => router.push('/')}
|
||||
className="text-[10px] font-black text-gray-400 uppercase tracking-widest hover:text-gray-900 transition"
|
||||
>
|
||||
Giriş Sayfasına Dön
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-20 flex items-center gap-3 px-6 py-2 bg-emerald-50 rounded-full border border-emerald-100">
|
||||
<ShieldCheck size={14} className="text-emerald-600" />
|
||||
<span className="text-[9px] font-black text-emerald-600 uppercase tracking-widest">End-to-End Secure Merchant Onboarding</span>
|
||||
<div className="mt-20 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-[9px] font-black text-blue-600 uppercase tracking-widest">Enterprise Secured Merchant Onboarding Flow</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user