diff --git a/backgammon b/backgammon new file mode 160000 index 0000000..d1786f8 --- /dev/null +++ b/backgammon @@ -0,0 +1 @@ +Subproject commit d1786f8b78b2f841d069c0684138a936ca75298b diff --git a/client/src/screens/MainMenu/MainMenu.jsx b/client/src/screens/MainMenu/MainMenu.jsx index 627df0f..3f02a5e 100644 --- a/client/src/screens/MainMenu/MainMenu.jsx +++ b/client/src/screens/MainMenu/MainMenu.jsx @@ -1,7 +1,7 @@ import ProfileCard from './components/ProfileCard' import ActionButtons from './components/ActionButtons' import RoomList from './components/RoomList' -import TonConnectButtonComponent from '../../components/TonConnectButton' +import TonConnectButton from './components/TonConnectButton' import '../../styles/MainMenu.css' // Главное меню приложения @@ -9,11 +9,11 @@ const MainMenu = () => { return (
-
- -
-
+ {/* TonConnect кнопка над ProfileCard */} +
+ +
diff --git a/client/src/screens/MainMenu/components/ActionButtons.jsx b/client/src/screens/MainMenu/components/ActionButtons.jsx index c239706..5dd5d35 100644 --- a/client/src/screens/MainMenu/components/ActionButtons.jsx +++ b/client/src/screens/MainMenu/components/ActionButtons.jsx @@ -1,19 +1,11 @@ import '../../../styles/ActionButtons.css' -// Кнопки управления игрой и балансом +// Кнопки управления игрой const ActionButtons = () => { const handleCreateGame = () => { console.log('Создание новой игры') } - const handleDeposit = () => { - console.log('Пополнение баланса') - } - - const handleWithdraw = () => { - console.log('Вывод средств') - } - return (
- -
- - - -
) } diff --git a/client/src/screens/MainMenu/components/ProfileCard.jsx b/client/src/screens/MainMenu/components/ProfileCard.jsx index 6f776b6..d52faf7 100644 --- a/client/src/screens/MainMenu/components/ProfileCard.jsx +++ b/client/src/screens/MainMenu/components/ProfileCard.jsx @@ -3,7 +3,7 @@ import '../../../styles/ProfileCard.css' // Компонент профиля пользователя const ProfileCard = () => { - const { username, balance, level, winRate, totalGames, wins, losses } = mockProfile + const { username, balance, winRate, wins, losses } = mockProfile return (
@@ -26,24 +26,20 @@ const ProfileCard = () => {
-
- -
-
-
{level}
-
Level
-
-
-
{winRate}
-
Win Rate
-
-
-
{wins}
-
Wins
-
-
-
{losses}
-
Losses
+ +
+
+
{winRate}
+
Win Rate
+
+
+
{wins}
+
Wins
+
+
+
{losses}
+
Losses
+
diff --git a/client/src/screens/MainMenu/components/RoomCard.jsx b/client/src/screens/MainMenu/components/RoomCard.jsx index 18f7c4a..4d247a1 100644 --- a/client/src/screens/MainMenu/components/RoomCard.jsx +++ b/client/src/screens/MainMenu/components/RoomCard.jsx @@ -1,5 +1,5 @@ -import { useState } from 'react' import '../../../styles/RoomCard.css' +import PropTypes from 'prop-types' // Карточка игровой комнаты с оппонентом и ставкой const RoomCard = ({ room, onEnter }) => { @@ -55,4 +55,13 @@ const RoomCard = ({ room, onEnter }) => { ) } +RoomCard.propTypes = { + room: PropTypes.shape({ + id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + opponent: PropTypes.string.isRequired, + bet: PropTypes.number.isRequired + }).isRequired, + onEnter: PropTypes.func.isRequired +} + export default RoomCard \ No newline at end of file diff --git a/client/src/screens/MainMenu/components/TonConnectButton.jsx b/client/src/screens/MainMenu/components/TonConnectButton.jsx new file mode 100644 index 0000000..d1965a2 --- /dev/null +++ b/client/src/screens/MainMenu/components/TonConnectButton.jsx @@ -0,0 +1,21 @@ +import '../../../styles/TonConnectButton.css' + +import { TonConnectButton as TonConnectButtonComponent, useTonWallet } from '@tonconnect/ui-react' + +function TonConnectButton() { + const wallet = useTonWallet() + + return ( +
+ + {wallet && ( +
+

Connected: {wallet.account.address}

+

Chain: {wallet.account.chain}

+
+ )} +
+ ) +} + +export default TonConnectButton \ No newline at end of file diff --git a/client/src/screens/SplashScreen/SplashScreen.jsx b/client/src/screens/SplashScreen/SplashScreen.jsx index 99b2b57..2027b45 100644 --- a/client/src/screens/SplashScreen/SplashScreen.jsx +++ b/client/src/screens/SplashScreen/SplashScreen.jsx @@ -1,5 +1,6 @@ import '../../styles/SplashScreen.css' import { useState } from 'react' +import PropTypes from 'prop-types' // Экран приветствия приложения const SplashScreen = ({ onNewGame, onContinue }) => { @@ -57,4 +58,9 @@ const SplashScreen = ({ onNewGame, onContinue }) => { ) } +SplashScreen.propTypes = { + onNewGame: PropTypes.func.isRequired, + onContinue: PropTypes.func.isRequired +} + export default SplashScreen \ No newline at end of file diff --git a/client/src/styles/ActionButtons.css b/client/src/styles/ActionButtons.css index 85c05a0..799eb9d 100644 --- a/client/src/styles/ActionButtons.css +++ b/client/src/styles/ActionButtons.css @@ -1,6 +1,6 @@ .action-buttons { - margin-bottom: 40px; - padding: 20px 0; + margin-bottom: 20px; + padding: 10px 0; } .create-game-button { @@ -16,7 +16,6 @@ letter-spacing: 1px; text-transform: uppercase; transition: all 0.3s ease; - margin-bottom: 25px; } .create-game-button:hover { @@ -24,66 +23,9 @@ box-shadow: 0 5px 20px rgba(0, 255, 85, 0.4); } -.balance-buttons { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 15px; - margin-top: 15px; -} - -.balance-button { - padding: 16px; - border-radius: 10px; - font-size: 1rem; - font-weight: 600; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - gap: 8px; - letter-spacing: 0.5px; - transition: all 0.3s ease; -} - -.balance-button:hover { - transform: translateY(-2px); -} - -.deposit-button { - background: rgba(0, 255, 85, 0.1); - color: #00FF55; - border: 2px solid #00FF55; -} - -.deposit-button:hover { - background: #00FF55; - color: #03142A; - box-shadow: 0 5px 15px rgba(0, 255, 85, 0.3); -} - -.withdraw-button { - background: rgba(139, 0, 255, 0.1); - color: #8B00FF; - border: 2px solid #8B00FF; -} - -.withdraw-button:hover { - background: #8B00FF; - color: #03142A; - box-shadow: 0 5px 15px rgba(139, 0, 255, 0.3); -} - @media (max-width: 768px) { .create-game-button { padding: 16px; font-size: 1.1rem; } - - .balance-buttons { - grid-template-columns: 1fr; - } - - .balance-button { - padding: 14px; - } } \ No newline at end of file diff --git a/client/src/styles/MainMenu.css b/client/src/styles/MainMenu.css index ae5b094..7b0d17d 100644 --- a/client/src/styles/MainMenu.css +++ b/client/src/styles/MainMenu.css @@ -13,29 +13,12 @@ .menu-content { display: flex; flex-direction: column; - gap: 30px; -} + gap: 8px; -.ton-connect-header { - display: flex; - justify-content: center; - align-items: center; - padding: 20px 0; - margin-bottom: 20px; } @media (max-width: 768px) { .main-menu { padding: 20px 15px; } - - .ton-connect-header { - padding: 15px 0; - margin-bottom: 15px; - } - - .hamburger-line { - width: 25px; - height: 2px; - } } \ No newline at end of file diff --git a/client/src/styles/ProfileCard.css b/client/src/styles/ProfileCard.css index 0f506fe..3f0d649 100644 --- a/client/src/styles/ProfileCard.css +++ b/client/src/styles/ProfileCard.css @@ -1,9 +1,14 @@ .profile-card { - background: rgba(3, 20, 42, 0.7); - border: 1px solid rgba(0, 255, 85, 0.3); + background: rgba(255, 255, 255, 0.05); + backdrop-filter: blur(10px); border-radius: 16px; - padding: 30px; - margin-bottom: 30px; + padding: 20px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2); + border: 1px solid rgba(255, 255, 255, 0.1); + width: 100%; + max-width: 900px; + animation: fadeIn 0.5s ease-out; + margin-bottom: 15px; transition: all 0.3s ease; } @@ -15,17 +20,26 @@ .profile-header { display: flex; + align-items: center; justify-content: space-between; - align-items: flex-start; margin-bottom: 25px; flex-wrap: wrap; - gap: 20px; + gap: 15px; } .avatar-container { display: flex; align-items: center; - gap: 20px; + gap: 15px; +} + +.stats-horizontal { + display: flex; + align-items: center; + gap: 25px; + background: rgba(0, 0, 0, 0.2); + padding: 12px 25px; + border-radius: 12px; } .avatar { @@ -33,7 +47,8 @@ height: 70px; border-radius: 50%; object-fit: cover; - border: 2px solid #00FF55; + border: 3px solid #e0a93e; + box-shadow: 0 0 15px rgba(224, 169, 62, 0.5); transition: all 0.3s ease; } @@ -42,8 +57,8 @@ } .balance-icon { - width: 24px; - height: 24px; + width: 20px; + height: 20px; margin-right: 8px; transition: all 0.3s ease; } @@ -53,19 +68,19 @@ } .user-info h2 { - font-size: 1.8rem; - font-weight: 700; - margin-bottom: 8px; - color: #FFFFFF; + font-size: 1.5rem; + font-weight: 600; + margin-bottom: 5px; + color: #fff; } .user-info .balance { display: flex; align-items: center; - gap: 10px; - font-size: 1.5rem; - font-weight: 700; - color: #00FF55; + gap: 8px; + font-size: 1.1rem; + font-weight: 600; + color: #e0a93e; } .stats-grid { @@ -77,13 +92,30 @@ .stat-item { text-align: center; + position: relative; + transition: transform 0.3s ease; +} + +.stat-item:not(:last-child):after { + content: ""; + position: absolute; + right: -15px; + top: 50%; + transform: translateY(-50%); + height: 40px; + width: 1px; + background: rgba(255, 255, 255, 0.1); +} + +.stat-item:hover { + transform: translateY(-3px); } .stat-value { font-size: 1.3rem; font-weight: 700; - margin-bottom: 5px; - color: #00FF55; + margin-bottom: 3px; + color: #fff; transition: all 0.3s ease; } @@ -92,28 +124,32 @@ } .stat-label { - font-size: 0.8rem; - color: #B0B0B0; + font-size: 0.85rem; + color: rgba(255, 255, 255, 0.7); text-transform: uppercase; - letter-spacing: 1px; + letter-spacing: 0.5px; } +/* Адаптивность для мобильных устройств */ @media (max-width: 768px) { - .stats-grid { - grid-template-columns: repeat(2, 1fr); - gap: 15px; + .profile-header { + flex-direction: column; + align-items: flex-start; } - - .avatar { - width: 60px; - height: 60px; + + .stats-horizontal { + width: 100%; + justify-content: space-around; + gap: 15px; } - - .user-info h2 { - font-size: 1.5rem; + + .stat-item:not(:last-child):after { + display: none; } +} - .user-info .balance { - font-size: 1.2rem; - } +/* Анимации */ +@keyframes fadeIn { + from { opacity: 0; transform: translateY(-10px); } + to { opacity: 1; transform: translateY(0); } } \ No newline at end of file diff --git a/client/src/styles/RoomList.css b/client/src/styles/RoomList.css index a23dee3..acac245 100644 --- a/client/src/styles/RoomList.css +++ b/client/src/styles/RoomList.css @@ -1,5 +1,5 @@ .rooms-section { - margin-top: 20px; + margin-top: 10px; } .rooms-header { diff --git a/client/src/styles/TonConnectButton.css b/client/src/styles/TonConnectButton.css new file mode 100644 index 0000000..5f14541 --- /dev/null +++ b/client/src/styles/TonConnectButton.css @@ -0,0 +1,53 @@ +.ton-connect-container { + display: flex; + flex-direction: column; + align-items: center; + gap: 16px; + padding: 20px; + background: rgba(3, 20, 42, 0.6); + border-radius: 12px; + margin-bottom: 20px; + transition: all 0.3s ease; +} + +.ton-connect-container:hover { + border-color: rgba(0, 255, 85, 0.6); + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); +} + +.wallet-info { + background: rgba(0, 0, 0, 0.3); + padding: 12px 16px; + border-radius: 8px; + border: 1px solid rgba(255, 255, 255, 0.1); + width: 100%; + max-width: 400px; +} + +.wallet-info p { + margin: 4px 0; + font-family: 'Roboto Mono', monospace; + font-size: 0.9rem; + color: #B0B0B0; + word-break: break-all; +} + +.wallet-info p:first-child { + color: #00FF55; + font-weight: 600; +} + +@media (max-width: 768px) { + .ton-connect-container { + padding: 15px; + } + + .wallet-info { + padding: 10px 12px; + } + + .wallet-info p { + font-size: 0.8rem; + } +} \ No newline at end of file