nakama/frontend/src/App.jsx

182 lines
6.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'
import { useState, useEffect } from 'react'
import { initTelegramApp, getTelegramUser, isThirdPartyClient } from './utils/telegram'
import { verifyAuth, authWithTelegramOAuth } from './utils/api'
import { initTheme } from './utils/theme'
import Layout from './components/Layout'
import Feed from './pages/Feed'
import Search from './pages/Search'
import Notifications from './pages/Notifications'
import Profile from './pages/Profile'
import UserProfile from './pages/UserProfile'
import CommentsPage from './pages/CommentsPage'
import PostMenuPage from './pages/PostMenuPage'
import TelegramLogin from './components/TelegramLogin'
import './styles/index.css'
function App() {
const [user, setUser] = useState(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
const [showLogin, setShowLogin] = useState(false)
useEffect(() => {
// Инициализировать тему
initTheme()
initApp()
}, [])
const initApp = async () => {
try {
// Инициализация Telegram Web App
initTelegramApp()
// Проверить наличие Telegram Web App API
const tg = window.Telegram?.WebApp
// Если нет Telegram Web App API вообще, показываем Login Widget
if (!tg) {
setShowLogin(true)
setLoading(false)
return
}
// Получить данные пользователя из Telegram
let telegramUser = getTelegramUser()
// Если нет пользователя в initData, но есть WebApp API - дать время на инициализацию
if (!telegramUser) {
// Дать немного времени на инициализацию (Telegram Web App может загружаться асинхронно)
await new Promise(resolve => setTimeout(resolve, 200))
telegramUser = getTelegramUser()
// Если все еще нет пользователя, показываем Login Widget
if (!telegramUser) {
setShowLogin(true)
setLoading(false)
return
}
}
// Верифицировать через API
const userData = await verifyAuth()
setUser(userData)
// Обработать параметр start из Telegram (для открытия конкретного поста)
if (tg?.startParam) {
// Если startParam начинается с "post_", это ссылка на пост
if (tg.startParam.startsWith('post_')) {
const postId = tg.startParam.replace('post_', '')
// Перенаправить на страницу с конкретным постом
window.location.href = `/feed?post=${postId}`
}
}
} catch (err) {
console.error('Ошибка инициализации:', err)
setError(err.message)
} finally {
setLoading(false)
}
}
const handleTelegramAuth = async (telegramUser) => {
try {
setLoading(true)
// Отправить данные OAuth на backend
const userData = await authWithTelegramOAuth(telegramUser)
setUser(userData)
setShowLogin(false)
} catch (err) {
console.error('Ошибка авторизации:', err)
setError(err.message || 'Ошибка авторизации через Telegram')
} finally {
setLoading(false)
}
}
if (loading) {
return (
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh',
flexDirection: 'column',
gap: '16px'
}}>
<div className="spinner" />
<p style={{ color: 'var(--text-secondary)' }}>Загрузка...</p>
</div>
)
}
// Показать Login Widget если нет авторизации
if (showLogin) {
// Получить имя бота из конфига или переменных окружения
const botName = import.meta.env.VITE_TELEGRAM_BOT_NAME || 'nakama_bot'
return <TelegramLogin botName={botName} onAuth={handleTelegramAuth} />
}
if (error) {
return (
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh',
flexDirection: 'column',
gap: '16px',
padding: '20px'
}}>
<p style={{ color: 'var(--text-primary)', textAlign: 'center' }}>
Ошибка загрузки приложения
</p>
<p style={{ color: 'var(--text-secondary)', textAlign: 'center' }}>
{error}
</p>
<button
onClick={() => {
setError(null)
setShowLogin(true)
}}
style={{
padding: '12px 24px',
borderRadius: '12px',
background: 'var(--button-accent)',
color: 'white',
border: 'none',
cursor: 'pointer',
fontSize: '16px'
}}
>
Попробовать снова
</button>
</div>
)
}
if (!user) {
return null
}
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout user={user} />}>
<Route index element={<Navigate to="/feed" replace />} />
<Route path="feed" element={<Feed user={user} />} />
<Route path="search" element={<Search user={user} />} />
<Route path="notifications" element={<Notifications user={user} />} />
<Route path="profile" element={<Profile user={user} setUser={setUser} />} />
<Route path="user/:id" element={<UserProfile currentUser={user} />} />
<Route path="post/:postId/comments" element={<CommentsPage user={user} />} />
<Route path="post/:postId/menu" element={<PostMenuPage user={user} />} />
</Route>
</Routes>
</BrowserRouter>
)
}
export default App