add components

Безопасная работа с Telegram Web App SDK
Улучшенная обработка ошибок
Плавная загрузка с индикаторами
Корректная работа в демо-режиме
This commit is contained in:
degradin 2025-03-16 12:35:18 +03:00
parent 8c152a47bd
commit 8af9c21cb1
4 changed files with 62 additions and 15 deletions

View File

@ -1,6 +1,7 @@
'use client';
import { useEffect, useState } from 'react';
import { Center, Spinner } from '@chakra-ui/react';
export default function ClientOnly({ children }: { children: React.ReactNode }) {
const [hasMounted, setHasMounted] = useState(false);
@ -10,7 +11,11 @@ export default function ClientOnly({ children }: { children: React.ReactNode })
}, []);
if (!hasMounted) {
return null;
return (
<Center h="100vh">
<Spinner size="xl" />
</Center>
);
}
return <>{children}</>;

View File

@ -8,8 +8,7 @@ import TransferBalance from './TransferBalance';
import { auth, getProfile, getShopItems, purchaseItem, transferBalance } from '../utils/api';
import { IUser } from '../../backend/models/User';
import { IShopItem } from '../../backend/models/ShopItem';
import { isDemoMode, getDemoWebApp } from '../utils/demo';
import WebApp from '@twa-dev/sdk';
import { useTelegramWebApp } from '../hooks/useTelegramWebApp';
type SafeUser = Omit<IUser, keyof Document>;
@ -18,18 +17,20 @@ export default function MainApp() {
const [user, setUser] = useState<SafeUser | null>(null);
const [shopItems, setShopItems] = useState<IShopItem[]>([]);
const toast = useToast();
const { webApp, error: webAppError } = useTelegramWebApp();
useEffect(() => {
if (webApp) {
initApp();
}
}, [webApp]);
const initApp = async () => {
try {
setIsLoading(true);
let webApp;
if (isDemoMode()) {
webApp = getDemoWebApp();
} else if (typeof window !== 'undefined') {
webApp = WebApp;
} else {
throw new Error('Приложение должно быть открыто в браузере');
if (!webApp) {
throw new Error('Telegram Web App не инициализирован');
}
// Авторизация пользователя
@ -58,11 +59,17 @@ export default function MainApp() {
}
};
useEffect(() => {
initApp();
}, []);
if (webAppError) {
return (
<Center h="100vh">
<Box p={4} textAlign="center" color="red.500">
{webAppError}
</Box>
</Center>
);
}
if (isLoading) {
if (isLoading || !webApp) {
return (
<Center h="100vh">
<Spinner size="xl" />

View File

@ -0,0 +1,29 @@
'use client';
import { useEffect, useState } from 'react';
import { isDemoMode, getDemoWebApp } from '../utils/demo';
export function useTelegramWebApp() {
const [webApp, setWebApp] = useState<any>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const initWebApp = async () => {
try {
if (isDemoMode()) {
setWebApp(getDemoWebApp());
} else if (typeof window !== 'undefined') {
const WebAppModule = await import('@twa-dev/sdk');
setWebApp(WebAppModule.default);
}
} catch (err) {
setError('Ошибка инициализации Telegram Web App');
console.error('WebApp initialization error:', err);
}
};
initWebApp();
}, []);
return { webApp, error };
}

View File

@ -1,8 +1,14 @@
import dynamic from 'next/dynamic';
import { Center, Spinner } from '@chakra-ui/react';
import ClientOnly from './components/ClientOnly';
const MainApp = dynamic(() => import('./components/MainApp'), {
ssr: false,
loading: () => (
<Center h="100vh">
<Spinner size="xl" />
</Center>
),
});
export default function Home() {