Ana Logo (Header - Sol Üst)
Test
Logo Alt Text (SEO)
Logo için SEO açıklaması
${header.logoSrc ? `
` : `
Logo Eksik!
Site logosu ayarlanmamış. Lütfen bir logo yükleyin.
`}
Ana Sayfa Arka Plan Görseli
Arka Plan Alt Text
Arka plan için SEO açıklaması
${background.mainBg ? `
` : `
Arka Plan Eksik!
Ana sayfa arka plan görseli ayarlanmamış. Lütfen bir arka plan yükleyin.
`}
Oyun Kategorileri Bölümü Arka Planı
Oyun Kategorileri Arka Plan Alt Text
SEO için arka plan görsel açıklaması
${gameCategories.background?.src ? `
` : `
Oyun Kategorileri Arka Planı Eksik!
Oyun kategorileri bölümü arka plan görseli ayarlanmamış. Lütfen bir arka plan yükleyin.
`}
Oyun Kategori Kartları Görselleri
${(gameCategories.cards || []).map((card, index) => `
Kategori ${index + 1}: ${card.title_line1 || 'Başlık'} ${card.title_line2 || ''}
${card.background?.src ? `
` : ''}
`).join('')}
Oyun kategorisi eklemek için "Oyun Kategorileri" bölümünü kullanın
Hakkımızda Bölümü Arka Planı
Hakkımızda Arka Plan Alt Text
SEO için arka plan görsel açıklaması
${about.background?.src ? `
` : `
Hakkımızda Arka Planı Eksik!
Hakkımızda bölümü arka plan görseli ayarlanmamış. Lütfen bir arka plan yükleyin.
`}
Favicon ve Site İkonları
${(favicon.ico || favicon.png16 || favicon.png32 || favicon.appleTouch) ? `
` : `
Favicon Eksik!
Site ikonu henüz ayarlanmamış. En az bir favicon yükleyin.
`}
Tüm Görselleri Kaydet
`;
}
function buildContentSection() {
const hero = currentConfig.hero || {};
const marquee = currentConfig.marquee || {};
const mobileApp = currentConfig.mobileApp || {};
const about = currentConfig.about || {};
return `
İçerik Yönetimi
Ana Sayfa İçerikleri
Ana Sayfa Açıklama Metni
Mobil Uygulama Bölümü
Açıklama Metni
Hakkımızda Bölümü
Alt Başlık
Hakkımızda Metni (HTML destekli)
HTML etiketleri kullanabilirsiniz: <p>, <br>, <strong>
Değişiklikleri Kaydet
`;
}
function buildDesignSection() {
const design = currentConfig.design || {};
return `
Tasarım & Renkler
Ana Renk Paleti
Canlı Renk Önizlemesi
Ana Renk
Butonlar ve vurgular
Hover Rengi
Üzerine gelme efekti
Arka Plan
Site arka planı
Test Butonları:
Ana Buton
Menü Butonu
Şeffaf Buton
Gerçek Zamanlı Uygulama:
Renk değişiklikleri anında uygulanır. Kaydetmek için "Tasarım Değişikliklerini Kaydet" butonuna tıklayın.
Değişiklikler tüm siteye otomatik olarak yansıyacaktır.
Yazı Tipleri ve Boyutları
Önizleme Yap
Tasarım Değişikliklerini Kaydet
`;
}
function buildSeoSection() {
// 🐦 TWITTER CREATOR FIX: Ensure seo.twitter structure exists
if (!currentConfig.seo) {
currentConfig.seo = {};
}
if (!currentConfig.seo.twitter) {
currentConfig.seo.twitter = {};
}
const seo = currentConfig.seo || {};
const meta = seo.meta || {};
const openGraph = seo.openGraph || {};
const twitter = seo.twitter || {};
const tracking = seo.tracking || {};
console.log('🐦 Twitter Creator Debug - current value:', twitter.creator);
return `
SEO Ayarları
Sosyal Medya Paylaşım (Open Graph)
Paylaşım Açıklaması
Takip Kodları (Analytics)
SEO Ayarlarını Kaydet
`;
}
function buildAmpSection() {
const amp = currentConfig.amp || {};
return `
AMP Ayarları
AMP (Accelerated Mobile Pages) Yapılandırması
AMP Sayfa Yolu/URL
Yerel dosya için: index.amp.php
Uzak URL için: https://example.com/amp-sayfasi
AMP Nedir?
AMP (Accelerated Mobile Pages), mobil cihazlarda sayfalarınızın çok hızlı yüklenmesini sağlayan Google teknolojisidir.
SEO performansınızı artırır ve mobil kullanıcı deneyimini iyileştirir.
AMP Ayarlarını Kaydet
`;
}
function buildSocialSection() {
const header = currentConfig.header || {};
const social = header.social || [];
return `
Sosyal Medya Ayarları
Header Sosyal Medya Linkleri
Site üst kısmında görünecek sosyal medya hesap linkleri. Boş bırakılan linkler görünmeyecektir.
Nasıl Çalışır?
• URL alanlarını doldurun, boş bırakılan sosyal medya hesapları görünmeyecektir
• Linkler site üst kısmında ikonlar halinde görünür
• Değişiklikler kaydetildikten sonra anında aktif olur
• Tüm linkler yeni sekmede açılır (_blank)
Önizleme
Mevcut sosyal medya linklerinizin önizlemesi:
${social.map(item => {
if (item && item.url) {
return `
`;
}
return '';
}).join('')}
${social.filter(item => item && item.url).length === 0 ? '
Henüz sosyal medya linki eklenmemiş ' : ''}
Sosyal Medya Ayarlarını Kaydet
`;
}
// Placeholder functions for other sections
function buildGamesSection() {
const gameCategories = currentConfig.gameCategories || {};
const cards = gameCategories.cards || [];
return `
Oyun Kategorileri Yönetimi
${cards.map((card, index) => `
`).join('')}
Yeni Oyun Kategorisi Ekle
Yeni Kategori Ekle
Maksimum 6 oyun kategorisi ekleyebilirsiniz
Tam Bölüm Önizlemesi
${cards.map(card => `
${card.title_line1 || card.title?.split(' ')[0] || 'BAŞLIK'}
${card.title_line2 || card.title?.split(' ')[1] || 'ALT BAŞLIK'}
${card.button?.text || 'Buton Metni'}
`).join('')}
Oyun Kategorilerini Kaydet
`;
}
function buildPaymentSection() {
const footer = currentConfig.footer || {};
const payments = footer.payments || [];
return `
Ödeme Sistemleri Yönetimi
${payments.map((payment, index) => `
Ödeme Yöntemi ${index + 1}: ${payment.alt || 'İsimsiz Ödeme Yöntemi'}
${payment.img ? `
` : `
Logo URL'si girildikten sonra önizleme burada görünecek
`}
`).join('')}
Yeni Ödeme Yöntemi Ekle
Yeni Ödeme Yöntemi Ekle
Maksimum 10 ödeme yöntemi ekleyebilirsiniz
Tam Bölüm Önizlemesi
${footer.payment_title || 'GÜVENLİ ÖDEME YÖNTEMLERİ'}
${payments.length > 0 ? payments.map(payment => `
${payment.img ? `
` : `
${payment.alt || 'Logo Eksik'}
`}
`).join('') : '
Henüz ödeme yöntemi eklenmemiş
'}
Kullanım Bilgileri
Önerilen Logo Özellikleri:
• Format: PNG (şeffaf arka plan)
• Boyut: Minimum 200x80px, Maksimum 400x160px
• Dosya boyutu: Maksimum 100KB
• Yatay düzen tercih edilir
• Yüksek çözünürlük (2x) önerilir
Ödeme Sistemlerini Kaydet
`;
}
function buildAdvancedSection() {
const advanced = currentConfig.advanced || {};
const security = advanced.security || {};
const performance = advanced.performance || {};
const system = advanced.system || {};
const email = advanced.email || {};
const backup = advanced.backup || {};
const legal = advanced.legal || {};
const custom = advanced.custom || {};
return `
Gelişmiş Sistem Ayarları
Güvenlik ve Koruma Ayarları
Engellenen IP Adresleri (Her satıra bir IP)
Bu IP adreslerinden gelen istekler engellenecek
Site Durumu ve Genel Ayarlar
Bakım Modu Mesajı
Yedekleme ve Geri Yükleme
Yedek Oluştur
Config İndir
Cache Temizle
Özel Kod Ekleme
Özel CSS Kodları
Bu kodlar sitenin <head> bölümüne eklenecek
Özel JavaScript Kodları
Bu kodlar sayfanın sonuna eklenecek
Google Tag Manager ID
Google Tag Manager container ID'si
Lisans ve Yasal Uyarılar
Yaş Sınırı Uyarısı
Sistem Bilgileri ve Durum
Server Yazılımı
LiteSpeed
Güvenlik Durumu:
✅ SSL Sertifikası Aktif
✅ Güvenlik Başlıkları Yapılandırıldı
✅ Rate Limiting Aktif
✅ Brute Force Koruması Aktif
Gelişmiş Ayarları Kaydet
`;
}
function buildFooterSection() {
const footer = currentConfig.footer || {};
const columns = footer.columns || [];
return `
Footer Yönetimi
Logo ve Açıklama Bölümü
Footer Açıklama Metni
Logo altında görünecek açıklama metni
${columns.map((column, columnIndex) => `
${column.title || `Kolon ${columnIndex + 1}`}
Kolon Başlığı
Bu kolonun üst başlığı
${(column.logos || []).length > 0 ? `
Logo Önizlemesi:
${column.logos.map(logo => `
`).join('')}
` : ''}
`).join('')}
Yeni Footer Kolonu Ekle
Yeni Kolon Ekle
Maksimum 4 kolon önerilir
Footer Önizlemesi
${footer.payment_title || 'GÜVENLİ ÖDEME YÖNTEMLERİ'}
${(footer.payments || []).map(payment => `
`).join('')}
LOGO
${footer.about_text || 'Footer açıklama metni buraya gelecek...'}
${Array(5).fill(0).map(() => '
').join('')}
${columns.map(column => `
${column.title || 'Kolon Başlığı'}
${(column.links || []).map(link => `
${link.text}
`).join('')}
${(column.logos || []).length > 0 ? `
${column.logos.map(logo => `
`).join('')}
` : ''}
`).join('')}
${footer.copyright || 'Copyrights © 2019 Kareasbet. Tüm Hakları Saklıdır.'}
Footer Ayarlarını Kaydet
`;
}
async function initializeAdminPanel() {
console.log('🔧 initializeAdminPanel başlatılıyor...');
// Load admin functions from database first
try {
console.log('📦 Database admin functions loading...');
await loadAdminFunctionsFromDB();
console.log('✅ Database admin functions loaded');
} catch (error) {
console.warn('⚠️ Database admin functions failed, loading emergency functions:', error);
loadEmergencyAdminFunctions();
}
// Ensure all critical functions are available globally
const criticalFunctions = {
showSection: typeof showSection !== 'undefined' ? showSection : function(section) {
console.log('🔄 Switching to section:', section);
currentSection = section;
document.querySelectorAll('.admin-nav-item').forEach(item => item.classList.remove('active'));
const navItem = document.querySelector(`[data-section="${section}"]`);
if (navItem) navItem.classList.add('active');
buildAdminSection(section);
},
logout: typeof logout !== 'undefined' ? logout : function() {
window.location.href = 'index.php?logout=true';
},
buildAdminSection: typeof buildAdminSection !== 'undefined' ? buildAdminSection : function(section) {
console.log('🏗️ Building admin section:', section);
const container = document.getElementById('admin-sections');
let html = '';
switch(section) {
case 'dashboard':
html = (typeof buildDashboard !== 'undefined') ? buildDashboard() : 'Dashboard Dashboard loading...
';
break;
case 'content':
html = (typeof buildContentSection !== 'undefined') ? buildContentSection() : 'Content Content section loading...
';
break;
case 'visuals':
html = (typeof buildVisualsSection !== 'undefined') ? buildVisualsSection() : 'Visuals Visuals section loading...
';
break;
case 'menu':
html = (typeof buildMenuSection !== 'undefined') ? buildMenuSection() : 'Menu Menu section loading...
';
break;
case 'design':
html = (typeof buildDesignSection !== 'undefined') ? buildDesignSection() : 'Design Design section loading...
';
break;
case 'seo':
html = (typeof buildSeoSection !== 'undefined') ? buildSeoSection() : 'SEO SEO section loading...
';
break;
case 'social':
html = (typeof buildSocialSection !== 'undefined') ? buildSocialSection() : 'Social Social section loading...
';
break;
case 'games':
html = (typeof buildGamesSection !== 'undefined') ? buildGamesSection() : 'Games Games section loading...
';
break;
case 'payment':
html = (typeof buildPaymentSection !== 'undefined') ? buildPaymentSection() : 'Payment Payment section loading...
';
break;
case 'footer':
html = (typeof buildFooterSection !== 'undefined') ? buildFooterSection() : 'Footer Footer section loading...
';
break;
case 'amp':
html = (typeof buildAmpSection !== 'undefined') ? buildAmpSection() : 'AMP AMP section loading...
';
break;
case 'advanced':
html = (typeof buildAdvancedSection !== 'undefined') ? buildAdvancedSection() : 'Advanced Advanced section loading...
';
break;
default:
html = 'Unknown Section Section not found: ' + section + '
';
}
if (container) {
container.innerHTML = html;
console.log('✅ Admin section built:', section);
} else {
console.error('❌ Admin sections container not found');
}
}
};
// Make all functions globally available
Object.assign(window, criticalFunctions);
// Initialize form state management
console.log('🔧 Form state management başlatılıyor...');
if (typeof formStateCache === 'undefined') {
window.formStateCache = {};
}
// Additional functions - only if they exist
const additionalFunctions = [
'addGameCategory', 'removeGameCategory', 'createBackup', 'downloadConfig',
'clearCache', 'addFooterColumn', 'removeFooterColumn', 'addFooterLink',
'removeFooterLink', 'addFooterLogo', 'removeFooterLogo', 'setTestLogo',
'saveChanges', 'validateAdminData', 'restoreDefaultData'
];
additionalFunctions.forEach(funcName => {
if (typeof window[funcName] !== 'undefined') {
// Function already exists, keep it
} else {
// Create placeholder
window[funcName] = function(...args) {
console.warn(`⚠️ Function ${funcName} not fully loaded, args:`, args);
alert(`Fonksiyon "${funcName}" henüz yüklenmedi. Lütfen sayfayı yenileyin.`);
};
}
});
console.log('🎯 Building initial dashboard...');
window.buildAdminSection('dashboard');
console.log('🔗 Setting up navigation...');
// Admin navigation event listeners
document.querySelectorAll('.admin-nav-item').forEach(item => {
item.addEventListener('click', function(e) {
e.preventDefault();
const section = this.getAttribute('data-section');
if (section) {
showSection(section);
}
});
});
// Quick actions event listeners
document.addEventListener('click', function(e) {
if (e.target.closest('[data-action]')) {
const action = e.target.closest('[data-action]').getAttribute('data-action');
switch(action) {
case 'content':
case 'visuals':
case 'design':
case 'seo':
showSection(action);
break;
case 'view':
window.open('index.php', '_blank');
break;
case 'logout':
logout();
break;
}
}
});
}
// Removed: Debug functions (production version)
async function saveChanges() {
console.log('🚀 === SAVE CHANGES STARTED ===');
let newConfig = null;
// EMERGENCY RECOVERY WRAPPER
try {
// 1. ÖNCE TOKEN'I YENİLE - Bu problemi çözecek!
console.log('🔄 CSRF token yenileniyor...');
try {
await refreshCSRFToken();
} catch (tokenError) {
console.error('❌ Token yenileme hatası:', tokenError);
throw new Error('CSRF token yenileme başarısız: ' + tokenError.message);
}
// 2. Yenilenmiş token'ı al
const csrfMetaTag = document.querySelector('meta[name="csrf-token"]');
const csrfToken = csrfMetaTag?.getAttribute('content');
console.log('🔐 CSRF Token (yenilenmiş):', csrfToken ? '✅ Found' : '❌ Missing');
if (!csrfToken) {
throw new Error('Güvenlik token\'ı bulunamadı veya yenilenemedi');
}
// 2. Güvenli config kopyalama
newConfig = safeDeepClone(currentConfig);
console.log('📋 Config cloned safely. Keys:', Object.keys(newConfig));
// 3. Form verilerini güvenli şekilde topla
console.log('📝 Collecting form data...');
let formData;
try {
formData = collectFormData();
console.log('📊 Form data collected:', Object.keys(formData));
// Form data validation
if (!formData || typeof formData !== 'object') {
throw new Error('Form verisi toplanamadı veya geçersiz format');
}
} catch (formError) {
console.error('❌ Form data toplama hatası:', formError);
throw new Error('Form verilerinde hata: ' + formError.message);
}
// 4. Config'i güvenli şekilde güncelle
try {
newConfig = safeUpdateConfig(currentConfig, formData);
console.log('🔄 Config updated safely');
// Config validation
if (!newConfig || typeof newConfig !== 'object') {
throw new Error('Config güncelleme sonucu geçersiz');
}
} catch (configError) {
console.error('❌ Config güncelleme hatası:', configError);
throw new Error('Config güncellemesi başarısız: ' + configError.message);
}
// 5. Verileri validate et
const validation = validateConfig(newConfig);
if (!validation.valid) {
throw new Error('❌ Config validation failed: ' + validation.errors.join(', '));
}
console.log('✅ Config validation passed');
// 6. API'ye güvenli gönderim
console.log('📤 Sending to API...');
let response;
try {
// JSON serialization test BEFORE sending
const testJson = JSON.stringify(newConfig);
if (!testJson || testJson.length === 0) {
throw new Error('Config JSON serileştirilemedi');
}
response = await safeSendToAPI(newConfig, csrfToken);
if (!response) {
throw new Error('API\'den yanıt alınamadı');
}
} catch (apiError) {
console.error('❌ API gönderim hatası:', apiError);
throw new Error('API iletişim hatası: ' + apiError.message);
}
if (response.success) {
console.log('🎉 SAVE SUCCESSFUL!');
// Config'i güncelle
currentConfig = newConfig;
siteConfig = newConfig;
// Public page'i güncelle
renderPublicPage(newConfig);
// HEMEN token'ı yenile - Bir sonraki kaydetme için
console.log('🔄 Başarılı kaydetmeden sonra token yenileniyor...');
await refreshCSRFToken();
// Başarı mesajını göster
alert('✅ Değişiklikler başarıyla kaydedildi!\n\n🔑 Admin panel bir sonraki değişiklik için hazır!');
// Cache problemini çözmek için anasayfayı yenile
setTimeout(() => {
console.log('🔄 Cache problemini önlemek için anasayfa yenileniyor...');
// Anasayfayı yeni sekmede aç ki admin panel kapanmasın
const newTab = window.open('index.php?t=' + Date.now(), '_blank');
if (newTab) {
newTab.focus();
} else {
// Popup blocker varsa bu şekilde çözüm
console.log('📱 Popup engellendi, manuel yenileme önerisi gösteriliyor');
showCacheRefreshNotification();
}
}, 2000);
} else {
throw new Error(response.error || 'API kaydetme hatası');
}
} catch (error) {
console.error('💥 SAVE ERROR:', error);
console.error('💥 Error Stack:', error.stack);
// EMERGENCY RECOVERY MODE
const errorMessage = error.message || 'Bilinmeyen hata';
// Error categorization for better handling
let recoveryOptions = [];
let autoRecovery = false;
if (errorMessage.includes('CSRF') || errorMessage.includes('token') || errorMessage.includes('403')) {
console.log('🔧 CSRF/Token error detected');
recoveryOptions.push('🔑 Token yenile ve tekrar dene');
recoveryOptions.push('🔄 Debug mode ile kaydet');
autoRecovery = true;
} else if (errorMessage.includes('JSON') || errorMessage.includes('parse')) {
console.log('🔧 JSON error detected');
recoveryOptions.push('📝 Form verilerini temizle');
recoveryOptions.push('🔄 Debug mode ile kaydet');
} else if (errorMessage.includes('API') || errorMessage.includes('network') || errorMessage.includes('fetch')) {
console.log('🔧 Network error detected');
recoveryOptions.push('🌐 Bağlantıyı kontrol et');
recoveryOptions.push('🔄 Debug mode ile kaydet');
autoRecovery = true;
} else if (errorMessage.includes('Form') || errorMessage.includes('data')) {
console.log('🔧 Form data error detected');
recoveryOptions.push('📝 Formu yenile');
recoveryOptions.push('🔄 Sayfayı yenile');
}
// AUTO RECOVERY for token issues
if (autoRecovery && (errorMessage.includes('CSRF') || errorMessage.includes('token'))) {
console.log('🚨 STARTING AUTO RECOVERY...');
// Show emergency status
const statusDisplay = showEmergencyStatus('OTOMATIK KURTARMA BAŞLATILIYOR... Token yenileniyor ve debug mode deneniyor...', true);
try {
console.log('🔄 Auto recovery: Token refreshing...');
await refreshCSRFToken();
statusDisplay.querySelector('div:nth-child(2)').textContent = 'Token yenilendi! Debug mode ile kaydetme deneniyor...';
console.log('🔄 Auto recovery: Trying debug mode save...');
const debugResult = await saveChangesDebugMode(newConfig || currentConfig);
if (debugResult) {
statusDisplay.remove();
showSecurityNotification('✅ OTOMATIK KURTARMA BAŞARILI! Değişiklikler debug mode ile kaydedildi.', 'success');
return;
}
} catch (recoveryError) {
console.error('❌ Auto recovery failed:', recoveryError);
statusDisplay.remove();
showEmergencyStatus('OTOMATIK KURTARMA BAŞARISIZ! Manuel kurtarma seçenekleri gösteriliyor...');
}
}
// MANUAL RECOVERY OPTIONS
let recoveryMessage = `🚨 CRITICAL ERROR DETECTED
❌ Hata: ${errorMessage}
🔧 RECOVERY OPTIONS:`;
if (recoveryOptions.length > 0) {
recoveryMessage += '\n\n' + recoveryOptions.map((option, index) => `${index + 1}. ${option}`).join('\n');
} else {
recoveryMessage += '\n\n1. 🔄 Debug mode ile kaydet\n2. 🚨 Emergency cache temizle\n3. 🔄 Sayfayı yenile';
}
recoveryMessage += '\n\nEADY TO PROCEED?';
if (confirm(recoveryMessage + '\n\nDebug mode ile kaydetmeyi deneyelim mi?')) {
// Show manual recovery status
const manualStatusDisplay = showEmergencyStatus('MANUEL KURTARMA BAŞLATILIYOR... Debug mode ile kaydetme deneniyor...', true);
try {
console.log('🔄 Manual recovery: Trying debug mode...');
const debugResult = await saveChangesDebugMode(newConfig || currentConfig);
if (debugResult) {
manualStatusDisplay.remove();
showSecurityNotification('✅ MANUEL KURTARMA BAŞARILI! Değişiklikler debug mode ile kaydedildi.', 'success');
return;
}
} catch (debugError) {
console.error('❌ Manual debug recovery failed:', debugError);
manualStatusDisplay.remove();
showEmergencyStatus('MANUEL KURTARMA DA BAŞARISIZ! Emergency cache clear öneriliyor...');
}
}
// LAST RESORT - Emergency cache clear
if (confirm('❌ Kurtarma başarısız!\n\n🚨 Son çare olarak Emergency Cache Clear yapılsın mı?\n\nBu işlem admin panelini tamamen sıfırlayacak.')) {
emergencyCacheClear();
} else {
alert('❌ Kaydetme başarısız oldu.\n\nLütfen sayfayı yenileyip tekrar deneyin.\n\nSorun devam ederse teknik destek ile iletişime geçin.');
}
}
}
// Güvenli deep clone fonksiyonu
function safeDeepClone(obj) {
try {
return JSON.parse(JSON.stringify(obj));
} catch (error) {
console.error('Deep clone error:', error);
return {};
}
}
// Form verilerini güvenli şekilde toplama - ROBUST VERSION
function collectFormData() {
const formData = {};
try {
console.log('🔍 ADMIN PANEL FORM COLLECTION BAŞLATILIYOR...');
// Önce admin sections var mı kontrol et
const adminSections = document.getElementById('admin-sections');
console.log('📋 Admin sections element:', adminSections ? 'FOUND' : 'NOT FOUND');
let inputs;
if (adminSections) {
inputs = adminSections.querySelectorAll('input[name], textarea[name], select[name]');
console.log(`📝 Admin sections içinde ${inputs.length} input bulundu`);
} else {
// Fallback - tüm sayfa inputs
inputs = document.querySelectorAll('input[name], textarea[name], select[name]');
console.log(`📝 Fallback: Sayfa genelinde ${inputs.length} input bulundu`);
}
if (!inputs || inputs.length === 0) {
throw new Error('Hiç form input bulunamadı');
}
return collectFromInputs(inputs, formData);
} catch (error) {
console.error('❌ Form data collection error:', error);
throw new Error('Form verisi toplanamadı: ' + error.message);
}
}
// Helper function for input collection
function collectFromInputs(inputs, formData) {
let processedCount = 0;
let errorCount = 0;
inputs.forEach((input, index) => {
try {
const name = input.name;
if (!name || name.trim() === '') {
console.debug(`Input ${index}: boş name atlandı`);
return;
}
console.log(`🔍 Processing input ${index}: "${name}" = "${input.value}"`);
// REMOVED STRICT VALIDATION - artık tüm name formatları kabul ediliyor
// Admin panel'de basit name'ler de olabilir
let value;
try {
if (input.type === 'checkbox') {
value = input.checked;
} else if (input.type === 'number') {
const numValue = parseFloat(input.value);
value = isNaN(numValue) ? 0 : numValue;
} else if (input.type === 'color') {
value = input.value || '#000000';
} else {
value = input.value || '';
}
} catch (valueError) {
console.warn(`Input ${index} value error:`, valueError);
value = '';
}
// Array handling için özel kontroller
try {
if (name.includes('[') && name.includes(']')) {
const arrayMatch = name.match(/(.+)\[(\d+)\]\.(.+)/);
if (arrayMatch) {
const [, basePath, arrayIndex, property] = arrayMatch;
const keys = basePath.split('.');
const index = parseInt(arrayIndex);
if (isNaN(index)) {
throw new Error(`Invalid array index: ${arrayIndex}`);
}
keys.push(index, property);
setNestedValue(formData, keys, value);
processedCount++;
} else {
console.warn(`Invalid array format: ${name}`);
}
} else {
const keys = name.split('.');
if (keys.length === 0) {
throw new Error(`Empty keys for name: ${name}`);
}
setNestedValue(formData, keys, value);
processedCount++;
}
} catch (nestError) {
console.error(`Nested value error for ${name}:`, nestError);
errorCount++;
}
} catch (error) {
console.error(`Error processing input ${index} (${input.name}):`, error);
errorCount++;
}
});
console.log(`📊 Form collection summary: ${processedCount} processed, ${errorCount} errors`);
if (processedCount === 0) {
throw new Error('Hiç form verisi işlenemedi');
}
if (errorCount > processedCount * 0.5) {
throw new Error(`Çok fazla hata: ${errorCount}/${inputs.length}`);
}
return formData;
}
// Nested değer atama - ROBUST VERSION
function setNestedValue(obj, keys, value) {
if (!obj || !keys || keys.length === 0) {
throw new Error('Invalid parameters for setNestedValue');
}
let current = obj;
try {
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
const nextKey = keys[i + 1];
// Key validation
if (key === null || key === undefined) {
throw new Error(`Invalid key at index ${i}: ${key}`);
}
// Check if current is a valid object
if (current === null || current === undefined) {
throw new Error(`Cannot set property ${key} on null/undefined`);
}
// Type checking
if (typeof current !== 'object') {
throw new Error(`Cannot set property ${key} on non-object: ${typeof current}`);
}
if (!current[key]) {
current[key] = typeof nextKey === 'number' ? [] : {};
}
current = current[key];
}
const finalKey = keys[keys.length - 1];
// Final key validation
if (finalKey === null || finalKey === undefined) {
throw new Error(`Invalid final key: ${finalKey}`);
}
// Final assignment
current[finalKey] = value;
} catch (error) {
console.error('❌ setNestedValue error:', error);
console.error('Keys:', keys);
console.error('Value:', value);
throw new Error(`Nested value assignment failed: ${error.message}`);
}
}
// Config'i güvenli şekilde güncelleme
function safeUpdateConfig(baseConfig, formData) {
try {
// Form data'yı base config'e merge et
const updated = deepMerge(baseConfig, formData);
// Özel temizlik işlemleri
if (updated.header?.social) {
updated.header.social = updated.header.social.filter(item =>
item && item.url && item.url.trim() !== ''
);
}
if (updated.footer?.payments) {
updated.footer.payments = updated.footer.payments.filter(item =>
item && item.img && item.img.trim() !== ''
);
}
return updated;
} catch (error) {
console.error('Config update error:', error);
throw new Error('Config güncellemesi başarısız');
}
}
// Deep merge fonksiyonu
function deepMerge(target, source) {
const result = { ...target };
for (const key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
result[key] = deepMerge(target[key] || {}, source[key]);
} else {
result[key] = source[key];
}
}
}
return result;
}
// Config validation
function validateConfig(config) {
const errors = [];
try {
// JSON serialization test
const jsonString = JSON.stringify(config);
if (jsonString.length > 5000000) { // 5MB limit
errors.push('Config too large');
}
// Required fields check
if (!config.pageTitle) errors.push('Page title required');
if (!config.hero) errors.push('Hero section required');
return {
valid: errors.length === 0,
errors: errors
};
} catch (error) {
return {
valid: false,
errors: ['Config validation failed: ' + error.message]
};
}
}
// API'ye güvenli gönderim
async function safeSendToAPI(config, csrfToken) {
try {
console.log('📡 API Request starting...');
console.log('📊 Config size:', JSON.stringify(config).length, 'characters');
const response = await fetch('api.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken
},
body: JSON.stringify(config)
});
console.log('📨 API Response status:', response.status);
const responseText = await response.text();
console.log('📄 API Response text:', responseText.substring(0, 200));
let result;
try {
result = JSON.parse(responseText);
} catch (parseError) {
console.error('API JSON parse error:', parseError);
throw new Error('API yanıtı geçersiz JSON: ' + responseText.substring(0, 100));
}
if (!response.ok) {
throw new Error(result.error || `HTTP ${response.status}: ${response.statusText}`);
}
return result;
} catch (error) {
console.error('API send error:', error);
throw error;
}
}
async function saveChangesDebugMode(config) {
console.log('🔧 === DEBUG MODE SAVE ===');
if (!config) {
alert('❌ Debug mode: Config verisi bulunamadı');
return false;
}
try {
console.log('🚀 Debug mode: Starting save...');
console.log('📊 Config keys:', Object.keys(config));
// Debug mode'da da token yenile
console.log('🔄 Debug mode: Token yenileniyor...');
await refreshCSRFToken();
const response = await fetch('api.php?debug=true', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(config)
});
console.log('📨 Debug response status:', response.status);
const responseText = await response.text();
console.log('📄 Debug response text:', responseText.substring(0, 300));
let result;
try {
result = JSON.parse(responseText);
} catch (parseError) {
console.error('Debug JSON parse error:', parseError);
throw new Error('Debug mode: API yanıtı geçersiz JSON: ' + responseText.substring(0, 100));
}
if (response.ok && result.success) {
console.log('✅ Debug mode başarılı!');
alert('✅ Debug mode ile kaydetme başarılı! CSRF problemi çözüldü.');
// Config'i güncelle
currentConfig = config;
siteConfig = config;
// Public page'i güncelle
renderPublicPage(config);
// Cache problemini çözmek için anasayfayı yenile
setTimeout(() => {
console.log('🔄 Debug mode: Cache problemini önlemek için anasayfa yenileniyor...');
const newTab = window.open('index.php?t=' + Date.now(), '_blank');
if (newTab) {
newTab.focus();
} else {
showCacheRefreshNotification();
}
}, 2000);
return true;
} else {
throw new Error(result.error || `Debug mode HTTP ${response.status}: ${response.statusText}`);
}
} catch (error) {
console.error('💥 Debug mode error:', error);
alert('❌ Debug mode kaydetme hatası: ' + error.message);
return false;
}
}
function attachFormHandlers() {
console.log('🔗 Form handlers ekleniyor...');
// Form State Restoration - Korunan verileri geri yükle
restoreFormState();
// Color input synchronization
const colorInputs = document.querySelectorAll('input[type="color"]');
colorInputs.forEach(input => {
const name = input.getAttribute('name');
const textInput = document.querySelector(`input[name="${name}_text"]`);
if (textInput) {
// Color picker changes text input
input.addEventListener('change', () => {
textInput.value = input.value;
// State'i hemen güncelle
updateFormStateCache(name, input.value);
});
// Text input changes color picker
textInput.addEventListener('input', () => {
if (/^#[0-9A-F]{6}$/i.test(textInput.value)) {
input.value = textInput.value;
// State'i hemen güncelle
updateFormStateCache(name, textInput.value);
}
});
}
});
// Auto-save on input changes to prevent data loss
const allInputs = document.querySelectorAll('#admin-sections input, #admin-sections textarea, #admin-sections select');
allInputs.forEach(input => {
if (!input.name || input.name.trim() === '') return;
const eventType = input.type === 'checkbox' || input.type === 'radio' ? 'change' : 'input';
input.addEventListener(eventType, function() {
// 🐦 TWITTER CREATOR IMMEDIATE UPDATE
if (input.name === 'seo.twitter.creator') {
console.log('🐦 Twitter creator input change detected:', input.value);
updateFormStateCache(input.name, getInputValue(input));
return;
}
// Debounced auto-update for other fields
clearTimeout(input.autoUpdateTimeout);
input.autoUpdateTimeout = setTimeout(() => {
updateFormStateCache(input.name, getInputValue(input));
}, 300); // 300ms delay
});
});
console.log('✅ Form handlers eklendi - auto-save aktif');
}
function restoreFormState() {
try {
console.log('🔄 Form state geri yükleniyor...');
const inputs = document.querySelectorAll('#admin-sections input, #admin-sections textarea, #admin-sections select');
let restoredCount = 0;
inputs.forEach(input => {
if (!input.name || input.name.trim() === '') return;
let value = getNestedValue(formStateCache, input.name) || getNestedValue(currentConfig, input.name);
// 🐦 TWITTER CREATOR SPECIAL RESTORE
if (input.name === 'seo.twitter.creator') {
console.log('🐦 Restoring Twitter creator field...');
// Try multiple sources for the value
value = value ||
formStateCache?.seo?.twitter?.creator ||
currentConfig?.seo?.twitter?.creator ||
'';
console.log('🐦 Twitter creator restore value:', value);
}
if (value !== undefined && value !== null) {
setInputValue(input, value);
restoredCount++;
if (input.name === 'seo.twitter.creator') {
console.log('🐦 Twitter creator field restored with value:', value);
}
}
});
console.log(`✅ ${restoredCount} form alanı geri yüklendi`);
} catch (error) {
console.error('❌ Form state geri yükleme hatası:', error);
}
}
function getNestedValue(obj, path) {
return path.split('.').reduce((current, key) => {
return current && current[key] !== undefined ? current[key] : undefined;
}, obj);
}
function setInputValue(input, value) {
try {
switch (input.type) {
case 'checkbox':
input.checked = Boolean(value);
break;
case 'radio':
if (input.value === String(value)) {
input.checked = true;
}
break;
case 'number':
case 'range':
input.value = Number(value) || 0;
break;
default:
input.value = String(value || '');
}
} catch (error) {
console.warn(`⚠️ Input value set error for ${input.name}:`, error);
}
}
function getInputValue(input) {
switch (input.type) {
case 'checkbox':
return input.checked;
case 'radio':
return input.checked ? input.value : undefined;
case 'number':
case 'range':
return parseFloat(input.value) || 0;
case 'color':
return input.value || '#000000';
default:
return input.value ? input.value.trim() : '';
}
}
function updateNestedValue(obj, path, value) {
const pathParts = path.split('.');
let current = obj;
for (let i = 0; i < pathParts.length - 1; i++) {
const part = pathParts[i];
if (!current[part]) {
current[part] = {};
}
current = current[part];
}
const finalPart = pathParts[pathParts.length - 1];
current[finalPart] = value;
}
function updateFormStateCache(fieldName, value) {
if (value === undefined) return;
try {
console.log('📝 Form state update:', fieldName, '=', value);
// 🐦 TWITTER CREATOR SPECIAL HANDLING
if (fieldName === 'seo.twitter.creator') {
console.log('🐦 Twitter creator field detected - ensuring structure...');
// Ensure seo.twitter structure exists in currentConfig
if (!currentConfig.seo) {
currentConfig.seo = {};
}
if (!currentConfig.seo.twitter) {
currentConfig.seo.twitter = {};
}
// Set the value directly
currentConfig.seo.twitter.creator = value;
console.log('✅ Twitter creator set to:', currentConfig.seo.twitter.creator);
// Also update formStateCache
if (!formStateCache.seo) {
formStateCache.seo = {};
}
if (!formStateCache.seo.twitter) {
formStateCache.seo.twitter = {};
}
formStateCache.seo.twitter.creator = value;
} else {
// Standard processing for other fields
// formStateCache'i güncelle
updateNestedValue(formStateCache, fieldName, value);
// currentConfig'i de güncelle - nested path için
updateNestedValue(currentConfig, fieldName, value);
}
// Global değişkenleri de güncelle
window.currentConfig = currentConfig;
window.siteConfig = currentConfig;
} catch (error) {
console.warn(`⚠️ Form state cache update error for ${fieldName}:`, error);
}
}
// Oyun kategorisi ekleme fonksiyonu
function addGameCategory() {
if (!currentConfig.gameCategories) currentConfig.gameCategories = {};
if (!currentConfig.gameCategories.cards) currentConfig.gameCategories.cards = [];
const cards = currentConfig.gameCategories.cards;
if (cards.length >= 6) {
alert('Maksimum 6 oyun kategorisi ekleyebilirsiniz!');
return;
}
cards.push({
title_line1: 'YENİ',
title_line2: 'KATEGORİ',
background: {
src: '/img/online-slot.png',
alt: 'Yeni oyun kategorisi'
},
button: {
text: 'Hadi Hemen Oyna!',
url: 'https://cutt.ly/Fw0yDcFe'
}
});
showSection('games');
}
// Oyun kategorisi silme fonksiyonu
function removeGameCategory(index) {
if (confirm('Bu oyun kategorisini silmek istediğinizden emin misiniz?')) {
if (!currentConfig.gameCategories) currentConfig.gameCategories = {};
if (!currentConfig.gameCategories.cards) currentConfig.gameCategories.cards = [];
currentConfig.gameCategories.cards.splice(index, 1);
showSection('games');
}
}
// Gelişmiş ayarlar buton fonksiyonları
function createBackup() {
if (confirm('Şu anki site ayarlarının yedeğini oluşturmak istediğinizden emin misiniz?')) {
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
if (!csrfToken) {
alert('❌ Güvenlik token\'ı bulunamadı. Sayfayı yenileyin.');
return;
}
fetch('api.php?action=create_backup', {
method: 'POST',
headers: {
'X-CSRF-Token': csrfToken
}
})
.then(response => response.json())
.then(result => {
if (result.success) {
alert('✅ Yedek başarıyla oluşturuldu!');
} else {
alert('❌ Yedek oluşturulamadı: ' + (result.error || 'Bilinmeyen hata'));
}
})
.catch(error => {
console.error('Backup error:', error);
alert('❌ Yedekleme sırasında hata oluştu: ' + error.message);
});
}
}
function downloadConfig() {
const configData = JSON.stringify(currentConfig, null, 2);
const blob = new Blob([configData], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `kareasbet-config-${new Date().toISOString().split('T')[0]}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
alert('✅ Konfigürasyon dosyası indirildi!');
}
function clearCache() {
if (confirm('Site önbelleğini temizlemek istediğinizden emin misiniz? Bu işlem site performansını geçici olarak etkileyebilir.')) {
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
if (!csrfToken) {
alert('❌ Güvenlik token\'ı bulunamadı. Sayfayı yenileyin.');
return;
}
fetch('api.php?action=clear_cache', {
method: 'POST',
headers: {
'X-CSRF-Token': csrfToken
}
})
.then(response => response.json())
.then(result => {
if (result.success) {
alert('✅ Önbellek başarıyla temizlendi!');
} else {
alert('❌ Önbellek temizlenemedi: ' + (result.error || 'Bilinmeyen hata'));
}
})
.catch(error => {
console.error('Cache clear error:', error);
alert('❌ Önbellek temizleme sırasında hata oluştu: ' + error.message);
});
}
}
// Footer yönetimi fonksiyonları
function addFooterColumn() {
if (!currentConfig.footer) currentConfig.footer = {};
if (!currentConfig.footer.columns) currentConfig.footer.columns = [];
const columns = currentConfig.footer.columns;
if (columns.length >= 4) {
alert('Maksimum 4 footer kolonu önerilir!');
return;
}
columns.push({
title: 'Yeni Kolon',
links: [],
logos: []
});
showSection('footer');
}
function removeFooterColumn(columnIndex) {
if (confirm('Bu footer kolonunu silmek istediğinizden emin misiniz?')) {
if (!currentConfig.footer) currentConfig.footer = {};
if (!currentConfig.footer.columns) currentConfig.footer.columns = [];
currentConfig.footer.columns.splice(columnIndex, 1);
showSection('footer');
}
}
function addFooterLink(columnIndex) {
if (!currentConfig.footer) currentConfig.footer = {};
if (!currentConfig.footer.columns) currentConfig.footer.columns = [];
if (!currentConfig.footer.columns[columnIndex]) return;
if (!currentConfig.footer.columns[columnIndex].links) {
currentConfig.footer.columns[columnIndex].links = [];
}
currentConfig.footer.columns[columnIndex].links.push({
text: 'Yeni Link',
url: 'https://'
});
showSection('footer');
}
function removeFooterLink(columnIndex, linkIndex) {
if (confirm('Bu linki silmek istediğinizden emin misiniz?')) {
if (!currentConfig.footer?.columns?.[columnIndex]?.links) return;
currentConfig.footer.columns[columnIndex].links.splice(linkIndex, 1);
showSection('footer');
}
}
function addFooterLogo(columnIndex) {
if (!currentConfig.footer) currentConfig.footer = {};
if (!currentConfig.footer.columns) currentConfig.footer.columns = [];
if (!currentConfig.footer.columns[columnIndex]) return;
if (!currentConfig.footer.columns[columnIndex].logos) {
currentConfig.footer.columns[columnIndex].logos = [];
}
currentConfig.footer.columns[columnIndex].logos.push({
img: '/img/logo.png',
alt: 'Logo',
url: 'https://'
});
showSection('footer');
}
function removeFooterLogo(columnIndex, logoIndex) {
if (confirm('Bu logoyu silmek istediğinizden emin misiniz?')) {
if (!currentConfig.footer?.columns?.[columnIndex]?.logos) return;
currentConfig.footer.columns[columnIndex].logos.splice(logoIndex, 1);
showSection('footer');
}
}
// EMERGENCY CACHE CLEARING - Admin panel için
window.emergencyCacheClear = function() {
console.log('🚨 EMERGENCY CACHE CLEAR BAŞLATILDI');
if (confirm('🚨 EMERGENCY CACHE TEMIZLEME\n\nBu işlem admin panelini tamamen yeniler ve tüm cache\'i temizler.\n\nDevam edilsin mi?')) {
// Local storage temizle
localStorage.clear();
sessionStorage.clear();
// Cache API ile temizle (modern browsers)
if ('caches' in window) {
caches.keys().then(function(names) {
names.forEach(function(name) {
caches.delete(name);
});
});
}
// Service worker'ları temizle
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistrations().then(function(registrations) {
for(let registration of registrations) {
registration.unregister();
}
});
}
alert('✅ Emergency cache temizleme tamamlandı!\n\nSayfa yeniden yükleniyor...');
// Force refresh
window.location.href = window.location.href + '?emergency_clear=' + Date.now();
}
};
// Cache refresh notification fonksiyonu
function showCacheRefreshNotification() {
const notification = document.createElement('div');
notification.style.cssText = `
position: fixed; top: 20px; right: 20px; z-index: 10000;
background: linear-gradient(45deg, #3B82F6, #1D4ED8); color: white;
padding: 20px 30px; border-radius: 12px; font-weight: bold;
box-shadow: 0 10px 25px rgba(59, 130, 246, 0.4);
border: 2px solid #60A5FA; max-width: 300px;
`;
notification.innerHTML = `
🔄
Cache Yenileniyor
Anasayfayı kontrol etmek için CTRL+SHIFT+R yapın veya
Anasayfayı Aç
🚨 Emergency Clear
`;
document.body.appendChild(notification);
setTimeout(() => notification?.remove(), 8000);
}
// EMERGENCY STATUS DISPLAY
function showEmergencyStatus(message, isRecovering) {
if (typeof isRecovering === 'undefined') isRecovering = false;
// Remove existing emergency status
const existing = document.getElementById('emergency-status');
if (existing) existing.remove();
const notification = document.createElement('div');
notification.id = 'emergency-status';
notification.style.cssText = `
position: fixed; top: 0; left: 0; width: 100%; z-index: 20000;
background: ${isRecovering ? 'linear-gradient(45deg, #F59E0B, #D97706)' : 'linear-gradient(45deg, #DC2626, #991B1B)'};
color: white; padding: 15px 20px; font-weight: bold; text-align: center;
box-shadow: 0 4px 15px rgba(0,0,0,0.5);
border-bottom: 3px solid ${isRecovering ? '#FBBF24' : '#F87171'};
`;
notification.innerHTML = `
${isRecovering ? '🔄' : '🚨'}
${message}
${isRecovering ? `
` : ''}
`;
document.body.appendChild(notification);
if (!isRecovering) {
setTimeout(() => notification?.remove(), 10000);
}
return notification;
}
// Security notification fonksiyonu
function showSecurityNotification(message, type = 'info') {
const notification = document.createElement('div');
let bgColor, borderColor;
switch(type) {
case 'success':
bgColor = 'linear-gradient(45deg, #10B981, #047857)';
borderColor = '#34D399';
break;
case 'warning':
bgColor = 'linear-gradient(45deg, #F59E0B, #D97706)';
borderColor = '#FBBF24';
break;
case 'error':
bgColor = 'linear-gradient(45deg, #DC2626, #991B1B)';
borderColor = '#F87171';
break;
default:
bgColor = 'linear-gradient(45deg, #3B82F6, #1D4ED8)';
borderColor = '#60A5FA';
}
notification.style.cssText = `
position: fixed; top: 20px; right: 20px; z-index: 10000;
background: ${bgColor}; color: white;
padding: 15px 25px; border-radius: 10px; font-weight: bold;
box-shadow: 0 10px 25px rgba(0,0,0,0.3);
border: 2px solid ${borderColor}; max-width: 300px;
`;
notification.innerHTML = `
${message}
`;
document.body.appendChild(notification);
setTimeout(() => notification?.remove(), 4000);
}
// CSRF token yenileme fonksiyonu - GÜÇLENDIRILDI
async function refreshCSRFToken() {
try {
console.log('🔄 Token yenileme başlatıldı...');
// Birden fazla deneme yap
for (let attempt = 1; attempt <= 3; attempt++) {
try {
const response = await fetch('api.php?action=get_csrf_token&t=' + Date.now() + '&attempt=' + attempt, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': '0'
}
});
console.log(`🔄 Token yenileme denemesi ${attempt}: HTTP ${response.status}`);
if (response.ok) {
const responseText = await response.text();
console.log('🔍 Token API response:', responseText.substring(0, 200));
let result;
try {
result = JSON.parse(responseText);
} catch (parseError) {
console.warn(`Deneme ${attempt}: JSON parse hatası, devam ediliyor...`);
continue;
}
if (result.csrf_token) {
const metaTag = document.querySelector('meta[name="csrf-token"]');
if (metaTag) {
const oldToken = metaTag.getAttribute('content');
metaTag.setAttribute('content', result.csrf_token);
console.log(`✅ CSRF token başarıyla yenilendi! (Deneme ${attempt})`);
console.log('🔑 Eski token:', oldToken?.substring(0, 10) + '...');
console.log('🔑 Yeni token:', result.csrf_token.substring(0, 10) + '...');
return true;
}
}
}
// Başarısızsa biraz bekle
if (attempt < 3) {
await new Promise(resolve => setTimeout(resolve, 500));
}
} catch (attemptError) {
console.warn(`Deneme ${attempt} başarısız:`, attemptError.message);
if (attempt < 3) {
await new Promise(resolve => setTimeout(resolve, 500));
}
}
}
throw new Error('3 denemede de token yenilenemedi');
} catch (error) {
console.error('❌ CSRF token yenileme tamamen başarısız:', error);
return false;
}
}
async function initialize() {
try {
// 🛡️ CRITICAL SECURITY FIX: gameCategories.cards Array Safety - Before any operations
console.log('🔧 Sistem güvenlik kontrolleri başlatılıyor...');
// Ensure gameCategories exists and cards is always an array
if (!window.currentConfig) {
window.currentConfig = {};
}
if (!window.currentConfig.gameCategories) {
console.log('🔧 gameCategories eksik - oluşturuluyor...');
window.currentConfig.gameCategories = {
title_red: 'EN POPÜLER',
title_white: ' OYUNLARIMIZ',
sub_title: 'Hemen Oynamaya Başla!',
description: 'Binlerce oyun arasından favori kategorini seç ve hemen oynamaya başla!',
cards: []
};
}
// CRITICAL: Ensure gameCategories.cards is ALWAYS an array
if (!window.currentConfig.gameCategories.cards || !Array.isArray(window.currentConfig.gameCategories.cards)) {
console.warn('⚠️ gameCategories.cards array güvenlik düzeltmesi uygulanıyor...');
window.currentConfig.gameCategories.cards = [];
}
console.log('✅ gameCategories.cards array güvenliği sağlandı:', Array.isArray(window.currentConfig.gameCategories.cards));
const urlParams = new URLSearchParams(window.location.search);
const isAdminPage = urlParams.get('admin') === 'true';
const isLoggedIn = false;
// CSRF token yenileme (sadece admin için) - GÜÇLENDIRILDI
if (isAdminPage && isLoggedIn) {
console.log('🔄 Admin panel başlatılıyor - Token yenileniyor...');
try {
const tokenSuccess = await refreshCSRFToken();
if (tokenSuccess) {
console.log('✅ Admin panel başlangıç token yenileme başarılı');
} else {
console.warn('⚠️ Admin panel başlangıç token yenileme başarısız - devam ediliyor');
}
} catch (tokenError) {
console.error('❌ Admin panel token yenileme hatası:', tokenError);
// Token refresh failed - continue anyway but warn user
setTimeout(() => {
alert('⚠️ Güvenlik token\'ı yenilenemedi.\n\nİlk kaydetme işleminizde sorun çıkarsa sayfayı yenileyin.');
}, 2000);
}
}
// Config yükleme
const config = await getSiteConfig();
if (!config || Object.keys(config).length === 0) {
return;
}
// 🛡️ Post-load security fix for gameCategories.cards
if (!config.gameCategories) {
console.log('🔧 Post-load: gameCategories eksik - oluşturuluyor...');
config.gameCategories = {
title_red: 'EN POPÜLER',
title_white: ' OYUNLARIMIZ',
sub_title: 'Hemen Oynamaya Başla!',
description: 'Binlerce oyun arasından favori kategorini seç ve hemen oynamaya başla!',
cards: []
};
}
if (!config.gameCategories.cards || !Array.isArray(config.gameCategories.cards)) {
console.warn('⚠️ Post-load: gameCategories.cards array değil - düzeltiliyor...');
config.gameCategories.cards = [];
}
console.log('✅ Post-load gameCategories.cards safety confirmed:', Array.isArray(config.gameCategories.cards));
// 🐦 TWITTER CREATOR FIX: Ensure seo.twitter structure in loaded config
if (!config.seo) {
config.seo = {};
}
if (!config.seo.twitter) {
config.seo.twitter = {};
}
console.log('🐦 Twitter Creator structure ensured - current value:', config.seo.twitter.creator);
// Sayfa türüne göre inizialize
if (isAdminPage) {
if (isLoggedIn) {
console.log('🎯 Admin panel başlatılıyor...');
// Config'i set et
currentConfig = config;
siteConfig = config;
window.currentConfig = config;
window.siteConfig = config;
console.log('📊 Config set for admin panel:', Object.keys(config));
// Public view'ı gizle
const publicView = document.getElementById('public-view');
if (publicView) {
publicView.style.display = 'none';
}
// Admin paneli göster - force display
const adminPanel = document.getElementById('admin-panel');
if (adminPanel) {
adminPanel.style.display = 'flex';
adminPanel.style.visibility = 'visible';
adminPanel.style.opacity = '1';
console.log('✅ Admin panel display set to flex');
} else {
console.error('❌ Admin panel element not found');
}
// Admin paneli başlat - emergency fallback ile
try {
console.log('🚀 initializeAdminPanel çağrılıyor...');
await initializeAdminPanel();
console.log('✅ Admin panel başarıyla başlatıldı');
} catch (adminError) {
console.error('❌ Admin panel başlatma hatası:', adminError);
// Emergency fallback: Manual admin panel initialization
console.log('🆘 Emergency admin panel fallback başlatılıyor...');
// Load emergency functions
loadEmergencyAdminFunctions();
// Manual section build
try {
buildAdminSection('dashboard');
console.log('✅ Emergency admin panel başlatıldı');
// Setup manual navigation
document.querySelectorAll('.admin-nav-item').forEach(item => {
item.addEventListener('click', function(e) {
e.preventDefault();
const section = this.getAttribute('data-section');
if (section) {
console.log('📍 Switching to section:', section);
showSection(section);
}
});
});
// Setup logout button
document.querySelector('[data-action="logout"]').addEventListener('click', function() {
window.location.href = 'index.php?logout=true';
});
} catch (emergencyError) {
console.error('❌ Emergency fallback failed:', emergencyError);
// Last resort: Show basic admin interface
document.getElementById('admin-sections').innerHTML = `
⚠️ Admin Panel Yükleme Hatası
Admin paneli düzgün yüklenemedi. Aşağıdaki seçenekleri deneyin:
🔄 Sayfayı Yenile
🔧 Debug Moduna Git
🚪 Çıkış Yap
🐛 Debug Bilgisi:
Config loaded: ${config ? 'YES' : 'NO'}
Config sections: ${config ? Object.keys(config).join(', ') : 'NONE'}
JavaScript functions: Check browser console for errors
`;
}
}
} else {
document.getElementById('admin-login').style.display = 'flex';
}
} else {
// Public sayfa render et
currentConfig = config;
siteConfig = config;
renderPublicPage(config);
}
} catch (error) {
// System initialization error - show basic error page
document.body.innerHTML = `
🚨 Sistem Hatası
Site başlatılırken bir hata oluştu.
🔄 Sayfayı Yenile
`;
}
}
// Test görsel ayarlama fonksiyonları
function setTestLogo(type) {
const testImages = {
header: {
src: '/img/kareaslogo.png',
alt: 'Kareasbet Test Logo'
},
hero: {
src: '/img/kareaslogo.png',
alt: 'Kareasbet Hero Test'
},
background: {
src: '/img/kareasbet-bannerone.jpg',
alt: 'Test Background'
},
gameCategories: {
src: '/img/bg-tokyobet.jpg',
alt: 'Game Categories Background'
}
};
if (!testImages[type]) return;
const inputs = {
header: {
src: 'header.logoSrc',
alt: 'header.logoAlt'
},
hero: {
src: 'hero.heroImage.src',
alt: 'hero.heroImage.alt'
},
background: {
src: 'background.mainBg',
alt: 'background.alt'
},
gameCategories: {
src: 'gameCategories.background.src',
alt: 'gameCategories.background.alt'
}
};
const config = inputs[type];
if (config) {
const srcInput = document.querySelector(`input[name="${config.src}"]`);
const altInput = document.querySelector(`input[name="${config.alt}"]`);
if (srcInput) {
srcInput.value = testImages[type].src;
// Trigger input change event to update any listeners
srcInput.dispatchEvent(new Event('input', { bubbles: true }));
}
if (altInput) {
altInput.value = testImages[type].alt;
altInput.dispatchEvent(new Event('input', { bubbles: true }));
}
showSecurityNotification(`✅ ${type.charAt(0).toUpperCase() + type.slice(1)} test görseli ayarlandı`, 'success');
// Update current config to reflect changes
if (type === 'header') {
if (!currentConfig.header) currentConfig.header = {};
currentConfig.header.logoSrc = testImages[type].src;
currentConfig.header.logoAlt = testImages[type].alt;
} else if (type === 'hero') {
if (!currentConfig.hero) currentConfig.hero = {};
if (!currentConfig.hero.heroImage) currentConfig.hero.heroImage = {};
currentConfig.hero.heroImage.src = testImages[type].src;
currentConfig.hero.heroImage.alt = testImages[type].alt;
} else if (type === 'background') {
if (!currentConfig.background) currentConfig.background = {};
currentConfig.background.mainBg = testImages[type].src;
currentConfig.background.alt = testImages[type].alt;
} else if (type === 'gameCategories') {
if (!currentConfig.gameCategories) currentConfig.gameCategories = {};
if (!currentConfig.gameCategories.background) currentConfig.gameCategories.background = {};
currentConfig.gameCategories.background.src = testImages[type].src;
currentConfig.gameCategories.background.alt = testImages[type].alt;
}
// Refresh the section to show preview
if (currentSection === 'visuals') {
buildAdminSection('visuals');
}
}
}
// Yeni görsel yönetim fonksiyonları
function resetAllImages() {
if (!confirm('⚠️ TÜM GÖRSELLERİ SIFIRLA\n\nTüm site görsellerini varsayılan değerlere döndürmek istediğinizden emin misiniz?\n\nBu işlem geri alınamaz!')) {
return;
}
console.log('🔄 Tüm görseller varsayılan değerlere sıfırlanıyor...');
// Reset header logo
const headerLogoSrc = document.querySelector('input[name="header.logoSrc"]');
const headerLogoAlt = document.querySelector('input[name="header.logoAlt"]');
if (headerLogoSrc) {
headerLogoSrc.value = '/img/kareaslogo.png';
headerLogoSrc.dispatchEvent(new Event('input', { bubbles: true }));
}
if (headerLogoAlt) {
headerLogoAlt.value = 'Kareasbet';
headerLogoAlt.dispatchEvent(new Event('input', { bubbles: true }));
}
// Reset hero image
const heroSrc = document.querySelector('input[name="hero.heroImage.src"]');
const heroAlt = document.querySelector('input[name="hero.heroImage.alt"]');
if (heroSrc) {
heroSrc.value = '/img/kareaslogo.png';
heroSrc.dispatchEvent(new Event('input', { bubbles: true }));
}
if (heroAlt) {
heroAlt.value = 'Kareasbet Logo';
heroAlt.dispatchEvent(new Event('input', { bubbles: true }));
}
// Reset background
const bgSrc = document.querySelector('input[name="background.mainBg"]');
const bgAlt = document.querySelector('input[name="background.alt"]');
if (bgSrc) {
bgSrc.value = '/img/kareasbet-bannerone.jpg';
bgSrc.dispatchEvent(new Event('input', { bubbles: true }));
}
if (bgAlt) {
bgAlt.value = 'Casino Background';
bgAlt.dispatchEvent(new Event('input', { bubbles: true }));
}
// Reset game categories background
const gameBgSrc = document.querySelector('input[name="gameCategories.background.src"]');
const gameBgAlt = document.querySelector('input[name="gameCategories.background.alt"]');
if (gameBgSrc) {
gameBgSrc.value = '/img/bg-tokyobet.jpg';
gameBgSrc.dispatchEvent(new Event('input', { bubbles: true }));
}
if (gameBgAlt) {
gameBgAlt.value = 'Games Background';
gameBgAlt.dispatchEvent(new Event('input', { bubbles: true }));
}
// Reset about background
const aboutBgSrc = document.querySelector('input[name="about.background.src"]');
const aboutBgAlt = document.querySelector('input[name="about.background.alt"]');
if (aboutBgSrc) {
aboutBgSrc.value = '/img/bg-tokyobet.jpg';
aboutBgSrc.dispatchEvent(new Event('input', { bubbles: true }));
}
if (aboutBgAlt) {
aboutBgAlt.value = 'About Background';
aboutBgAlt.dispatchEvent(new Event('input', { bubbles: true }));
}
// Reset SEO Open Graph image
const ogImageSrc = document.querySelector('input[name="seo.openGraph.image"]');
const ogImageAlt = document.querySelector('input[name="seo.openGraph.imageAlt"]');
if (ogImageSrc) {
ogImageSrc.value = '/img/kareasbet-social.jpg';
ogImageSrc.dispatchEvent(new Event('input', { bubbles: true }));
}
if (ogImageAlt) {
ogImageAlt.value = 'Kareasbet Sosyal Medya Görseli';
ogImageAlt.dispatchEvent(new Event('input', { bubbles: true }));
}
// Reset mobile app image
const mobileAppSrc = document.querySelector('input[name="mobileApp.image.src"]');
const mobileAppAlt = document.querySelector('input[name="mobileApp.image.alt"]');
if (mobileAppSrc) {
mobileAppSrc.value = '/img/kareaslogo.png';
mobileAppSrc.dispatchEvent(new Event('input', { bubbles: true }));
}
if (mobileAppAlt) {
mobileAppAlt.value = 'Mobil Uygulama';
mobileAppAlt.dispatchEvent(new Event('input', { bubbles: true }));
}
showSecurityNotification('🔄 Tüm görseller varsayılan değerlere sıfırlandı', 'warning');
// Refresh the section
if (currentSection === 'visuals') {
buildAdminSection('visuals');
}
}
function optimizeAllImages() {
showSecurityNotification('⚡ Görsel optimizasyonu başlatıldı...', 'info');
// Simulate optimization process
setTimeout(() => {
const imageInputs = document.querySelectorAll('input[type="url"][name*="src"], input[type="url"][name*="image"]');
let optimizedCount = 0;
let recommendationsCount = 0;
imageInputs.forEach(input => {
if (input.value && input.value.trim() !== '') {
// Check for WebP format
if (!input.value.includes('.webp')) {
recommendationsCount++;
}
// Check for proper alt text
const name = input.getAttribute('name');
const altName = name.replace('src', 'alt').replace('image', 'imageAlt');
const altInput = document.querySelector(`input[name="${altName}"]`);
if (!altInput || !altInput.value.trim()) {
recommendationsCount++;
}
optimizedCount++;
}
});
let message = `⚡ Analiz tamamlandı! ${optimizedCount} görsel tespit edildi.`;
if (recommendationsCount > 0) {
message += ` ${recommendationsCount} optimizasyon önerisi var (WebP formatı, alt text eksiklikleri).`;
}
showSecurityNotification(message, recommendationsCount > 0 ? 'warning' : 'success');
}, 2000);
}
function analyzeImages() {
showSecurityNotification('🔍 Görsel analizi başlatılıyor...', 'info');
setTimeout(() => {
// Count all image inputs
const allImageInputs = document.querySelectorAll('input[type="url"][name*="src"], input[type="url"][name*="image"]');
const filledImages = Array.from(allImageInputs).filter(input => input.value && input.value.trim() !== '');
const missingImages = allImageInputs.length - filledImages.length;
// Count alt text fields
const altInputs = document.querySelectorAll('input[name*="alt"], input[name*="Alt"]');
const filledAlts = Array.from(altInputs).filter(input => input.value && input.value.trim() !== '');
// Calculate SEO score
const seoScore = altInputs.length > 0 ? Math.round((filledAlts.length / altInputs.length) * 100) : 100;
// Update display
const imageCountEl = document.getElementById('image-count');
const missingCountEl = document.getElementById('missing-count');
const seoScoreEl = document.getElementById('seo-score');
if (imageCountEl) imageCountEl.textContent = filledImages.length;
if (missingCountEl) missingCountEl.textContent = missingImages;
if (seoScoreEl) seoScoreEl.textContent = seoScore + '%';
// Change colors based on status
if (missingCountEl) {
if (missingImages === 0) {
missingCountEl.className = 'text-2xl font-bold text-green-400';
} else if (missingImages <= 2) {
missingCountEl.className = 'text-2xl font-bold text-yellow-400';
} else {
missingCountEl.className = 'text-2xl font-bold text-red-400';
}
}
if (seoScoreEl) {
if (seoScore >= 90) {
seoScoreEl.className = 'text-2xl font-bold text-green-400';
} else if (seoScore >= 70) {
seoScoreEl.className = 'text-2xl font-bold text-yellow-400';
} else {
seoScoreEl.className = 'text-2xl font-bold text-red-400';
}
}
let statusMessage = '📊 Analiz tamamlandı! ';
if (missingImages === 0 && seoScore >= 90) {
statusMessage += 'Tüm görseller mükemmel durumda!';
} else if (missingImages > 0) {
statusMessage += `${missingImages} eksik görsel tespit edildi.`;
} else if (seoScore < 70) {
statusMessage += 'SEO için daha fazla alt text eklemelisiniz.';
} else {
statusMessage += 'Görseller genel olarak iyi durumda.';
}
showSecurityNotification(statusMessage, seoScore >= 80 && missingImages === 0 ? 'success' : 'warning');
}, 1500);
}
window.uploadImage = async function(fileInput, configPath) {
try {
console.log('📤 Görsel yükleme başlatılıyor...', configPath);
if (!fileInput.files || fileInput.files.length === 0) {
showSecurityNotification('❌ Lütfen bir dosya seçin', 'error');
return;
}
const file = fileInput.files[0];
const maxSize = 5 * 1024 * 1024;
if (file.size > maxSize) {
showSecurityNotification('❌ Dosya boyutu 5MB\'dan büyük olamaz', 'error');
fileInput.value = '';
return;
}
const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'];
if (!allowedTypes.includes(file.type)) {
showSecurityNotification('❌ Sadece JPEG, PNG, GIF ve WebP dosyaları desteklenir', 'error');
fileInput.value = '';
return;
}
const loadingNotification = document.createElement('div');
loadingNotification.style.cssText = `
position: fixed; top: 20px; right: 20px; z-index: 9999;
background: linear-gradient(45deg, #3B82F6, #1D4ED8); color: white;
padding: 15px 25px; border-radius: 10px; font-weight: bold;
box-shadow: 0 10px 25px rgba(59, 130, 246, 0.4);
border: 1px solid #60A5FA;
`;
loadingNotification.innerHTML = `
`;
document.body.appendChild(loadingNotification);
const formData = new FormData();
formData.append('image', file);
console.log('📡 Görsel upload.php\'ye gönderiliyor...');
const response = await fetch('upload.php', {
method: 'POST',
body: formData
});
const result = await response.json();
loadingNotification?.remove();
if (result.success && result.url) {
console.log('✅ Görsel başarıyla yüklendi:', result.url);
updateConfigPath(configPath, result.url);
updateImagePreview(configPath, result.url);
showSecurityNotification('✅ Görsel başarıyla yüklendi!', 'success');
const altPath = configPath.replace('.src', '.alt').replace('Src', 'Alt');
const altInput = document.querySelector(`input[name="${altPath}"]`);
if (altInput && (!altInput.value || altInput.value.trim() === '')) {
const defaultAlt = file.name.replace(/\.[^/.]+$/, "").replace(/[_-]/g, ' ');
altInput.value = defaultAlt;
updateConfigPath(altPath, defaultAlt);
}
if (confirm('✅ Görsel yüklendi!\n\n🔄 Değişiklikleri şimdi kaydetmek ister misiniz?\n\n(Bu işlem sitenizi hemen günceller)')) {
await saveChanges();
} else {
showSecurityNotification('💡 Değişiklikleri kaydetmeyi unutmayın!', 'warning');
}
} else {
console.error('❌ Görsel yükleme hatası:', result.error);
showSecurityNotification('❌ Yükleme hatası: ' + (result.error || 'Bilinmeyen hata'), 'error');
fileInput.value = ''; // Input'u temizle
}
} catch (error) {
console.error('❌ Upload error:', error);
showSecurityNotification('❌ Yükleme hatası: ' + error.message, 'error');
document.querySelector('[style*="Görsel yükleniyor"]')?.remove();
fileInput.value = '';
}
};
function updateConfigPath(path, value) {
console.log('🔧 Config path güncelleniyor:', path, '=', value);
if (!currentConfig) {
currentConfig = {};
}
const pathParts = path.split('.');
let current = currentConfig;
for (let i = 0; i < pathParts.length - 1; i++) {
const part = pathParts[i];
if (/^\d+$/.test(part)) {
const arrayIndex = parseInt(part);
if (!Array.isArray(current)) {
current = [];
}
if (!current[arrayIndex]) {
current[arrayIndex] = {};
}
current = current[arrayIndex];
} else {
if (!current[part]) {
current[part] = {};
}
current = current[part];
}
}
const finalPart = pathParts[pathParts.length - 1];
if (/^\d+$/.test(finalPart)) {
const arrayIndex = parseInt(finalPart);
if (!Array.isArray(current)) {
current = [];
}
current[arrayIndex] = value;
} else {
current[finalPart] = value;
}
const input = document.querySelector(`input[name="${path}"]`);
if (input) {
input.value = value;
input.dispatchEvent(new Event('input', { bubbles: true }));
}
console.log('✅ Config path güncellendi:', path);
}
function updateImagePreview(configPath, imageUrl) {
console.log('🖼️ Görsel önizleme güncelleniyor:', configPath, imageUrl);
// Arka plan görselleri için önizleme güncelleme
if (configPath.includes('background.mainBg')) {
// Ana sayfa arka planı önizleme güncelleme
const bgPreview = document.querySelector('[style*="background-image"][style*="kareasbet-bannerone"], [style*="background-image"][style*="mainBg"]');
if (bgPreview) {
bgPreview.style.backgroundImage = `url('${imageUrl}?t=${Date.now()}')`;
console.log('✅ Ana sayfa arka plan önizlemesi güncellendi');
}
// Eğer visuals bölümündeysek, bölümü yeniden yükle
if (currentSection === 'visuals') {
setTimeout(() => {
buildAdminSection('visuals');
console.log('🔄 Visuals bölümü yeniden yüklendi - Ana sayfa arka planı');
}, 500);
}
return;
}
if (configPath.includes('gameCategories.background.src')) {
// Oyun kategorileri arka planı önizleme güncelleme
const gamesBgPreview = document.querySelector('[style*="background-image"][style*="bg-tokyobet"], [style*="background-image"][style*="gameCategories"]');
if (gamesBgPreview) {
gamesBgPreview.style.backgroundImage = `linear-gradient(rgba(0,0,0,0.6), rgba(0,0,0,0.6)), url('${imageUrl}?t=${Date.now()}')`;
console.log('✅ Oyun kategorileri arka plan önizlemesi güncellendi');
}
// Eğer visuals bölümündeysek, bölümü yeniden yükle
if (currentSection === 'visuals') {
setTimeout(() => {
buildAdminSection('visuals');
console.log('🔄 Visuals bölümü yeniden yüklendi - Oyun kategorileri arka planı');
}, 500);
}
return;
}
if (configPath.includes('about.background.src')) {
// Hakkımızda bölümü arka planı önizleme güncelleme
const aboutBgPreview = document.querySelector('[style*="background-image"][style*="about"]');
if (aboutBgPreview) {
aboutBgPreview.style.backgroundImage = `linear-gradient(rgba(0,0,0,0.6), rgba(0,0,0,0.6)), url('${imageUrl}?t=${Date.now()}')`;
console.log('✅ Hakkımızda bölümü arka plan önizlemesi güncellendi');
}
// Eğer visuals bölümündeysek, bölümü yeniden yükle
if (currentSection === 'visuals') {
setTimeout(() => {
buildAdminSection('visuals');
console.log('🔄 Visuals bölümü yeniden yüklendi - Hakkımızda arka planı');
}, 500);
}
return;
}
// Diğer görsel türleri için mevcut önizleme sistemi
let previewSelector = '';
if (configPath.includes('header.logoSrc')) {
previewSelector = '[data-preview="header-logo"]';
} else if (configPath.includes('hero.heroImage.src')) {
previewSelector = '[data-preview="hero-image"]';
} else if (configPath.includes('mobileApp.image.src')) {
previewSelector = '[data-preview="mobile-app-image"]';
} else if (configPath.includes('seo.openGraph.image')) {
previewSelector = '[data-preview="og-image"]';
} else if (configPath.includes('seo.favicon.')) {
if (currentSection === 'visuals') {
setTimeout(() => {
buildAdminSection('visuals');
console.log('🔄 Visuals bölümü yeniden yüklendi - Favicon');
}, 500);
}
console.log('✅ Favicon önizleme yeniden yüklendi');
return;
}
if (previewSelector) {
const previewElement = document.querySelector(previewSelector);
if (previewElement) {
if (previewElement.tagName === 'IMG') {
previewElement.src = imageUrl + '?t=' + Date.now();
} else {
previewElement.style.backgroundImage = `url('${imageUrl}?t=${Date.now()}')`;
}
console.log('✅ Önizleme güncellendi:', previewSelector);
}
}
// Tüm benzer görselleri güncelle
const allImages = document.querySelectorAll('img[src*="' + imageUrl.split('/').pop() + '"]');
allImages.forEach(img => {
img.src = imageUrl + '?t=' + Date.now();
});
const allBgElements = document.querySelectorAll('[style*="background-image"]');
allBgElements.forEach(el => {
const currentBg = el.style.backgroundImage;
if (currentBg && currentBg.includes(imageUrl.split('/').pop())) {
el.style.backgroundImage = `url('${imageUrl}?t=${Date.now()}')`;
}
});
console.log('🖼️ Tüm görsel önizlemeleri güncellendi:', configPath);
}
// Enhanced Config Save System - Veri Kaybı Önleyici Sistem
window.saveChanges = async function() {
try {
console.log('💾 Gelişmiş kaydetme sistemi başlatılıyor...');
// Step 1: Backup current config before changes
const configBackup = JSON.parse(JSON.stringify(currentConfig || {}));
console.log('📋 Current config backed up with sections:', Object.keys(configBackup));
// Step 2: Validate current session and config
if (!currentConfig || Object.keys(currentConfig).length === 0) {
console.warn('⚠️ Current config is empty, attempting to reload...');
try {
const freshConfig = await getSiteConfig();
if (freshConfig && Object.keys(freshConfig).length > 0) {
currentConfig = freshConfig;
window.currentConfig = freshConfig;
console.log('✅ Fresh config loaded with sections:', Object.keys(freshConfig));
} else {
throw new Error('Fresh config is also empty');
}
} catch (reloadError) {
console.error('❌ Could not reload config:', reloadError);
alert('❌ Yapılandırma yüklenemedi. Lütfen sayfayı yenileyin.');
return;
}
}
// Step 3: Show progress overlay
const loadingOverlay = document.createElement('div');
loadingOverlay.id = 'save-loading';
loadingOverlay.style.cssText = `
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background: linear-gradient(45deg, rgba(0,0,0,0.9), rgba(20,20,20,0.9));
z-index: 9999; display: flex; align-items: center; justify-content: center; color: white;
backdrop-filter: blur(5px);
`;
loadingOverlay.innerHTML = `
💾
Kaydetme İşlemi
Verileriniz güvenli şekilde kaydediliyor...
Başlatılıyor...
`;
document.body.appendChild(loadingOverlay);
const progressBar = document.getElementById('save-progress-bar');
const statusDiv = document.getElementById('save-status');
// Step 4: Improved form data collection with deep merge support
statusDiv.textContent = 'Form verileri toplanıyor...';
progressBar.style.width = '20%';
console.log('🔍 Form verilerini toplama başlangıcı...');
const formData = {};
const inputs = document.querySelectorAll('#admin-sections input, #admin-sections textarea, #admin-sections select');
console.log(`📝 ${inputs.length} form elementi bulundu`);
// Enhanced input processing with type safety
inputs.forEach((input, index) => {
if (!input.name || input.name.trim() === '') return;
let value;
const inputType = input.type;
const inputName = input.name;
try {
// Type-safe value extraction
switch (inputType) {
case 'checkbox':
value = input.checked;
break;
case 'number':
case 'range':
const numValue = parseFloat(input.value);
value = isNaN(numValue) ? 0 : numValue;
break;
case 'color':
value = input.value || '#000000';
break;
case 'radio':
if (input.checked) {
value = input.value;
} else {
return; // Skip unchecked radio buttons
}
break;
default:
value = input.value ? input.value.trim() : '';
}
// Build nested object structure with array support
const pathParts = inputName.split('.');
let current = formData;
for (let i = 0; i < pathParts.length - 1; i++) {
const part = pathParts[i];
// Handle array indices
if (/^\d+$/.test(part)) {
const arrayIndex = parseInt(part);
if (!Array.isArray(current)) {
current = [];
}
if (!current[arrayIndex]) {
current[arrayIndex] = {};
}
current = current[arrayIndex];
} else {
if (!current[part]) {
current[part] = {};
}
current = current[part];
}
}
const finalPart = pathParts[pathParts.length - 1];
if (/^\d+$/.test(finalPart)) {
const arrayIndex = parseInt(finalPart);
if (!Array.isArray(current)) {
current = [];
}
current[arrayIndex] = value;
} else {
current[finalPart] = value;
}
console.log(`✅ Processed: ${inputName} = ${typeof value === 'object' ? JSON.stringify(value) : value}`);
} catch (error) {
console.warn(`⚠️ Error processing input ${inputName}:`, error);
}
});
// Step 5: Smart config merging to prevent data loss
statusDiv.textContent = 'Veriler birleştiriliyor...';
progressBar.style.width = '40%';
console.log('🔄 Smart config merge başlatılıyor...');
console.log('📊 Form data sections:', Object.keys(formData));
console.log('📊 Current config sections:', Object.keys(currentConfig));
// Deep merge function to preserve existing data
function deepMerge(target, source) {
const result = JSON.parse(JSON.stringify(target)); // Clone target
for (const key in source) {
if (source[key] !== null && source[key] !== undefined) {
if (typeof source[key] === 'object' && !Array.isArray(source[key]) &&
typeof result[key] === 'object' && !Array.isArray(result[key])) {
// Recursively merge objects
result[key] = deepMerge(result[key] || {}, source[key]);
} else {
// Direct assignment for primitives and arrays
result[key] = source[key];
}
}
}
return result;
}
// Create final configuration
const finalConfig = deepMerge(currentConfig, formData);
console.log('📋 Final config sections:', Object.keys(finalConfig));
console.log('💾 Final config size:', JSON.stringify(finalConfig).length, 'characters');
// Step 6: Validation before save
statusDiv.textContent = 'Veriler doğrulanıyor...';
progressBar.style.width = '60%';
// Essential sections check
const essentialSections = ['header', 'hero', 'footer', 'design'];
const missingSections = essentialSections.filter(section => !finalConfig[section]);
if (missingSections.length > 0) {
console.warn('⚠️ Missing essential sections:', missingSections);
// Restore from backup
missingSections.forEach(section => {
if (configBackup[section]) {
finalConfig[section] = configBackup[section];
console.log(`🔄 Restored ${section} from backup`);
}
});
}
// Step 7: API save with enhanced error handling
statusDiv.textContent = 'Sunucuya gönderiliyor...';
progressBar.style.width = '80%';
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
if (!csrfToken) {
throw new Error('CSRF token bulunamadı - Güvenlik hatası');
}
console.log('📡 API save başlatılıyor...');
const response = await fetch('api.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken,
'X-Security-Level': 'admin',
'X-Request-Time': Date.now().toString()
},
body: JSON.stringify(finalConfig)
});
let result;
try {
result = await response.json();
} catch (jsonError) {
console.error('❌ JSON parse error:', jsonError);
throw new Error('Sunucu yanıtı geçersiz - Lütfen tekrar deneyin');
}
if (!response.ok) {
console.error('❌ HTTP error:', response.status, result);
throw new Error(result.error || `HTTP Hatası ${response.status}`);
}
// Step 8: Success handling
statusDiv.textContent = 'Tamamlanıyor...';
progressBar.style.width = '100%';
// Update global config
currentConfig = finalConfig;
window.currentConfig = finalConfig;
window.siteConfig = finalConfig;
console.log('✅ Config saved successfully');
console.log('🔄 Updating page display...');
// Update public page display if not in admin mode
setTimeout(() => {
if (typeof renderPublicPage === 'function') {
renderPublicPage(finalConfig);
}
}, 500);
// Show success message
setTimeout(() => {
loadingOverlay?.remove();
// Success notification
const successNotification = document.createElement('div');
successNotification.style.cssText = `
position: fixed; top: 20px; right: 20px; z-index: 9999;
background: linear-gradient(135deg, #10B981, #047857); color: white;
padding: 20px 30px; border-radius: 10px; font-weight: bold;
box-shadow: 0 10px 25px rgba(16, 185, 129, 0.4);
border: 1px solid #34D399;
`;
successNotification.innerHTML = `
✅
Başarıyla Kaydedildi!
Tüm değişiklikler uygulandı
`;
document.body.appendChild(successNotification);
setTimeout(() => successNotification?.remove(), 4000);
}, 1000);
} catch (error) {
console.error('❌ Save error:', error);
// Remove loading overlay
document.getElementById('save-loading')?.remove();
// Show error notification
const errorNotification = document.createElement('div');
errorNotification.style.cssText = `
position: fixed; top: 20px; right: 20px; z-index: 9999;
background: linear-gradient(45deg, #DC2626, #991B1B); color: white;
padding: 20px 30px; border-radius: 10px; font-weight: bold;
box-shadow: 0 10px 25px rgba(220, 38, 38, 0.4);
border: 1px solid #F87171;
`;
errorNotification.innerHTML = `
❌
Kaydetme Hatası
${error.message}
`;
document.body.appendChild(errorNotification);
setTimeout(() => errorNotification?.remove(), 6000);
}
};
initialize();
});
-->