CampFireID/app/components/MainApp.tsx
2025-03-16 11:25:09 +03:00

135 lines
3.8 KiB
TypeScript
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.

'use client';
import React, { useEffect, useState } from 'react';
import { Container, Tabs, TabList, TabPanels, Tab, TabPanel, useToast } from '@chakra-ui/react';
import { UserProfile } from './UserProfile';
import { Shop } from './Shop';
import { TransferBalance } from './TransferBalance';
import * as api from '../utils/api';
import WebApp from '@twa-dev/sdk';
import { IUser } from '../../backend/models/User';
import { IShopItem } from '../../backend/models/ShopItem';
export function MainApp() {
const [user, setUser] = useState<IUser | null>(null);
const [shopItems, setShopItems] = useState<IShopItem[]>([]);
const toast = useToast();
useEffect(() => {
const initApp = async () => {
try {
// Получаем данные из Telegram WebApp
const initData = WebApp.initData;
if (!initData) {
throw new Error('Приложение должно быть открыто в Telegram');
}
// Авторизуем пользователя
const authData = await api.auth(
WebApp.initDataUnsafe.user?.id.toString() || '',
WebApp.initDataUnsafe.user?.username || ''
);
setUser(authData.user);
// Загружаем предметы магазина
const items = await api.getShopItems();
setShopItems(items);
} catch (error: any) {
toast({
title: 'Ошибка инициализации',
description: error.message,
status: 'error',
duration: 5000,
isClosable: true,
});
}
};
initApp();
}, []);
const handlePurchase = async (itemId: string) => {
try {
const result = await api.purchaseItem(itemId);
setUser(result.user);
toast({
title: 'Покупка успешна!',
status: 'success',
duration: 3000,
isClosable: true,
});
} catch (error: any) {
toast({
title: 'Ошибка покупки',
description: error.response?.data?.error || 'Произошла ошибка',
status: 'error',
duration: 3000,
isClosable: true,
});
}
};
const handleTransfer = async (recipientUsername: string, amount: number) => {
try {
const result = await api.transferBalance(recipientUsername, amount);
setUser(prev => prev ? { ...prev, balance: result.balance } : null);
toast({
title: 'Перевод выполнен',
status: 'success',
duration: 3000,
isClosable: true,
});
} catch (error: any) {
toast({
title: 'Ошибка перевода',
description: error.response?.data?.error || 'Произошла ошибка',
status: 'error',
duration: 3000,
isClosable: true,
});
}
};
if (!user) {
return null; // или компонент загрузки
}
return (
<Container maxW="container.xl" py={8}>
<Tabs isFitted variant="enclosed">
<TabList mb="1em">
<Tab>Профиль</Tab>
<Tab>Магазин</Tab>
<Tab>Перевод</Tab>
</TabList>
<TabPanels>
<TabPanel>
<UserProfile
username={user.username}
level={user.level}
experience={user.experience}
balance={user.balance}
achievements={user.achievements}
/>
</TabPanel>
<TabPanel>
<Shop
items={shopItems}
userBalance={user.balance}
onPurchase={handlePurchase}
/>
</TabPanel>
<TabPanel>
<TransferBalance
userBalance={user.balance}
onTransfer={handleTransfer}
/>
</TabPanel>
</TabPanels>
</Tabs>
</Container>
);
}