113 lines
7.2 KiB
React
113 lines
7.2 KiB
React
import {useApp} from '../../context/AppContext';
|
||
import {getToken} from '../../services/auth';
|
||
import React, { useEffect, useState, useRef } from 'react';
|
||
import { Send, CheckCircle2, AlertTriangle, Loader2, Unplug } from 'lucide-react';
|
||
import { telegramDurum, telegramBagla, telegramTest, telegramSil } from '../../services/account';
|
||
|
||
/**
|
||
* Telegram bildirim bağlantısı — kullanıcı kendi kurar.
|
||
* Bot tokenı sunucuda (TELEGRAM_BOT_TOKEN); kullanıcı 6 haneli kodu bota yazar,
|
||
* "Doğrula" deyince sunucu kodu görüp sohbeti hesaba bağlar. Token bizden geçmez.
|
||
*/
|
||
const kodUret = () => String(Math.floor(100000 + Math.random() * 900000));
|
||
|
||
export const TelegramBaglanti = () => {
|
||
const {authUser,isAdmin}=useApp();
|
||
return <TelegramPanel key={`${authUser?.email}:${getToken()}`} isAdmin={isAdmin}/>;
|
||
};
|
||
const TelegramPanel = ({isAdmin}) => {
|
||
const [d, setD] = useState(null);
|
||
const [kod] = useState(kodUret);
|
||
const [busy, setBusy] = useState(null);
|
||
const [mesaj, setMesaj] = useState(null);
|
||
|
||
const alive=useRef(true),locked=useRef(false);
|
||
const yenile = async () => {
|
||
const data=await telegramDurum();
|
||
if(typeof data.bagli!=='boolean'||typeof data.yapilandirilmis!=='boolean')throw new Error('Telegram bağlantı durumu doğrulanamadı.');
|
||
if(alive.current)setD(data);
|
||
};
|
||
const calistir = async (ad, fn, basari) => {
|
||
if(locked.current)return;locked.current=true;
|
||
setBusy(ad);setMesaj(null);
|
||
try {await fn();if(!alive.current)return;if(ad!=='load')await yenile();if(alive.current&&basari)setMesaj({tur:'ok',metin:basari});}
|
||
catch(e){if(alive.current)setMesaj({tur:'hata',metin:e.message});}
|
||
finally{locked.current=false;if(alive.current)setBusy(null);}
|
||
};
|
||
useEffect(()=>{alive.current=true;void calistir('load',yenile);return()=>{alive.current=false;};},[]);
|
||
|
||
if(!d)return <section className="bg-white border rounded-xl p-5 space-y-3" aria-label="Telegram bağlantı durumu">
|
||
<h3 className="font-bold text-sm">Telegram Bildirimi</h3>
|
||
{busy&&<p role="status" className="text-sm">Bağlantı durumu yükleniyor…</p>}
|
||
{mesaj&&<p role="alert" className="text-red-700 text-sm">{mesaj.metin}</p>}
|
||
<button disabled={!!busy} onClick={()=>calistir('load',yenile)} className="border rounded p-2 text-sm">Telegram durumunu yeniden dene</button>
|
||
</section>;
|
||
|
||
return (
|
||
<div className="bg-white p-6 rounded-2xl border border-slate-200 shadow-xs space-y-4">
|
||
<div className="flex items-center justify-between border-b border-slate-100 pb-3">
|
||
<h3 className="font-extrabold text-sm text-slate-900 flex items-center gap-2">
|
||
<Send className="w-4 h-4 text-sky-600" /> Telegram Bildirimi
|
||
</h3>
|
||
{d.bagli
|
||
? <span className="bg-emerald-100 text-emerald-800 font-extrabold text-[10px] px-2 py-0.5 rounded-full">bağlı{d.ad ? ` · ${d.ad}` : ''}</span>
|
||
: <span className="bg-slate-100 text-slate-600 font-extrabold text-[10px] px-2 py-0.5 rounded-full">bağlı değil</span>}
|
||
</div>
|
||
|
||
<p className="text-xs text-slate-600 leading-relaxed">
|
||
Telegram bağlantısı ve ilgili bildirim hizmetleri etkinse ihale özetleri bu kanaldan gönderilebilir. Gönderim, okunma veya her kaynak değişikliğinin yakalanması garanti edilmez.
|
||
</p>
|
||
|
||
{!d.yapilandirilmis ? (
|
||
<div className="bg-amber-50 border border-amber-200 rounded-xl p-4 space-y-2 text-xs text-amber-900 leading-relaxed">
|
||
{isAdmin ? <><p className="font-bold">Sunucuda Telegram botu henüz tanımlı değil. Kurulum (yönetici, bir kez):</p>
|
||
<ol className="list-decimal pl-5 space-y-1">
|
||
<li>Telegram'da <strong>@BotFather</strong>'a yazın: <code className="bg-amber-100 px-1 rounded">/newbot</code> → bir ad ve <code className="bg-amber-100 px-1 rounded">…bot</code> ile biten kullanıcı adı verin.</li>
|
||
<li>BotFather'ın verdiği tokenı Coolify → ihaleist → Environment'a <code className="bg-amber-100 px-1 rounded">TELEGRAM_BOT_TOKEN</code> olarak ekleyin, Redeploy.</li>
|
||
<li>Bu sayfa yeniden açıldığında aşağıdaki bağlama adımları görünür.</li>
|
||
</ol>
|
||
<p className="text-[11px] text-amber-800">Token yalnızca sunucuda durur; uygulamaya girilmez.</p></> : <p>Telegram bildirim hizmeti henüz etkin değil. Kurulum için yöneticinizle görüşün.</p>}
|
||
</div>
|
||
) : d.bagli ? (
|
||
<div className="flex flex-wrap gap-2">
|
||
<button onClick={() => calistir('test', telegramTest, 'Test mesajı gönderildi — Telegram\'ı kontrol edin.')} disabled={!!busy}
|
||
className="bg-sky-600 hover:bg-sky-500 disabled:opacity-40 text-white font-bold text-xs px-4 py-2 rounded-lg flex items-center gap-1.5">
|
||
{busy === 'test' ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Send className="w-3.5 h-3.5" />} Test mesajı gönder
|
||
</button>
|
||
<button onClick={() => calistir('sil', telegramSil, 'Telegram bağlantısı kaldırıldı.')} disabled={!!busy}
|
||
className="bg-white hover:bg-slate-50 disabled:opacity-40 text-slate-700 font-bold text-xs px-4 py-2 rounded-lg border border-slate-300 flex items-center gap-1.5">
|
||
<Unplug className="w-3.5 h-3.5" /> Bağlantıyı kaldır
|
||
</button>
|
||
</div>
|
||
) : (
|
||
<div className="bg-sky-50 border border-sky-200 rounded-xl p-4 space-y-3 text-xs text-slate-800">
|
||
<p className="font-bold">Bağlamak için 3 adım:</p>
|
||
<ol className="list-decimal pl-5 space-y-1.5 leading-relaxed">
|
||
<li>
|
||
Telegram'da botu açın:{' '}
|
||
{d.bot
|
||
? <a href={`https://t.me/${d.bot}`} target="_blank" rel="noopener noreferrer" className="font-bold text-sky-700 underline">@{d.bot}</a>
|
||
: <span className="font-bold">(bot adı alınamadı — yöneticiye sorun)</span>}
|
||
{' '}ve <strong>Başlat</strong>'a basın.
|
||
</li>
|
||
<li>Bota şu kodu yazıp gönderin: <code className="bg-white border border-sky-300 px-2 py-0.5 rounded font-mono text-sm font-black tracking-widest">{kod}</code></li>
|
||
<li>Sonra buraya dönüp <strong>Doğrula</strong>'ya basın.</li>
|
||
</ol>
|
||
<button onClick={() => calistir('bagla', () => telegramBagla(kod), 'Telegram bağlantısı kaydedildi.')} disabled={!!busy}
|
||
className="bg-sky-600 hover:bg-sky-500 disabled:opacity-40 text-white font-bold text-xs px-5 py-2 rounded-lg flex items-center gap-1.5">
|
||
{busy === 'bagla' ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <CheckCircle2 className="w-3.5 h-3.5" />} Doğrula
|
||
</button>
|
||
</div>
|
||
)}
|
||
|
||
<button disabled={!!busy} onClick={()=>calistir('load',yenile)} className="border rounded p-2 text-xs">Telegram durumunu yenile</button>
|
||
{mesaj && (
|
||
<div role={mesaj.tur === 'ok' ? 'status' : 'alert'} className={`rounded-lg p-3 flex gap-2 text-xs ${mesaj.tur === 'ok' ? 'bg-emerald-50 border border-emerald-200 text-emerald-900' : 'bg-red-50 border border-red-200 text-red-800'}`}>
|
||
{mesaj.tur === 'ok' ? <CheckCircle2 className="w-4 h-4 shrink-0" /> : <AlertTriangle className="w-4 h-4 shrink-0" />}
|
||
<span>{mesaj.metin}</span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
};
|