Show Telegram status errors and keep setup instructions admin-only

This commit is contained in:
2026-09-06 13:42:25 +03:00
parent 2f86c6d690
commit 44c9809deb
4 changed files with 59 additions and 16 deletions
+32 -16
View File
@@ -1,4 +1,6 @@
import React, { useEffect, useState } from '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';
@@ -10,22 +12,36 @@ import { telegramDurum, telegramBagla, telegramTest, telegramSil } from '../../s
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 yenile = () => telegramDurum().then(setD).catch((e) => setMesaj({ tur: 'hata', metin: e.message }));
useEffect(() => { yenile(); }, []);
const calistir = async (ad, fn, basari) => {
setBusy(ad); setMesaj(null);
try { await fn(); setMesaj({ tur: 'ok', metin: basari }); await yenile(); }
catch (e) { setMesaj({ tur: 'hata', metin: e.message }); }
finally { setBusy(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 null;
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">
@@ -39,19 +55,18 @@ export const TelegramBaglanti = () => {
</div>
<p className="text-xs text-slate-600 leading-relaxed">
Yeni ihale özetleri, takipteki ihalede <strong>zeyilname/düzeltme ilanı</strong> ve <strong>sonuç</strong>
("X firması Y'ye aldı, %Z kırım") e-postanın yanında Telegram'a da gelir.
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">
<p className="font-bold">Sunucuda Telegram botu henüz tanımlı değil. Kurulum (yönetici, bir kez):</p>
{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 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">
@@ -78,15 +93,16 @@ export const TelegramBaglanti = () => {
<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), 'Bağlandı! Telegram\'a onay mesajı gönderildi.')} disabled={!!busy}
<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 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'}`}>
<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>