feat(web): authenticated home redesign + Telegram OAuth + SMTP

- AppLayout: logged-in desktop home redesigned — score cards, 4 section
  cards (Finance/Governance/Social/Education), governance extras, fixed
  bottom tab bar (Home/Citizen/Referral) matching mobile layout
- AppLayout: Trading dropdown in header (Presale/Staking/MultiSig),
  Logout button; removed 8-button grid
- Removed PalletsGrid and TokenomicsSection components
- Login: Telegram OAuth via oauth.telegram.org popup + postMessage +
  custom Edge Function (hash verification, find-or-create user,
  magic link token exchange)
- Login: X (Twitter) OAuth 2.0 wired to Supabase
- supabase/functions/telegram-auth: new Edge Function — verifies
  Telegram Login Widget hash, issues Supabase magic link token
- vite.config.ts: process-shim alias to fix TDZ with node polyfills
- i18n: updated locales (en/tr/kmr) for new UI sections
- SDK docs search index regenerated
This commit is contained in:
Kurdistan Tech Ministry committed 2026-05-01 10:12:03 +03:00
1 parent 709d408983
commit bac4148020
306 files changed
+2187 -2366

No files matched your search

+111 -6
View File
@@ -133,13 +133,9 @@ const Login: React.FC = () => {
try {
const { error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: window.location.origin + '/',
},
options: { redirectTo: window.location.origin + '/' },
});
if (error) {
setError(error.message);
}
if (error) setError(error.message);
} catch {
setError('Google sign-in failed. Please try again.');
} finally {
@@ -147,6 +143,91 @@ const Login: React.FC = () => {
}
};
const handleXSignIn = async () => {
setError('');
setLoading(true);
try {
const { error } = await supabase.auth.signInWithOAuth({
provider: 'twitter',
options: { redirectTo: window.location.origin + '/' },
});
if (error) setError(error.message);
} catch {
setError('X sign-in failed. Please try again.');
} finally {
setLoading(false);
}
};
const handleTelegramSignIn = () => {
setError('');
setLoading(true);
const BOT_ID = '8690398980';
const origin = window.location.origin;
const popup = window.open(
`https://oauth.telegram.org/auth?bot_id=${BOT_ID}&origin=${encodeURIComponent(origin)}&embed=1&request_access=write`,
'TelegramLogin',
'width=550,height=470,left=400,top=200'
);
if (!popup) {
setError('Popup blocked. Please allow popups for this site.');
setLoading(false);
return;
}
const onMessage = async (event: MessageEvent) => {
if (event.origin !== 'https://oauth.telegram.org') return;
if (!event.data || event.data.event !== 'auth_result') return;
window.removeEventListener('message', onMessage);
popup.close();
try {
const tgData = event.data.result;
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabaseKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
const res = await fetch(`${supabaseUrl}/functions/v1/telegram-auth`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': supabaseKey,
'Authorization': `Bearer ${supabaseKey}`,
},
body: JSON.stringify(tgData),
});
const json = await res.json();
if (!res.ok) throw new Error(json.error || 'Telegram auth failed');
const { error: otpError } = await supabase.auth.verifyOtp({
token_hash: json.token_hash,
type: 'magiclink',
});
if (otpError) throw otpError;
navigate('/');
} catch (err) {
setError(err instanceof Error ? err.message : 'Telegram sign-in failed.');
} finally {
setLoading(false);
}
};
window.addEventListener('message', onMessage);
// Cleanup if popup is closed without completing auth
const pollClosed = setInterval(() => {
if (popup.closed) {
clearInterval(pollClosed);
window.removeEventListener('message', onMessage);
setLoading(false);
}
}, 500);
};
return (
<div className="min-h-screen bg-gradient-to-br from-gray-900 via-black to-gray-900 flex items-center justify-center p-4">
<div className="absolute inset-0 bg-[url('/grid.svg')] bg-center [mask-image:linear-gradient(180deg,white,rgba(255,255,255,0))]"></div>
@@ -404,6 +485,30 @@ const Login: React.FC = () => {
</Button>
)}
<Button
variant="outline"
className="w-full border-gray-700 bg-gray-800 hover:bg-gray-700 text-white"
onClick={handleXSignIn}
disabled={loading}
>
<svg className="mr-2 h-4 w-4" viewBox="0 0 24 24" fill="currentColor">
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
</svg>
{t('login.xSignIn', 'Continue with X')}
</Button>
<Button
variant="outline"
className="w-full border-gray-700 bg-gray-800 hover:bg-gray-700 text-white"
onClick={handleTelegramSignIn}
disabled={loading}
>
<svg className="mr-2 h-4 w-4" viewBox="0 0 24 24" fill="#26A5E4">
<path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm5.562 8.248-1.97 9.28c-.145.658-.537.818-1.084.508l-3-2.21-1.447 1.394c-.16.16-.295.295-.605.295l.213-3.053 5.56-5.023c.242-.213-.054-.333-.373-.12L6.12 14.26l-2.96-.924c-.643-.204-.657-.643.136-.953l11.57-4.461c.537-.194 1.006.131.696.326z"/>
</svg>
{t('login.telegramSignIn', 'Continue with Telegram')}
</Button>
<Button
variant="outline"
className="w-full border-gray-700 bg-gray-800 hover:bg-gray-700 text-white"