import { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useQuery } from '@tanstack/react-query'; import { brandingApi, type TelegramWidgetConfig } from '../api/branding'; import { useAuthStore } from '../store/auth'; import { useNavigate } from 'react-router'; interface TelegramLoginButtonProps { referralCode?: string; } export default function TelegramLoginButton({ referralCode }: TelegramLoginButtonProps) { const { t } = useTranslation(); const navigate = useNavigate(); const containerRef = useRef(null); const [oidcLoading, setOidcLoading] = useState(false); const [oidcError, setOidcError] = useState(''); const loginWithTelegramOIDC = useAuthStore((s) => s.loginWithTelegramOIDC); const { data: widgetConfig } = useQuery({ queryKey: ['telegram-widget-config'], queryFn: brandingApi.getTelegramWidgetConfig, staleTime: 60000, }); const botUsername = widgetConfig?.bot_username || import.meta.env.VITE_TELEGRAM_BOT_USERNAME || ''; const isOIDC = Boolean(widgetConfig?.oidc_enabled && widgetConfig?.oidc_client_id); // OIDC callback handler (ref pattern to avoid stale closures and unnecessary re-inits) const handleOIDCCallbackRef = useRef<(data: { id_token?: string; error?: string }) => void>(undefined); handleOIDCCallbackRef.current = async (data: { id_token?: string; error?: string }) => { if (data.error || !data.id_token) { setOidcError(data.error || t('auth.loginFailed')); setOidcLoading(false); return; } try { setOidcLoading(true); setOidcError(''); await loginWithTelegramOIDC(data.id_token); navigate('/'); } catch (err: unknown) { let message = t('common.error'); if (err && typeof err === 'object' && 'response' in err) { const resp = (err as { response?: { data?: { detail?: string } } }).response; if (resp?.data?.detail) message = resp.data.detail; } setOidcError(message); } finally { setOidcLoading(false); } }; // Load OIDC script and init useEffect(() => { if (!isOIDC || !widgetConfig?.oidc_client_id) return; const scriptId = 'telegram-login-oidc-script'; let script = document.getElementById(scriptId) as HTMLScriptElement | null; const initTelegramLogin = () => { if (window.Telegram?.Login) { window.Telegram.Login.init( { client_id: Number(widgetConfig.oidc_client_id) || widgetConfig.oidc_client_id, request_access: widgetConfig.request_access ? ['write'] : undefined, lang: document.documentElement.lang || 'en', }, (data) => handleOIDCCallbackRef.current?.(data), ); } }; if (!script) { script = document.createElement('script'); script.id = scriptId; script.src = 'https://oauth.telegram.org/js/telegram-login.js?3'; script.async = true; script.onload = initTelegramLogin; document.head.appendChild(script); } else { // Script already loaded, just re-init initTelegramLogin(); } }, [isOIDC, widgetConfig?.oidc_client_id, widgetConfig?.request_access]); // Legacy widget effect (only when NOT OIDC) useEffect(() => { if (isOIDC || !containerRef.current || !botUsername || !widgetConfig) return; const container = containerRef.current; while (container.firstChild) { container.removeChild(container.firstChild); } const redirectUrl = `${window.location.origin}/auth/telegram/callback`; const script = document.createElement('script'); script.src = 'https://telegram.org/js/telegram-widget.js?23'; script.setAttribute('data-telegram-login', botUsername); script.setAttribute('data-size', widgetConfig.size); script.setAttribute('data-radius', String(widgetConfig.radius)); script.setAttribute('data-userpic', String(widgetConfig.userpic)); script.setAttribute('data-auth-url', redirectUrl); if (widgetConfig.request_access) { script.setAttribute('data-request-access', 'write'); } script.async = true; container.appendChild(script); return () => { while (container.firstChild) { container.removeChild(container.firstChild); } }; }, [isOIDC, botUsername, widgetConfig]); if (!botUsername || botUsername === 'your_bot') { return (
{t('auth.telegramNotConfigured')}
); } return (
{/* OIDC mode: custom button that opens popup */} {isOIDC ? (
{oidcError &&

{oidcError}

}
) : ( /* Legacy widget mode: iframe-based widget */
)}

{t('auth.orOpenInApp')}

@{botUsername}
); }