import React, { createContext, useContext, useState, useCallback, useEffect } from 'react'; import { api } from '../services/api'; import { currentUser, initTelegramApp } from '../services/auth'; const AppContext = createContext(null); export function AppProvider({ children }) { // App state const [isLoading, setIsLoading] = useState(true); const [user, setUser] = useState(null); const [error, setError] = useState(null); // Card queue const [cardQueue, setCardQueue] = useState([]); const [currentCardIndex, setCurrentCardIndex] = useState(0); const [chosenCard, setChosenCard] = useState(null); // null | "A" | "B" // Panels const [isMenuOpen, setIsMenuOpen] = useState(false); const [isCommentsOpen, setIsCommentsOpen] = useState(false); const [menuScreen, setMenuScreen] = useState('menu'); // 'menu' | 'about' | 'create' // Toast const [toast, setToast] = useState(null); // Current card helper const currentCard = cardQueue[currentCardIndex] || null; // Initialize app useEffect(() => { async function init() { try { initTelegramApp(); // Check/register user const checkResult = await api.checkUser(currentUser.id); if (!checkResult.result) { await api.addUser({ user_id: currentUser.id, username: currentUser.username, first_name: currentUser.first_name, last_name: currentUser.last_name, photo_url: currentUser.photo_url, }); } const userResult = await api.getUser(currentUser.id); if (!userResult.error) { setUser(userResult.result); } // Load first batch of cards await loadCards(); } catch (err) { setError('Не удалось загрузить приложение'); console.error('Init error:', err); } finally { setIsLoading(false); } } init(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // Load cards batch const loadCards = useCallback(async () => { try { const result = await api.getRandomCards(currentUser.id); if (!result.error && Array.isArray(result.result) && result.result.length > 0) { setCardQueue(result.result); setCurrentCardIndex(0); setChosenCard(null); } else { // No more cards or error setCardQueue([]); setCurrentCardIndex(0); } } catch (err) { console.error('Load cards error:', err); setError('Ошибка загрузки карточек'); } }, []); // Choose a card (A or B) const chooseCard = useCallback((choice) => { if (chosenCard) { // Second tap on chosen card — go next if (choice === chosenCard) { goToNextCard(); } return; } setChosenCard(choice); // Fire select_choice to backend if (currentCard) { api.selectChoice(currentUser.id, currentCard.card_id, choice).catch(console.error); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [chosenCard, currentCard]); // Go to next card const goToNextCard = useCallback(async () => { const nextIndex = currentCardIndex + 1; if (nextIndex < cardQueue.length) { setCurrentCardIndex(nextIndex); setChosenCard(null); } else { // Load next batch await loadCards(); } }, [currentCardIndex, cardQueue.length, loadCards]); // Reactions const likeCard = useCallback(async () => { if (!currentCard || !chosenCard) return; const result = await api.likeCard(currentUser.id, currentCard.card_id); if (!result.error) { // Refresh user data to get updated liked_card_ids const userResult = await api.getUser(currentUser.id); if (!userResult.error) setUser(userResult.result); } return result; }, [currentCard, chosenCard]); const dislikeCard = useCallback(async () => { if (!currentCard || !chosenCard) return; const result = await api.dislikeCard(currentUser.id, currentCard.card_id); if (!result.error) { const userResult = await api.getUser(currentUser.id); if (!userResult.error) setUser(userResult.result); } return result; }, [currentCard, chosenCard]); // Toast helper const showToast = useCallback((message, duration = 2500) => { setToast(message); setTimeout(() => setToast(null), duration); }, []); // Menu helpers const openMenu = useCallback(() => { setIsMenuOpen(true); setMenuScreen('menu'); }, []); const closeMenu = useCallback(() => { setIsMenuOpen(false); setMenuScreen('menu'); }, []); const value = { // State isLoading, user, error, currentCard, chosenCard, cardQueue, currentCardIndex, isMenuOpen, isCommentsOpen, menuScreen, toast, // Actions chooseCard, goToNextCard, loadCards, likeCard, dislikeCard, openMenu, closeMenu, setMenuScreen, setIsCommentsOpen, showToast, setError, }; return {children}; } export function useApp() { const context = useContext(AppContext); if (!context) { throw new Error('useApp must be used within AppProvider'); } return context; }