import {DeliveryQueue} from './DeliveryQueue'; import React, { useState, useEffect } from 'react'; import { useApp } from '../../context/AppContext'; import { Smartphone, Wifi, WifiOff, Download, Bell, CheckCircle2, Moon, Mail, Send } from 'lucide-react'; import confetti from 'canvas-confetti'; import { getToken } from '../../services/auth'; import { NotifySubscriptions } from './NotifySubscriptions'; export const PwaSettings = () => { const { userProfile, authUser, tenders, reminderSettings, setReminderSettings, requestPushPermission, notify, isQuietNow } = useApp(); // Gerçek Cache API sayımı — sahte "102 ihale önbellekte" yerine const [onbellekSayisi, setOnbellekSayisi] = useState(null); const [onbellekAdi, setOnbellekAdi] = useState(''); const [cacheLoading, setCacheLoading] = useState(false); const [cacheError, setCacheError] = useState(null); const [online, setOnline] = useState(navigator.onLine); const refreshCacheStatus = async () => { setCacheLoading(true); setCacheError(null); try { if (!('caches' in window)) throw new Error('Bu tarayıcı uygulama önbelleğini desteklemiyor.'); const adlar = (await caches.keys()).filter(name => name.startsWith('ihaleist-')); let toplam = 0; for (const ad of adlar) toplam += (await (await caches.open(ad)).keys()).length; setOnbellekSayisi(toplam); setOnbellekAdi(adlar.join(', ')); } catch (error) { setCacheError(error.message); setOnbellekSayisi(null); } finally { setCacheLoading(false); } }; useEffect(() => { refreshCacheStatus(); }, []); useEffect(() => { const changed = () => setOnline(navigator.onLine); window.addEventListener('online', changed); window.addEventListener('offline', changed); return () => { window.removeEventListener('online', changed); window.removeEventListener('offline', changed); }; }, []); const [installed, setInstalled] = useState(false); const [permission, setPermission] = useState(typeof Notification !== 'undefined' ? Notification.permission : 'unsupported'); // E-posta (Resend) durumu + test gönderimi const [emailCfg, setEmailCfg] = useState(null); // null=bilinmiyor, true/false const [emailSending, setEmailSending] = useState(false); const [emailResult, setEmailResult] = useState(null); useEffect(() => { fetch('/api/notify/email/config') .then((r) => r.json()) .then((d) => setEmailCfg(Boolean(d.configured))) .catch(() => setEmailCfg(false)); }, []); const sendTestEmail = async () => { setEmailSending(true); setEmailResult(null); try { const yeniler = tenders.filter((t) => t.isYeni).slice(0, 15); const res = await fetch('/api/notify/email/test', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${getToken()}` }, body: JSON.stringify({ subject: 'İhaleist — bildirim testi', tenders: yeniler }), }); const data = await res.json(); if (data.success) { setEmailResult({ ok: true, msg: `E-posta gönderildi → ${data.to}` }); notify('E-posta gönderildi', `Test e-postası ${data.to} adresine iletildi.`); } else { setEmailResult({ ok: false, msg: data.error || 'Gönderilemedi' }); } } catch (e) { setEmailResult({ ok: false, msg: e.message }); } finally { setEmailSending(false); } }; const handleEnablePush = async () => { const p = await requestPushPermission(); setPermission(p); if (p === 'granted') { setReminderSettings((s) => ({ ...s, pushEnabled: true })); notify('Bildirimler açıldı', 'Yeni ihale ve son tarih uyarıları buradan gelecek.'); confetti({ particleCount: 50 }); } }; const setQuiet = (patch) => setReminderSettings((s) => ({ ...s, ...patch })); // Gerçek PWA kurulumu: tarayıcı beforeinstallprompt verirse yerel diyalog; // zaten standalone açıldıysa "yüklü"; iOS Safari'de olay yok → yol tarifi. const [kurulumOlayi, setKurulumOlayi] = useState(null); const [iosIpucu, setIosIpucu] = useState(false); useEffect(() => { const standalone = window.matchMedia?.('(display-mode: standalone)')?.matches || window.navigator.standalone === true; if (standalone) setInstalled(true); const yakala = (e) => { e.preventDefault(); setKurulumOlayi(e); }; const kuruldu = () => { setInstalled(true); setKurulumOlayi(null); }; window.addEventListener('beforeinstallprompt', yakala); window.addEventListener('appinstalled', kuruldu); return () => { window.removeEventListener('beforeinstallprompt', yakala); window.removeEventListener('appinstalled', kuruldu); }; }, []); const handleInstallPwa = async () => { if (kurulumOlayi) { kurulumOlayi.prompt(); const { outcome } = await kurulumOlayi.userChoice.catch(() => ({ outcome: 'dismissed' })); if (outcome === 'accepted') setInstalled(true); setKurulumOlayi(null); return; } setIosIpucu(true); // olay yoksa (iOS / zaten yüklü / desteklenmiyor) yol tarifi göster }; return (
Uygulama kabuğu önbellekten açılabilir. İhale güncelleme, belge erişimi ve hazırlık kaydı için internet bağlantısı gerekir.
İhale Kayıtları (bellekte): {tenders.length.toLocaleString('tr-TR')} ihale
Önbelleğe alınmış istek: {onbellekSayisi == null ? '—' : `${onbellekSayisi} kayıt`}
Uygulama sürümü önbelleği: {onbellekAdi || '—'}
{cacheError}
}Bağlantı durumu sunucuya erişimi garanti etmez. Çevrimdışı değişiklikler otomatik gönderim kuyruğuna alınmaz; kayıt sonucunu kontrol edin.
Tarayıcı bildirimlerine izin verin; yeni ihale ve son tarih uyarıları gerçek bildirim olarak gelir.
{permission !== 'granted' ? ( ) : ( )} {/* Sessiz saatler — gerçek */}{isQuietNow() ? '🔕 Şu an sessiz saatte — tarayıcı bildirimi gösterilmez, uyarılar listeye eklenir.' : '🔔 Şu an aktif — bildirimler gösterilir.'}
)}{emailCfg === false ? 'E-posta göndermek için sunucuya RESEND_API_KEY ekleyin (Coolify → Environment). Ayrıca gönderen domainini Resend’de DNS ile doğrulayın.' : 'Takip kriterlerinize uyan ihaleler, hesabınızın e-posta adresine özet olarak gönderilir. Aşağıdan kendinize test gönderebilirsiniz.'}
{emailResult && ({emailResult.ok ? '✓ ' : '⚠ '}{emailResult.msg}
)}İhaleist'i iOS, Android, Windows veya Mac cihazınıza bir tıklama ile uygulama olarak kurun.
{iosIpucu && !installed && (iPhone / iPad (Safari): alttaki Paylaş simgesi → Ana Ekrana Ekle.
Android (Chrome): sağ üst ⋮ menü → Uygulamayı yükle / Ana ekrana ekle.
Masaüstü (Chrome/Edge): adres çubuğunun sağındaki yükleme simgesi.