├── .gitignore ├── .vscode └── easycode.ignore ├── LICENSE ├── README.md ├── components.json ├── craco.config.js ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── src ├── App.tsx ├── assets │ ├── icons │ │ ├── index.ts │ │ ├── items │ │ │ ├── bcoin.png │ │ │ ├── bumb.png │ │ │ ├── cat.png │ │ │ ├── dog.png │ │ │ ├── fire.png │ │ │ ├── fullhealth.png │ │ │ ├── health.png │ │ │ ├── scoin.png │ │ │ ├── shield.png │ │ │ ├── slow.png │ │ │ └── x2.png │ │ └── src │ │ │ ├── bronzeIcon.png │ │ │ ├── footprintIcon.svg │ │ │ ├── friendFullIcon.svg │ │ │ ├── friendIcon.svg │ │ │ ├── goldIcon.png │ │ │ ├── heartEmptyIcon.svg │ │ │ ├── heartIcon.svg │ │ │ ├── homeFullIcon.svg │ │ │ ├── homeIcon.svg │ │ │ ├── leadersFullIcon.svg │ │ │ ├── leadersIcon.svg │ │ │ ├── menuFullIcon.svg │ │ │ ├── menuIcon.svg │ │ │ ├── questsFullIcon.svg │ │ │ ├── questsIcon.svg │ │ │ ├── shopFullIcon.svg │ │ │ ├── shopIcon.svg │ │ │ ├── silverIcon.png │ │ │ ├── vectorLeftIcon.svg │ │ │ └── vectorRightIcon.svg │ └── imgs │ │ ├── index.ts │ │ └── src │ │ ├── img_blur.png │ │ ├── img_boxlion_left.png │ │ ├── img_boxlion_right.png │ │ ├── img_cancel_btn.png │ │ ├── img_copy.png │ │ ├── img_feather_down.png │ │ ├── img_feather_up.png │ │ ├── img_fire.png │ │ ├── img_foot.png │ │ ├── img_footprint.png │ │ ├── img_item_back.png │ │ ├── img_item_clock.png │ │ ├── img_item_double.png │ │ ├── img_item_fire.png │ │ ├── img_item_heart.png │ │ ├── img_item_light.png │ │ ├── img_item_secret.png │ │ ├── img_kinglion.png │ │ ├── img_shape_footprint.png │ │ ├── img_small_footprint.png │ │ ├── img_star.png │ │ ├── img_user.png │ │ └── img_user_bg.png ├── components │ ├── custom │ │ ├── backImg.tsx │ │ ├── backImgCommon.tsx │ │ ├── backImgShop.tsx │ │ ├── button.tsx │ │ ├── catBtn.tsx │ │ ├── claimModal.tsx │ │ ├── drawer.tsx │ │ ├── image.tsx │ │ └── shop_item.tsx │ ├── items │ │ ├── Booster.tsx │ │ └── Coin.tsx │ └── ui │ │ └── input.tsx ├── contexts │ └── TelegramContext.ts ├── index.css ├── index.tsx ├── layouts │ ├── index.tsx │ └── nav.tsx ├── lib │ └── utils.ts ├── logo.svg ├── pages │ ├── Card.tsx │ ├── Claim.tsx │ ├── Friends.tsx │ ├── Home.tsx │ ├── Leaderboard.tsx │ ├── Play.tsx │ ├── Quest.tsx │ └── Shop.tsx ├── react-app-env.d.ts ├── reportWebVitals.ts ├── router │ ├── ProtectedRoute.tsx │ └── index.tsx └── styles │ └── App.css ├── tailwind.config.js ├── test.json ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /.vscode/easycode.ignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | vendor/ 4 | cache/ 5 | .*/ 6 | *.min.* 7 | *.test.* 8 | *.spec.* 9 | *.bundle.* 10 | *.bundle-min.* 11 | *.log 12 | package-lock.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Jan Michael Garot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Shadcn/UI Template 2 | 3 | A React TypeScript + Tailwind template powered by [shadcn/ui](https://ui.shadcn.com/). 4 | 5 | ## 🎉 Features 6 | 7 | - **React** - A JavaScript library for building user interfaces. 8 | - **TypeScript** - A typed superset of JavaScript that compiles to plain JavaScript. 9 | - **Tailwind CSS** - A utility-first CSS framework. 10 | - **shadcn/ui** - Beautifully designed components you can copy and paste into your apps. 11 | - **React Router** - Declarative routing for React. 12 | 13 | ## 🚀 Getting Started 14 | Follow these steps to get started: 15 | 1. Clone the repository: 16 | 17 | ```bash 18 | git clone https://github.com/heischichou/React-Shadcn-UI-Template 19 | ``` 20 | 21 | 2. Navigate to the project directory: 22 | 23 | ```bash 24 | cd React-Shadcn-UI-Template 25 | ``` 26 | 27 | 3. Install the dependencies: 28 | 29 | ```bash 30 | npm install 31 | ``` 32 | 33 | 4. Start the development server: 34 | 35 | ```bash 36 | npm run start 37 | ``` 38 | 39 | ## 📜 Available Scripts 40 | ### Compiles and hot-reloads for development 41 | Runs the app in the development mode at [http://localhost:3000](http://localhost:3000).\ 42 | The page will reload if you make edits. You will also see any lint errors in the console. 43 | ``` 44 | npm run start 45 | ``` 46 | 47 | ### Compiles and minifies for production 48 | Builds the app for production to the `build` folder. It correctly bundles React in production mode and optimizes the build for the best performance. 49 | ``` 50 | npm run build 51 | ``` 52 | 53 | ### Remove the project single-build dependency 54 | This command will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 55 | 56 | **Note: This is a one-way operation. Once you `eject`, you can’t go back!** 57 | ``` 58 | npm run eject 59 | ``` 60 | 61 | ## 📂 Project Structure 62 | 63 | The project structure follows a standard React application layout: 64 | 65 | ```python 66 | React-Shadcn-UI-Template/ 67 | ├── node_modules/ # Project dependencies 68 | ├── public/ # Public assets 69 | ├── src/ # Application source code 70 | │ ├── components/ # React components 71 | │ │ └── ui/ # Shadcn UI components 72 | │ │ └── button.tsx # Shadcn Button component 73 | │ │ └── input.tsx # Shadcn Input component 74 | │ ├── pages/ # React Router pages 75 | │ │ └── HomePage.tsx # Default route component 76 | │ ├── styles/ # CSS stylesheets for components 77 | │ │ └── App.css # Default stylesheet with shadcn globals declared 78 | │ ├── App.tsx # Application entry point 79 | │ ├── index.css # Application stylesheet 80 | │ └── index.tsx # Main rendering file 81 | ├── craco.config.js # CRACO configuration 82 | ├── tailwind.config.js # Tailwind CSS configuration 83 | └── tsconfig.json # TypeScript configuration 84 | ``` 85 | 86 | ## 📄 License 87 | 88 | This project is licensed under the MIT License. See the [LICENSE](https://choosealicense.com/licenses/mit/) file for details. 89 | # lion_king_game 90 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.js", 8 | "css": "./src/index.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } -------------------------------------------------------------------------------- /craco.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | module.exports = { 3 | webpack: { 4 | alias: { 5 | '@': path.resolve(__dirname, 'src'), 6 | }, 7 | }, 8 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-typescript-template", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@radix-ui/react-slot": "^1.0.2", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "@twa-dev/sdk": "^8.0.2", 10 | "@types/jest": "^27.5.2", 11 | "@types/node": "^16.18.14", 12 | "@types/react": "^18.0.28", 13 | "@types/react-dom": "^18.0.11", 14 | "axios": "^1.7.9", 15 | "class-variance-authority": "^0.7.0", 16 | "clsx": "^2.1.0", 17 | "lucide-react": "^0.358.0", 18 | "react": "^18.2.0", 19 | "react-dom": "^18.2.0", 20 | "react-icons": "^5.4.0", 21 | "react-router": "^6.22.3", 22 | "react-router-dom": "^6.22.3", 23 | "react-scripts": "^5.0.1", 24 | "tailwind-merge": "^2.2.1", 25 | "tailwindcss-animate": "^1.0.7", 26 | "typescript": "^4.9.5", 27 | "web-vitals": "^2.1.4" 28 | }, 29 | "scripts": { 30 | "start": "craco start HOST=0.0.0.0", 31 | "build": "craco build", 32 | "test": "craco test", 33 | "eject": "react-scripts eject" 34 | }, 35 | "eslintConfig": { 36 | "extends": [ 37 | "react-app", 38 | "react-app/jest" 39 | ] 40 | }, 41 | "browserslist": { 42 | "production": [ 43 | ">0.2%", 44 | "not dead", 45 | "not op_mini all" 46 | ], 47 | "development": [ 48 | "last 1 chrome version", 49 | "last 1 firefox version", 50 | "last 1 safari version" 51 | ] 52 | }, 53 | "devDependencies": { 54 | "@craco/craco": "^5.9.0", 55 | "@craco/types": "^7.1.0", 56 | "@svgr/webpack": "^8.1.0", 57 | "tailwindcss": "^3.2.7" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 31 | React App 32 | 33 | 34 | 35 |
36 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import "./styles/App.css"; 2 | import Router from "./router"; 3 | import AppLayout from "./layouts"; 4 | import WebApp from "@twa-dev/sdk"; 5 | import { useEffect, useState } from "react"; 6 | import { TelegramContext, TelegramUser } from "./contexts/TelegramContext"; 7 | import axios from "axios"; 8 | 9 | export default function App() { 10 | const [user, setUser] = useState(null); 11 | const webApp = WebApp; 12 | 13 | useEffect(() => { 14 | const userData = webApp.initDataUnsafe; 15 | 16 | if (userData?.user) { 17 | setUser(userData.user); 18 | } 19 | 20 | const handleVisibilityChange = () => { 21 | if (document.hidden) { 22 | console.log("Telegram Mini App minimized or closed"); 23 | } 24 | }; 25 | 26 | document.addEventListener("visibilitychange", handleVisibilityChange); 27 | 28 | return () => { 29 | document.removeEventListener("visibilitychange", handleVisibilityChange); 30 | }; 31 | }, [webApp.initDataUnsafe]); 32 | 33 | useEffect(() => { 34 | const registerUser = async () => { 35 | if (user) { 36 | try { 37 | const response = await axios.post( 38 | "https://simon.billtears76.workers.dev/auth/register_user", 39 | { 40 | telegramid: user.id, 41 | username: user.username, 42 | avatar: user.photo_url, 43 | invitedby: new URLSearchParams(window.location.search).get("start"), 44 | } 45 | ); 46 | console.log("User registered:", response.data); 47 | } catch (error) { 48 | console.error("Error registering user:", error); 49 | } 50 | } 51 | }; 52 | 53 | registerUser(); 54 | }, [user]); 55 | 56 | return ( 57 | 58 |
59 | 60 | 61 | 62 |
63 |
64 | ); 65 | } 66 | -------------------------------------------------------------------------------- /src/assets/icons/index.ts: -------------------------------------------------------------------------------- 1 | import FootprintIcon from "./src/footprintIcon.svg"; 2 | import VectorLeftIcon from "./src/vectorLeftIcon.svg"; 3 | import VectorRightIcon from "./src/vectorRightIcon.svg"; 4 | import HeartIcon from "./src/heartIcon.svg"; 5 | import HeartEmptyIcon from "./src/heartEmptyIcon.svg"; 6 | import FriendIcon from "./src/friendIcon.svg"; 7 | import FriendFullIcon from "./src/friendFullIcon.svg"; 8 | import LeadersIcon from "./src/leadersIcon.svg"; 9 | import LeadersFullIcon from "./src/leadersFullIcon.svg"; 10 | import QuestsFullIcon from "./src/questsFullIcon.svg"; 11 | import QuestsIcon from "./src/questsIcon.svg"; 12 | import ShopIcon from "./src/shopIcon.svg"; 13 | import ShopFullIcon from "./src/shopFullIcon.svg"; 14 | import HomeIcon from "./src/homeIcon.svg"; 15 | import HomeFullIcon from "./src/homeFullIcon.svg"; 16 | import MenuIcon from "./src/menuIcon.svg"; 17 | import MenuFullIcon from "./src/menuFullIcon.svg"; 18 | import GoldIcon from "./src/goldIcon.png"; 19 | import SilverIcon from "./src/silverIcon.png"; 20 | import BronzeIcon from "./src/bronzeIcon.png"; 21 | export { 22 | FootprintIcon, 23 | VectorLeftIcon, 24 | VectorRightIcon, 25 | HeartIcon, 26 | HeartEmptyIcon, 27 | FriendFullIcon, 28 | FriendIcon, 29 | LeadersFullIcon, 30 | LeadersIcon, 31 | QuestsFullIcon, 32 | QuestsIcon, 33 | ShopFullIcon, 34 | ShopIcon, 35 | HomeFullIcon, 36 | HomeIcon, 37 | MenuFullIcon, 38 | MenuIcon, 39 | GoldIcon, 40 | SilverIcon, 41 | BronzeIcon, 42 | }; 43 | -------------------------------------------------------------------------------- /src/assets/icons/items/bcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/icons/items/bcoin.png -------------------------------------------------------------------------------- /src/assets/icons/items/bumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/icons/items/bumb.png -------------------------------------------------------------------------------- /src/assets/icons/items/cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/icons/items/cat.png -------------------------------------------------------------------------------- /src/assets/icons/items/dog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/icons/items/dog.png -------------------------------------------------------------------------------- /src/assets/icons/items/fire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/icons/items/fire.png -------------------------------------------------------------------------------- /src/assets/icons/items/fullhealth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/icons/items/fullhealth.png -------------------------------------------------------------------------------- /src/assets/icons/items/health.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/icons/items/health.png -------------------------------------------------------------------------------- /src/assets/icons/items/scoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/icons/items/scoin.png -------------------------------------------------------------------------------- /src/assets/icons/items/shield.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/icons/items/shield.png -------------------------------------------------------------------------------- /src/assets/icons/items/slow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/icons/items/slow.png -------------------------------------------------------------------------------- /src/assets/icons/items/x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/icons/items/x2.png -------------------------------------------------------------------------------- /src/assets/icons/src/bronzeIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/icons/src/bronzeIcon.png -------------------------------------------------------------------------------- /src/assets/icons/src/footprintIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/assets/icons/src/friendFullIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/src/friendIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/src/goldIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/icons/src/goldIcon.png -------------------------------------------------------------------------------- /src/assets/icons/src/heartEmptyIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/assets/icons/src/heartIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/assets/icons/src/homeFullIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/assets/icons/src/homeIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/assets/icons/src/leadersFullIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/src/leadersIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/src/menuFullIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/icons/src/menuIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/icons/src/questsFullIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/assets/icons/src/questsIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/src/shopFullIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/src/shopIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/src/silverIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/icons/src/silverIcon.png -------------------------------------------------------------------------------- /src/assets/icons/src/vectorLeftIcon.svg: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
-------------------------------------------------------------------------------- /src/assets/icons/src/vectorRightIcon.svg: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
-------------------------------------------------------------------------------- /src/assets/imgs/index.ts: -------------------------------------------------------------------------------- 1 | import ImgKinglion from "./src/img_kinglion.png"; 2 | import Feather_down from "./src/img_feather_down.png"; 3 | import Feather_up from "./src/img_feather_up.png"; 4 | import Shape_footprint from "./src/img_shape_footprint.png"; 5 | import FootPrint from "./src/img_footprint.png"; 6 | import Boxlion_left from "./src/img_boxlion_left.png"; 7 | import Boxlion_right from "./src/img_boxlion_right.png"; 8 | import Fire from "./src/img_fire.png"; 9 | import Foot from "./src/img_foot.png"; 10 | import Item_back from "./src/img_item_back.png"; 11 | import Item_clock from "./src/img_item_clock.png"; 12 | import Item_double from "./src/img_item_double.png"; 13 | import Item_fire from "./src/img_item_fire.png"; 14 | import Item_heart from "./src/img_item_heart.png"; 15 | import Item_light from "./src/img_item_light.png"; 16 | import Item_secret from "./src/img_item_secret.png"; 17 | import Cancel_btn from "./src/img_cancel_btn.png"; 18 | import User_avatar from "./src/img_user.png"; 19 | import Small_footprint from "./src/img_small_footprint.png"; 20 | import UserBgIcon from "./src/img_user_bg.png"; 21 | import StarIcon from "./src/img_star.png"; 22 | import CopyIcon from "./src/img_copy.png"; 23 | 24 | export { 25 | ImgKinglion, 26 | Feather_down, 27 | Feather_up, 28 | Shape_footprint, 29 | FootPrint, 30 | Boxlion_left, 31 | Boxlion_right, 32 | Fire, 33 | Foot, 34 | Item_back, 35 | Item_clock, 36 | Item_double, 37 | Item_fire, 38 | Item_light, 39 | Item_heart, 40 | Item_secret, 41 | Cancel_btn, 42 | User_avatar, 43 | Small_footprint, 44 | UserBgIcon, 45 | StarIcon, 46 | CopyIcon, 47 | }; 48 | -------------------------------------------------------------------------------- /src/assets/imgs/src/img_blur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_blur.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_boxlion_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_boxlion_left.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_boxlion_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_boxlion_right.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_cancel_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_cancel_btn.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_copy.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_feather_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_feather_down.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_feather_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_feather_up.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_fire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_fire.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_foot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_foot.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_footprint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_footprint.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_item_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_item_back.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_item_clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_item_clock.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_item_double.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_item_double.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_item_fire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_item_fire.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_item_heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_item_heart.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_item_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_item_light.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_item_secret.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_item_secret.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_kinglion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_kinglion.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_shape_footprint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_shape_footprint.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_small_footprint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_small_footprint.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_star.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_user.png -------------------------------------------------------------------------------- /src/assets/imgs/src/img_user_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vortexory/telegrambot/dab998ac9696e0c58f60edfbc7f582ecbcfecb11/src/assets/imgs/src/img_user_bg.png -------------------------------------------------------------------------------- /src/components/custom/backImg.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { cn } from "@/lib/utils"; 3 | 4 | export interface BackImgProps extends React.HtmlHTMLAttributes { 5 | className?: string; 6 | children: React.ReactNode; 7 | round?: string; 8 | } 9 | 10 | const BackImg = React.forwardRef( 11 | ({ className, children, round, ...props }, ref) => { 12 | return ( 13 |
22 |
{children}
23 |
24 | ); 25 | } 26 | ); 27 | 28 | BackImg.displayName = "BackImg"; 29 | 30 | export { BackImg }; 31 | -------------------------------------------------------------------------------- /src/components/custom/backImgCommon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { cn } from "@/lib/utils"; 3 | 4 | export interface BackImgCommonProps 5 | extends React.HtmlHTMLAttributes { 6 | className?: string; 7 | children: React.ReactNode; 8 | round?: string; 9 | gradient?: boolean; 10 | } 11 | 12 | const BackImgCommon = React.forwardRef( 13 | ({ className, children, gradient, round, ...props }, ref) => { 14 | return ( 15 |
20 | {/* Gradient Border */} 21 |
28 | 29 | {/* Inner Background */} 30 |
40 | {children} 41 |
42 |
43 | ); 44 | } 45 | ); 46 | 47 | BackImgCommon.displayName = "BackImgCommon"; 48 | 49 | export { BackImgCommon }; 50 | -------------------------------------------------------------------------------- /src/components/custom/backImgShop.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { cn } from "@/lib/utils"; 3 | 4 | export interface BackImgShopProps 5 | extends React.HtmlHTMLAttributes { 6 | className?: string; 7 | children: React.ReactNode; 8 | round?: string; 9 | gradient?: boolean; 10 | } 11 | 12 | const BackImgShop = React.forwardRef( 13 | ({ className, children, gradient, round, ...props }, ref) => { 14 | return ( 15 |
20 | {/* Gradient Border */} 21 |
24 | 25 | {/* Inner Background */} 26 |
33 | {children} 34 |
35 |
36 | ); 37 | } 38 | ); 39 | 40 | BackImgShop.displayName = "BackImgt"; 41 | 42 | export { BackImgShop }; 43 | -------------------------------------------------------------------------------- /src/components/custom/button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { cn } from "@/lib/utils"; 3 | 4 | export interface ButtonProps 5 | extends React.ButtonHTMLAttributes { 6 | width?: number | string; 7 | height?: number | string; 8 | icon?: React.ReactNode; 9 | children: React.ReactNode; 10 | className?: string; 11 | } 12 | 13 | const Button = React.forwardRef( 14 | ({ className, width, height, icon, children, ...props }, ref) => { 15 | return ( 16 | 31 | ); 32 | } 33 | ); 34 | 35 | Button.displayName = "Button"; 36 | 37 | export { Button }; 38 | -------------------------------------------------------------------------------- /src/components/custom/catBtn.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | export interface CatBtnProps 3 | extends React.ButtonHTMLAttributes { 4 | firstTitle: string; 5 | lastTitle: string; 6 | } 7 | 8 | const CatBtn = React.forwardRef( 9 | ({ firstTitle, lastTitle, className, ...props }, ref) => { 10 | const [toggle, setToggle] = React.useState(true); 11 | 12 | const handleToggle = () => { 13 | setToggle(!toggle); 14 | }; 15 | 16 | return ( 17 |
21 | 30 | 39 |
40 | ); 41 | } 42 | ); 43 | 44 | CatBtn.displayName = "CatBtn"; 45 | 46 | export { CatBtn }; 47 | -------------------------------------------------------------------------------- /src/components/custom/claimModal.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { useNavigate } from "react-router-dom"; 3 | import { Image } from "./image"; 4 | import { Fire, Foot, Feather_down, Feather_up } from "@/assets/imgs"; 5 | import axios from "axios"; 6 | 7 | interface IsOpenType { 8 | win: boolean; 9 | lose: boolean; 10 | } 11 | export interface ClaimModalProps extends React.HTMLAttributes { 12 | isOpen: IsOpenType; 13 | score: number; 14 | username: string; 15 | // children?: React.ReactNode; 16 | className?: string; 17 | } 18 | 19 | const ClaimModal = React.forwardRef( 20 | ({ isOpen, score, username, children, ...props }, ref) => { 21 | const navigate = useNavigate(); 22 | const modal = 23 | isOpen.win || isOpen.lose ? "w-full absolute z-[100] h-screen" : "w-0"; 24 | 25 | const handleClaim = async () => { 26 | // update user point 27 | const point = await axios.post( 28 | "https://simon.billtears76.workers.dev/score/add_point", 29 | { username, pointToAdd: score } 30 | ); 31 | console.log(point.data.result.point, "point"); 32 | // Claim reward 33 | const claim = await axios.post( 34 | "https://simon.billtears76.workers.dev/score/update_user_score", 35 | { username, newScore: score } 36 | ); 37 | if (claim.data.success) { 38 | console.log("success"); 39 | navigate("/"); 40 | } else { 41 | console.log("failed"); 42 | } 43 | }; 44 | 45 | return ( 46 |
47 |
48 |
49 |
50 |
51 | logo 56 |

57 | {isOpen.win ? "Congratulations" : "Game Over"} 58 |

59 |

60 | {isOpen.win ? "You win the game" : "You loose the game"} 61 |

62 |
63 |
64 |
65 |

66 | You reward: 67 |

68 | {isOpen.win ? ( 69 |
70 | 5 TON 71 |
72 | ) : ( 73 |
74 | 1000 $King 75 |
76 | )} 77 |
78 |
79 | 85 | vector_down 90 | vector_up 95 |
96 |
97 |
98 |
99 |
100 | ); 101 | } 102 | ); 103 | 104 | ClaimModal.displayName = "ClaimModal"; 105 | 106 | export { ClaimModal }; 107 | -------------------------------------------------------------------------------- /src/components/custom/drawer.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { cn } from "@/lib/utils"; // Make sure this utility is correctly implemented 3 | import { Cancel_btn, Feather_up, Feather_down } from "@/assets/imgs"; 4 | import { Image } from "./image"; 5 | 6 | export interface DrawerProps extends React.HTMLAttributes { 7 | className?: string; 8 | img: string; 9 | isOpen: boolean; 10 | title: string; 11 | description: string; 12 | cost: number; 13 | onClose: () => void; 14 | onSubmit: () => void; 15 | } 16 | 17 | const Drawer = React.forwardRef( 18 | ( 19 | { 20 | className, 21 | img, 22 | title, 23 | description, 24 | cost, 25 | isOpen, 26 | onSubmit, 27 | onClose, 28 | ...props 29 | }, 30 | ref 31 | ) => { 32 | return ( 33 |
42 |
43 | 46 |
47 |

48 | Confirm your purchase 49 |

50 |

51 | {title} 52 |

53 | {img} 58 |

59 | {description} 60 |

61 |

62 | Cost: {cost}$King 63 |

64 |
65 | 71 | vector_down 76 | vector_up 81 |
82 |
83 |
84 | ); 85 | } 86 | ); 87 | 88 | Drawer.displayName = "Drawer"; 89 | 90 | export { Drawer }; 91 | -------------------------------------------------------------------------------- /src/components/custom/image.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { cn } from "@/lib/utils"; 3 | 4 | export interface ImageProps extends React.ImgHTMLAttributes { 5 | src: string; 6 | width?: number | string; 7 | height?: number | string; 8 | alt: string; 9 | className?: string; 10 | } 11 | 12 | const Image = React.forwardRef( 13 | ({ className, src, width, height, alt, ...props }, ref) => { 14 | return ( 15 | {alt} 24 | ); 25 | } 26 | ); 27 | 28 | Image.displayName = "Image"; 29 | 30 | export { Image }; 31 | -------------------------------------------------------------------------------- /src/components/custom/shop_item.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { cn } from "@/lib/utils"; 3 | import { BackImgShop } from "./backImgShop"; 4 | import { Button } from "./button"; 5 | 6 | export interface ShopItemProps extends React.HTMLAttributes { 7 | className?: string; 8 | img?: string; 9 | title: string; 10 | onClick: () => void; 11 | } 12 | 13 | const ShopItem = React.forwardRef( 14 | ({ className, img, title, onClick, ...props }, ref) => { 15 | return ( 16 |
24 | 25 |
26 | {img && item} 27 |
28 |
29 |

{title}

30 | 36 |
37 | ); 38 | } 39 | ); 40 | 41 | ShopItem.displayName = "ShopItem"; 42 | 43 | export { ShopItem }; 44 | -------------------------------------------------------------------------------- /src/components/items/Booster.tsx: -------------------------------------------------------------------------------- 1 | import bumb from '@/assets/icons/items/bumb.png' // 4% 2 | import health from '@/assets/icons/items/health.png' // 6% 3 | import speedup from '@/assets/icons/items/fire.png' // 15% 4 | import fullhealth from '@/assets/icons/items/fullhealth.png' // 15% 5 | import shield from '@/assets/icons/items/shield.png' // 15% 6 | import slow from '@/assets/icons/items/slow.png' // 15% 7 | import x2 from '@/assets/icons/items/x2.png' // 15% 8 | 9 | const items = [bumb, speedup, fullhealth, health, shield, slow, x2]; 10 | const itemScore = [`bomb`, `speedup`, `fullhealth`, `health`, `shield`, `slow`, `x2`]; 11 | 12 | const booster = () => { 13 | let type = 0; 14 | 15 | const random_num = Math.random(); 16 | if (random_num < 0.04) type = 0; // 4% for bumb 17 | else if (random_num < 0.25) type = 1; // 15% for speedup 18 | else if (random_num < 0.40) type = 2; // 15% for fullhealth 19 | else if (random_num < 0.10) type = 3; // 6% for health 20 | else if (random_num < 0.55) type = 4; // 15% for shield 21 | else if (random_num < 0.70) type = 5; // 15% for slow 22 | else type = 6; // 15% for x2 23 | 24 | return { item: items[type], score: itemScore[type] } 25 | }; 26 | 27 | export default booster; -------------------------------------------------------------------------------- /src/components/items/Coin.tsx: -------------------------------------------------------------------------------- 1 | import BigCoin from '@/assets/icons/items/bcoin.png' // 5% score 10 2 | import SmallCoin from '@/assets/icons/items/scoin.png' // 65% score 1 3 | import Cat from '@/assets/icons/items/cat.png' // 15% score 3 4 | import Dog from '@/assets/icons/items/dog.png' // 15% score 3 5 | 6 | const items = [Cat, Dog, BigCoin, SmallCoin] 7 | const appearanceRates = [15, 15, 5, 65]; 8 | const itemScore = [1, 1, 1, 1]; 9 | 10 | 11 | const coin = () => { 12 | let type = 0; 13 | 14 | const random = Math.random() * 100 15 | let cumulativeRate = 0 16 | for (let i = 0; i < appearanceRates.length; i++) { 17 | cumulativeRate += appearanceRates[i] 18 | if (random < cumulativeRate) { 19 | type = i; 20 | break 21 | } 22 | } 23 | 24 | return { item: items[type], score: itemScore[type] } 25 | }; 26 | 27 | export default coin; -------------------------------------------------------------------------------- /src/components/ui/input.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | export interface InputProps 6 | extends React.InputHTMLAttributes {} 7 | 8 | const Input = React.forwardRef( 9 | ({ className, type, ...props }, ref) => { 10 | return ( 11 | 20 | ); 21 | } 22 | ); 23 | Input.displayName = "Input"; 24 | 25 | export { Input }; 26 | -------------------------------------------------------------------------------- /src/contexts/TelegramContext.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | declare global { 3 | interface Window { 4 | Telegram?: { 5 | WebApp?: any; 6 | }; 7 | } 8 | } 9 | 10 | export interface TelegramUser { 11 | id: number; 12 | first_name?: string; // Changed from firstName to match Telegram's format 13 | last_name?: string; // Changed from lastName to match Telegram's format 14 | username?: string; 15 | photo_url?: string; 16 | } 17 | 18 | export const TelegramContext = createContext(null); 19 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.cdnfonts.com/css/sf-pro-display"); 2 | 3 | @tailwind base; 4 | @tailwind components; 5 | @tailwind utilities; 6 | 7 | @layer base { 8 | :root { 9 | --background: 0 0% 100%; 10 | --foreground: 222.2 84% 4.9%; 11 | 12 | --card: 0 0% 100%; 13 | --card-foreground: 222.2 84% 4.9%; 14 | 15 | --popover: 0 0% 100%; 16 | --popover-foreground: 222.2 84% 4.9%; 17 | 18 | --primary: 222.2 47.4% 11.2%; 19 | --primary-foreground: 210 40% 98%; 20 | 21 | --secondary: 210 40% 96.1%; 22 | --secondary-foreground: 222.2 47.4% 11.2%; 23 | 24 | --muted: 210 40% 96.1%; 25 | --muted-foreground: 215.4 16.3% 46.9%; 26 | 27 | --accent: 210 40% 96.1%; 28 | --accent-foreground: 222.2 47.4% 11.2%; 29 | 30 | --destructive: 0 84.2% 60.2%; 31 | --destructive-foreground: 210 40% 98%; 32 | 33 | --border: 214.3 31.8% 91.4%; 34 | --input: 214.3 31.8% 91.4%; 35 | --ring: 222.2 84% 4.9%; 36 | 37 | --radius: 0.5rem; 38 | } 39 | 40 | .dark { 41 | --background: 222.2 84% 4.9%; 42 | --foreground: 210 40% 98%; 43 | 44 | --card: 222.2 84% 4.9%; 45 | --card-foreground: 210 40% 98%; 46 | 47 | --popover: 222.2 84% 4.9%; 48 | --popover-foreground: 210 40% 98%; 49 | 50 | --primary: 210 40% 98%; 51 | --primary-foreground: 222.2 47.4% 11.2%; 52 | 53 | --secondary: 217.2 32.6% 17.5%; 54 | --secondary-foreground: 210 40% 98%; 55 | 56 | --muted: 217.2 32.6% 17.5%; 57 | --muted-foreground: 215 20.2% 65.1%; 58 | 59 | --accent: 217.2 32.6% 17.5%; 60 | --accent-foreground: 210 40% 98%; 61 | 62 | --destructive: 0 62.8% 30.6%; 63 | --destructive-foreground: 210 40% 98%; 64 | 65 | --border: 217.2 32.6% 17.5%; 66 | --input: 217.2 32.6% 17.5%; 67 | --ring: 212.7 26.8% 83.9%; 68 | } 69 | } 70 | 71 | @layer base { 72 | * { 73 | @apply border-border; 74 | } 75 | body { 76 | @apply bg-background text-foreground; 77 | font-family: "Roboto", "SF Pro Display", -apple-system, BlinkMacSystemFont, 78 | "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", 79 | "Helvetica Neue", sans-serif; 80 | } 81 | } 82 | ::-webkit-scrollbar { 83 | display: none; 84 | } 85 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | import "./index.css"; 5 | import App from "./App"; 6 | // import reportWebVitals from "./reportWebVitals"; 7 | 8 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 9 | const root = ReactDOM.createRoot( 10 | document.getElementById("root") as HTMLElement 11 | ).render( 12 | 13 | 14 | 15 | 16 | 17 | ) ; 18 | 19 | // If you want to start measuring performance in your app, pass a function 20 | // to log results (for example: reportWebVitals(console.log)) 21 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 22 | // reportWebVitals(); 23 | -------------------------------------------------------------------------------- /src/layouts/index.tsx: -------------------------------------------------------------------------------- 1 | import { useMemo } from "react"; 2 | import { useLocation } from "react-router-dom"; 3 | import Nav from "./nav"; 4 | interface AppLayoutProps { 5 | children: React.ReactNode; 6 | } 7 | 8 | const AppLayout = ({ children }: AppLayoutProps) => { 9 | const location = useLocation(); 10 | 11 | const isShowNav = useMemo( 12 | () => 13 | ["/", "/shop", "/leaders", "/friends", "/quests"].includes( 14 | location.pathname 15 | ), 16 | [location.pathname] 17 | ); 18 | const isAdmin = useMemo( 19 | () => location.pathname.includes("/admin"), 20 | [location.pathname] 21 | ); 22 | return ( 23 |
24 | {isShowNav &&
27 | ); 28 | }; 29 | 30 | export default AppLayout; 31 | -------------------------------------------------------------------------------- /src/layouts/nav.tsx: -------------------------------------------------------------------------------- 1 | import { useCallback } from "react"; 2 | import { useNavigate, NavLink, useLocation } from "react-router-dom"; 3 | import { GoHome } from "react-icons/go"; 4 | import { RxDashboard } from "react-icons/rx"; 5 | import { BiBasket } from "react-icons/bi"; 6 | import { FaUserPlus, FaAward } from "react-icons/fa"; 7 | import { IoMdCheckbox } from "react-icons/io"; 8 | import { 9 | HomeFullIcon, 10 | HomeIcon, 11 | QuestsFullIcon, 12 | QuestsIcon, 13 | MenuFullIcon, 14 | MenuIcon, 15 | ShopFullIcon, 16 | ShopIcon, 17 | FriendFullIcon, 18 | FriendIcon, 19 | LeadersFullIcon, 20 | LeadersIcon, 21 | } from "@/assets/icons"; 22 | import { Image } from "@/components/custom/image"; 23 | interface NavProps { 24 | isAdmin?: boolean; 25 | } 26 | 27 | const Nav = ({ isAdmin }: NavProps) => { 28 | const navigate = useNavigate(); 29 | const navigation = useLocation(); 30 | const pathName = navigation.pathname; 31 | 32 | const gotoHome = useCallback(() => { 33 | navigate("/overview"); 34 | }, [navigate]); 35 | 36 | const gotoAllCourses = useCallback(() => { 37 | navigate("/all-courses"); 38 | }, [navigate]); 39 | 40 | return ( 41 | <> 42 | {/* {isAdmin && ( */} 43 |
44 |
45 | {/* Main */} 46 | 47 |
48 | {/* */} 49 | Home 54 | 59 | Main 60 | 61 |
62 |
63 | 64 | {/* Quests */} 65 | 66 |
67 | Quests 72 | 79 | Quests 80 | 81 |
82 |
83 | 84 | {/* Cards */} 85 | 86 |
87 | card 92 | 97 | Cards 98 | 99 |
100 |
101 | 102 | {/* Shop */} 103 | 104 |
105 | Shop 110 | 115 | Shop 116 | 117 |
118 |
119 | 120 | {/* Friends */} 121 | 122 |
123 | Friends 128 | 135 | Friends 136 | 137 |
138 |
139 | 140 | {/* Leaders */} 141 | 142 |
143 | Leaders 148 | 155 | Leaders 156 | 157 |
158 |
159 |
160 |
161 | 162 | ); 163 | }; 164 | 165 | export default Nav; 166 | -------------------------------------------------------------------------------- /src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | 8 | export const calculateDateDifference = (d1: string | null, d2: string) => { 9 | if (!d1) return 1; 10 | const date1 = new Date(d1); 11 | const date2 = new Date(d2); 12 | return Math.floor(Math.abs((date1.setHours(0, 0, 0, 0) - date2.setHours(0, 0, 0, 0)) / (1000 * 3600 * 36))); 13 | }; -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/Card.tsx: -------------------------------------------------------------------------------- 1 | import { useContext, useEffect, useState } from "react"; 2 | import { useNavigate } from "react-router"; 3 | import { Image } from "@/components/custom/image"; 4 | import { Button } from "@/components/custom/button"; 5 | import { BackImg } from "@/components/custom/backImg"; 6 | import { FootPrint } from "@/assets/imgs"; 7 | import { IoIosArrowBack, IoIosShareAlt } from "react-icons/io"; 8 | import { TelegramContext, TelegramUser } from "../contexts/TelegramContext"; 9 | import axios from "axios"; 10 | 11 | const Card = () => { 12 | const navigate = useNavigate(); 13 | const [index, setIndex] = useState(null); 14 | const [selectSkin, setSelectSkin] = useState(0); 15 | const [ownSkin, setOwnSkin] = useState(0); 16 | const [totalSkins, setTotalSkins] = useState<{ imageurl: string }[]>([]); 17 | const currentUser = useContext(TelegramContext); 18 | const displayName = 19 | currentUser?.username || currentUser?.first_name || "Guest"; 20 | const avatarUrl = 21 | currentUser?.photo_url || "https://i.postimg.cc/YSm0rKS7/User-35.png"; 22 | 23 | useEffect(() => { 24 | const fetchTotalSkins = async () => { 25 | try { 26 | // Fetch skins from API 27 | const total = await axios.get( 28 | "https://simon.billtears76.workers.dev/skin/get_total_skin" 29 | ); 30 | console.log(total); 31 | setTotalSkins(total.data.result); 32 | } catch (error) { 33 | console.error("Failed to get total skins:", error); 34 | } 35 | }; 36 | fetchTotalSkins(); 37 | },[]); 38 | 39 | useEffect(() => { 40 | const fetchOwnSkins = async () => { 41 | try { 42 | // Fetch skins from API 43 | const own = await axios.post( 44 | "https://simon.billtears76.workers.dev/skin/get_own_skin", 45 | { username: displayName } 46 | ); 47 | setOwnSkin(own.data.result); 48 | } catch (error) { 49 | console.error("Failed to get skins:", error); 50 | } 51 | }; 52 | fetchOwnSkins(); 53 | }, [displayName]); 54 | console.log(ownSkin, 'ownskin') 55 | 56 | useEffect(() => { 57 | const fetchCurrentSkins = async () => { 58 | try { 59 | // Fetch skins from API 60 | const current = await axios.post( 61 | "https://simon.billtears76.workers.dev/skin/get_skin_state", 62 | { username: displayName } 63 | ); 64 | setSelectSkin(current.data.result.id); 65 | } catch (error) { 66 | console.error("Failed to get skins:", error); 67 | } 68 | }; 69 | fetchCurrentSkins(); 70 | }, [displayName, selectSkin]); 71 | 72 | const handleChoose = async () => { 73 | const response = await axios.post( 74 | "https://simon.billtears76.workers.dev/skin/update_skin_state", 75 | { username: displayName, skin: index } 76 | ); 77 | if (response.data.success) { 78 | console.log("success"); 79 | setSelectSkin(index !== null ? index : 0); 80 | } else { 81 | console.log("failed"); 82 | } 83 | }; 84 | 85 | console.log(selectSkin, "selectSkin"); 86 | console.log(index, "index"); 87 | 88 | return ( 89 |
90 |
91 |
92 |
93 |
94 | 102 | {avatarUrl} 107 |

{displayName}

108 |
109 |
110 |
111 |

112 | Play the game, earn points, get

characters and become 113 | the coolest

player in King Leon! 114 |

115 |
116 |
117 | 121 |
122 |
123 |
124 | {`skin${index 129 |
130 |

131 | Skin Name 132 |

133 |

134 | Description 135 |

136 | {index !== null && index === selectSkin ? ( 137 | 140 | ) : ( 141 | 154 | )} 155 |
156 |
157 |
158 | {totalSkins.map((item, idx) => 159 | index === idx ? ( 160 |
166 | 167 | {`skin${idx}`} 172 | 173 |
174 | ) : ( 175 |
181 |
setIndex(idx)} 184 | > 185 | {`skin${idx}`} 190 |
191 |
192 | ) 193 | )} 194 |
195 |
196 |
197 |
198 |
199 | 205 |
206 | 207 | {/* Footprint Background Effect */} 208 |
212 | {/* Top Gradient Overlay */} 213 |
214 | {/* Bottom Gradient Overlay */} 215 |
216 | 217 | {/* Bottom Gradient-1 Overlay */} 218 |
219 |
220 | ); 221 | }; 222 | 223 | export default Card; 224 | -------------------------------------------------------------------------------- /src/pages/Claim.tsx: -------------------------------------------------------------------------------- 1 | import { useContext, useEffect, useState } from "react"; 2 | import { useNavigate } from "react-router-dom"; 3 | import { Image } from "@/components/custom/image"; 4 | import { ImgKinglion, Feather_down, Feather_up } from "@/assets/imgs"; 5 | import { TelegramContext, TelegramUser } from "../contexts/TelegramContext"; 6 | import axios from "axios"; 7 | 8 | const Claim = () => { 9 | const navigate = useNavigate(); 10 | const currentUser = useContext(TelegramContext); 11 | const displayName = 12 | currentUser?.username || currentUser?.first_name || "Guest"; 13 | const [days, setDays] = useState(1); 14 | 15 | useEffect(() => { 16 | const fetchDays = async () => { 17 | try { 18 | const response = await axios.post( 19 | "https://simon.billtears76.workers.dev/score/get_continueDays", 20 | { username: displayName } 21 | ); 22 | setDays(response.data.continuedays || 1); 23 | console.log(response); 24 | } catch (error) { 25 | console.error("Failed to get days:", error); 26 | } 27 | }; 28 | fetchDays(); 29 | }, [displayName]); 30 | 31 | const getClaim = async () => { 32 | try { 33 | const response = await axios.post( 34 | "https://simon.billtears76.workers.dev/score/claim_daily_reward", 35 | { username: displayName } 36 | ); 37 | console.log(response); 38 | navigate("/"); 39 | } catch (error) { 40 | console.error("Failed to claim daily reward:", error); 41 | } 42 | }; 43 | 44 | return ( 45 |
46 |
47 |
48 |

49 | Daily check-in 50 |

51 |

Day {days}

52 |
53 |
54 |
55 |
56 |
57 | logo 58 |
59 |
60 |
61 |

62 | You got: 63 |

64 |
200 $King
65 |
66 | 72 | vector_down 77 | vector_up 82 |
83 |
84 |
85 |
86 | ); 87 | }; 88 | export default Claim; 89 | -------------------------------------------------------------------------------- /src/pages/Friends.tsx: -------------------------------------------------------------------------------- 1 | import { useContext, useEffect, useState } from "react"; 2 | import { BackImg } from "@/components/custom/backImg"; 3 | import { BackImgCommon } from "@/components/custom/backImgCommon"; 4 | import { Button } from "@/components/custom/button"; 5 | import { Image } from "@/components/custom/image"; 6 | import { StarIcon, UserBgIcon, Small_footprint } from "@/assets/imgs"; 7 | import { FaCheck } from "react-icons/fa6"; 8 | import { IoCopy } from "react-icons/io5"; 9 | import { IoIosShareAlt } from "react-icons/io"; 10 | import axios from "axios"; 11 | import { TelegramContext, TelegramUser } from "../contexts/TelegramContext"; 12 | 13 | interface Friend { 14 | avatar: string; 15 | username: string; 16 | ispremiumuser: string; 17 | score: string; 18 | } 19 | 20 | const botUrl = "https://t.me/tmakingliontestbot?start="; 21 | 22 | const Friends = () => { 23 | const [friends, setFriends] = useState([]); 24 | const [error, setError] = useState(null); 25 | const [copy, setCopy] = useState(false); 26 | const currentUser = useContext(TelegramContext); 27 | const displayName = 28 | currentUser?.username || currentUser?.first_name || "d_d_ross"; 29 | const inviteUrl = botUrl + (currentUser?.id || ""); 30 | const hiddenUrl = 31 | inviteUrl.split("").slice(8, 20).join("") + 32 | " . . . " + 33 | inviteUrl.split("").slice(-10).join(""); 34 | useEffect(() => { 35 | const getFriends = async () => { 36 | try { 37 | const response = await axios.post( 38 | "https://simon.billtears76.workers.dev/friend/get-invited-by-users", 39 | { username: displayName } 40 | ); 41 | setFriends(response.data); 42 | } catch (err) { 43 | setError("Failed to fetch users."); 44 | } 45 | }; 46 | getFriends(); 47 | }, [displayName]); 48 | 49 | console.log(friends); 50 | 51 | const onClipSave = () => { 52 | setCopy(true); 53 | navigator.clipboard.writeText(inviteUrl); 54 | setTimeout(() => { 55 | setCopy(false); 56 | }, 2000); 57 | }; 58 | 59 | const handleInvite = () => { 60 | const shareUrl = `https://t.me/share/url?url=${encodeURIComponent(inviteUrl)}`; 61 | if (window.Telegram?.WebApp?.openTelegramLink) { 62 | window.Telegram.WebApp.openTelegramLink(shareUrl); 63 | } else { 64 | alert("Sharing is not supported on this platform."); 65 | } 66 | }; 67 | 68 | if (error) return

{error}

; 69 | 70 | return ( 71 |
72 | {/* Main Content */} 73 |
74 | {/* Referral Program Section */} 75 |
76 |

77 | Referral Program 78 |

79 |

80 | Invite your friends and earn points 81 |

82 |
83 |
84 |
85 | {UserBgIcon} 90 |
91 |

92 | Common User 93 |

94 |

95 | +1000 96 |

97 |
98 |
99 | 100 | {/* Decorative Image */} 101 | Small footprint 106 |
107 |
108 | {/* User Info */} 109 |
110 | {StarIcon} 115 |
116 |

117 | Premium User 118 |

119 |

120 | +5000 121 |

122 |
123 |
124 | 125 | {/* Decorative Image */} 126 | Small footprint 131 |
132 |
133 | {/* Telegram Link */} 134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |

142 | Your link 143 |

144 |

145 | {hiddenUrl} 146 |

147 |
148 |
149 | {copy ? ( 150 | 153 | ) : ( 154 | 160 | )} 161 |
162 |
163 |
164 |
165 | 171 |
172 |
173 |
174 | Your friends ({friends.length}) 175 |
176 |
177 |
178 | {friends.length === 0 ? ( 179 | 180 |
181 |

182 | No friends yet... 183 |

184 |
185 |
186 | ) : ( 187 | friends?.map((data, index) => ( 188 | 189 |
190 | {/* User Info */} 191 |
192 | {data.avatar} 197 |
198 |
{data.username}
199 |

200 | {data.ispremiumuser 201 | ? "Premium User" 202 | : "Common User"} 203 |

204 |
205 |
206 |
207 |

208 | Your reward 209 |

210 |
{data.score}
211 |
212 |
213 |
214 | )) 215 | )} 216 |
217 |
218 |
219 |
220 | {/* Top Effect Overlay*/} 221 |
222 | 223 | {/* Bottom Effect Overlay */} 224 |
225 | 226 | {/* Bottom Effect2 Overlay*/} 227 |
228 | 229 | {/* Circle Blur Overlay */} 230 | {/*
*/} 231 |
232 | ); 233 | }; 234 | 235 | export default Friends; 236 | -------------------------------------------------------------------------------- /src/pages/Home.tsx: -------------------------------------------------------------------------------- 1 | import { useContext, useRef } from "react"; 2 | import { useNavigate } from "react-router-dom"; 3 | import { Image } from "@/components/custom/image"; 4 | import { FootPrint } from "@/assets/imgs"; 5 | import { VectorLeftIcon, VectorRightIcon } from "@/assets/icons"; 6 | import { TelegramContext } from "../contexts/TelegramContext"; 7 | 8 | const Home = () => { 9 | const navigate = useNavigate(); 10 | const playRef = useRef(null); 11 | 12 | // Get user data from Telegram WebApp 13 | // @ts-ignore 14 | const currentUser = useContext(TelegramContext); 15 | const displayName = 16 | currentUser?.username || currentUser?.first_name || "Guest"; 17 | const avatarUrl = 18 | currentUser?.photo_url || "https://i.postimg.cc/YSm0rKS7/User-35.png"; 19 | 20 | const play = () => { 21 | console.log(playRef.current, "adlfasljdfljsdlkj") 22 | if (playRef.current) { 23 | playRef.current.className = "text-white text-center pt-[50px] text-[40px] font-semibold animate-slideRotateOut"; 24 | } 25 | setTimeout(() => { 26 | navigate("/play"); 27 | }, 500); 28 | }; 29 | 30 | return ( 31 |
32 | {/* Header */} 33 |
34 |
35 | {avatarUrl} 36 |

{displayName}

37 |
38 |
39 |
Общая прибыль
40 |

1000 $King

41 |
42 |
43 | 44 | {/* Main Content */} 45 |
46 | {/* Background and blur elements */} 47 |
48 |
49 | 50 |
51 | {/* Main Effect */} 52 |
53 |
54 |
55 |
56 |
57 | 58 | {/* Down Gradient */} 59 |
60 | 61 | {/* Content with text */} 62 |
63 |

64 | Tap to play 65 |

66 |
67 |
68 | 72 |
73 | 74 | {/* Overlay with Footprint and Icons */} 75 |
83 |
84 | {/* Left Icons */} 85 |
86 | left_1 87 | left_2 88 |
89 | 90 | {/* Right Icons */} 91 |
92 | right_1 93 | right_2 94 |
95 |
96 |
97 |
98 |
99 |
100 | ); 101 | }; 102 | 103 | export default Home; 104 | -------------------------------------------------------------------------------- /src/pages/Leaderboard.tsx: -------------------------------------------------------------------------------- 1 | import { useContext, useEffect, useState } from "react"; 2 | import axios from "axios"; 3 | import { BackImgCommon } from "@/components/custom/backImgCommon"; 4 | import { Image } from "@/components/custom/image"; 5 | import { FootPrint, Small_footprint } from "@/assets/imgs"; 6 | import { GoldIcon, SilverIcon, BronzeIcon } from "@/assets/icons"; 7 | import { TelegramContext, TelegramUser } from "../contexts/TelegramContext"; 8 | 9 | interface User { 10 | username: string; 11 | point?: number; 12 | avatar: string; 13 | score?: number; 14 | ranking?: number; 15 | } 16 | 17 | const Leaderboard = () => { 18 | const [users, setUsers] = useState([]); 19 | const [userRank, setUserRank] = useState(null); 20 | const [totalUsers, setTotalUsers] = useState(0); 21 | const [error, setError] = useState(null); 22 | const currentUser = useContext(TelegramContext); 23 | const displayName = 24 | currentUser?.username || currentUser?.first_name || "Guest"; 25 | const avatarUrl = 26 | currentUser?.photo_url || "https://i.postimg.cc/YSm0rKS7/User-35.png"; 27 | 28 | useEffect(() => { 29 | const fetchTopUsers = async () => { 30 | try { 31 | const response = await axios.get( 32 | "https://simon.billtears76.workers.dev/score/get_top_users" 33 | ); 34 | const total = await axios.get( 35 | "https://simon.billtears76.workers.dev/auth/total-users" 36 | ); 37 | const user = await axios.post( 38 | "https://simon.billtears76.workers.dev/score/get_user_ranking", 39 | { username: displayName } 40 | ); 41 | setUserRank(user.data.userRanking); 42 | setUsers(response.data.topUsers); 43 | setTotalUsers(total.data.totalUsers); 44 | } catch (err) { 45 | setError("Failed to fetch users."); 46 | } 47 | }; 48 | fetchTopUsers(); 49 | }, [displayName]); 50 | if (error) return

{error}

; 51 | console.log(users); 52 | return ( 53 |
54 | {/* Main Content */} 55 |
56 | {/* Leaderboard Section */} 57 |
58 |

59 | Leaderboard 60 |

61 |
62 | {/* Blurred Background Effect */} 63 |
64 | 65 | {/* User Card */} 66 |
67 | {/* User Info */} 68 |
69 | {avatarUrl} 74 |
75 |

{displayName}

76 |

77 | {userRank ? `${userRank.point} points` : "000 points"} 78 |

79 |
80 |
81 |
82 | #{userRank?.ranking} 83 |
84 | 85 | {/* Decorative Image */} 86 | Small footprint 91 |
92 |
93 |
94 |
95 |
96 | {totalUsers} holders 97 |
98 |
99 |
100 | {users.map((data, index) => ( 101 | 106 |
107 |
108 | {data.avatar} 113 |
114 |

{data.username}

115 |

116 | {data.point} points 117 |

118 |
119 |
120 |
121 | {index === 0 ? ( 122 | GoldIcon 123 | ) : index === 1 ? ( 124 | SilverIcon 125 | ) : index === 2 ? ( 126 | BronzeIcon 127 | ) : ( 128 | `#${index + 1}` 129 | )} 130 |
131 |
132 |
133 | ))} 134 |
135 |
136 |
137 |
138 | 139 | {/* Footprint Background Effect */} 140 |
144 | 145 | {/* Long Blur Overlay */} 146 |
147 | 148 | {/* Bottom Effect Overlay */} 149 |
150 | 151 | {/* Bottom Gradient Overlay */} 152 |
153 | 154 | {/* Circle Blur Overlay */} 155 |
156 |
157 | ); 158 | }; 159 | 160 | export default Leaderboard; 161 | -------------------------------------------------------------------------------- /src/pages/Play.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect, useState } from "react"; 2 | import { Image } from "@/components/custom/image"; 3 | import { Button } from "@/components/custom/button"; 4 | import { ClaimModal } from "@/components/custom/claimModal"; 5 | import { TelegramContext, TelegramUser } from "../contexts/TelegramContext"; 6 | import axios from "axios"; 7 | 8 | import { 9 | VectorLeftIcon, 10 | VectorRightIcon, 11 | HeartEmptyIcon, 12 | HeartIcon, 13 | } from "@/assets/icons"; 14 | 15 | import { FootPrint, Boxlion_left, Boxlion_right } from "@/assets/imgs"; 16 | // import coin from "@/components/items/Coin"; 17 | // import booster from "@/components/items/Booster"; 18 | 19 | import bumb from "@/assets/icons/items/bumb.png"; // 4% 20 | import healthIcon from "@/assets/icons/items/health.png"; // 6% 21 | import speedup from "@/assets/icons/items/fire.png"; // 15% 22 | import fullhealth from "@/assets/icons/items/fullhealth.png"; // 15% 23 | import shield from "@/assets/icons/items/shield.png"; // 15% 24 | import slow from "@/assets/icons/items/slow.png"; // 15% 25 | import x2 from "@/assets/icons/items/x2.png"; // 15% 26 | 27 | import BigCoin from "@/assets/icons/items/bcoin.png"; // 5% score 10 28 | import SmallCoin from "@/assets/icons/items/scoin.png"; // 65% score 1 29 | import Cat from "@/assets/icons/items/cat.png"; // 15% score 3 30 | import Dog from "@/assets/icons/items/dog.png"; // 15% score 3 31 | 32 | const firstCoin = `data:image/png;base64,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`; 33 | 34 | const Play = () => { 35 | const currentUser = useContext(TelegramContext); 36 | const displayName = 37 | currentUser?.username || currentUser?.first_name || "Guest"; 38 | const avatarUrl = 39 | currentUser?.photo_url || "https://i.postimg.cc/YSm0rKS7/User-35.png"; 40 | 41 | interface LionData { 42 | id?: number; 43 | heart?: number; 44 | imageurl?: string; 45 | // Add other properties if needed 46 | } 47 | 48 | const [currentLionData, setCurrentLionData] = useState({}); 49 | const fianllyScore = 1000; 50 | // let catchCoinCounter = 0; 51 | const [catchCoinCounter, setCatchCoinCounter] = useState(0); 52 | 53 | const items = [speedup, fullhealth, healthIcon, shield, slow, x2]; 54 | const itemScore = [`speedup`, `fullhealth`, `health`, `shield`, `slow`, `x2`]; 55 | const [bombChance, setBombChance] = useState(0.05); 56 | 57 | const booster = () => { 58 | let type = 0; 59 | const random_num = Math.random(); 60 | // if (random_num < bombChance) type = 0; // 4% for bumb 61 | if (random_num < 0.1) type = 2; // 6% for health 62 | else if (random_num < 0.25) type = 0; // 15% for speedup 63 | else if (random_num < 0.4) type = 1; // 15% for fullhealth 64 | else if (random_num < 0.55) type = 3; // 15% for shield 65 | else if (random_num < 0.7) type = 4; // 15% for slow 66 | else type = 5; // 15% for x2 67 | 68 | return { item: items[type], score: itemScore[type] }; 69 | }; 70 | 71 | const bombCoin = () => { 72 | return { item: bumb, score: `bomb` }; 73 | }; 74 | 75 | const coin = () => { 76 | const items = [Cat, Dog, BigCoin, SmallCoin]; 77 | const appearanceRates = [15, 15, 5, 65]; 78 | const itemScore = [coinScore, coinScore, coinScore, coinScore]; 79 | let type = 0; 80 | 81 | const random = Math.random() * 100; 82 | let cumulativeRate = 0; 83 | for (let i = 0; i < appearanceRates.length; i++) { 84 | cumulativeRate += appearanceRates[i]; 85 | if (random < cumulativeRate) { 86 | type = i; 87 | break; 88 | } 89 | } 90 | 91 | return { item: items[type], score: itemScore[type] }; 92 | }; 93 | 94 | interface BoosterIcon { 95 | url: string; 96 | wid: number; 97 | score: string; 98 | } 99 | 100 | const [bombTime, setBombTime] = useState(0); 101 | const [time, setTime] = useState(0); 102 | const [boosterIcons, setBoosterIcons] = useState([]); 103 | const [currentScore, setCurrentScore] = useState(0); 104 | 105 | const [autoReceiveImage, setAutoReceiveImage] = useState( 106 | `/static/media/img_boxlion_left.9c5a19854930b2612a0a.png` 107 | ); 108 | const [autoReceiveCount, setAutoReceiveCount] = useState(1); 109 | const [autoReceivePosition, setAutoReceivePosition] = useState(1); 110 | 111 | let generateMulti = 0; 112 | const [generateSpeed, setGenerateSpeed] = useState(6000); 113 | const [generateEvent, setGenerateEvent] = useState(0); 114 | const [currentShowItems, setCurrentShowItems] = useState(1); 115 | 116 | const [speed, setSpeed] = useState(1300); 117 | const [firstCoinDelay, setFirstCoinDelay] = useState(true); 118 | const [previousLocation, setPreviousLocation] = useState(1000); 119 | 120 | const [boosterChance, setBoosterChance] = useState(0.1); 121 | const [coinCounter, setCoinCounter] = useState(0); 122 | const [coinScore, setCoinScore] = useState(1); 123 | 124 | const [showingItems, setShowingItems] = useState< 125 | { 126 | id: string; 127 | item: React.ReactNode; 128 | wid: number; 129 | top: number; 130 | pos: number; 131 | location: number; 132 | score: any; 133 | url: any; 134 | }[] 135 | >([]); 136 | 137 | useEffect(() => { 138 | const fetchCurrentData = async () => { 139 | try { 140 | // Fetch skins from API 141 | const current = await axios.post( 142 | "https://simon.billtears76.workers.dev/skin/get_skin_state", 143 | { username: displayName } 144 | ); 145 | setCurrentLionData(current.data.result); 146 | setHealth( 147 | current.data.result.heart 148 | ? Array(current.data.result.heart).fill(1) 149 | : [1, 1, 1, 1] 150 | ); 151 | } catch (error) { 152 | console.error("Failed to get skins:", error); 153 | } 154 | }; 155 | fetchCurrentData(); 156 | }, [displayName]); 157 | 158 | const [health, setHealth] = useState([1, 1, 1, 1]); 159 | const [showModal, setShowModal] = useState({ win: false, lose: false }); 160 | 161 | const [pos, setPos] = useState({ direction: Boxlion_left }); 162 | const [boosterScore2x, setBoosterScore2x] = useState(false); 163 | 164 | const [boosterShield, setBoosterShield] = useState(false); 165 | const [boosterEffectx2, setBoosterEffectx2] = useState(false); 166 | const [boosterEffectup, setBoosterEffectup] = useState(false); 167 | 168 | const [boosterEffectSlow, setBoosterEffectSlow] = useState(false); 169 | const [boosterEffectShield, setBoosterEffectShield] = useState(false); 170 | const [isGameRunning, setIsGameRunning] = useState(true); 171 | 172 | /////////////////////// 173 | // // 174 | // WIN OR LOSE // 175 | // STOP GAME // 176 | // // 177 | /////////////////////// 178 | 179 | const stopGame = () => { 180 | setIsGameRunning(false); 181 | setShowingItems([]); 182 | setBoosterIcons([]); 183 | setSpeed(1500); 184 | setCoinCounter(0); 185 | setBombChance(0.05); 186 | setBoosterChance(0.3); 187 | }; 188 | 189 | /////////////////////// 190 | // // 191 | // WIN OR LOSE // 192 | // POPUP // 193 | // // 194 | /////////////////////// 195 | 196 | const winOrFailModal = (str: string) => { 197 | if (str === "win") { 198 | setShowModal({ win: true, lose: false }); 199 | stopGame(); 200 | return; 201 | } else if (str === "lose") { 202 | setShowModal({ win: false, lose: true }); 203 | stopGame(); 204 | return; 205 | } 206 | }; 207 | 208 | /////////////////////// 209 | // // 210 | // 100 coin +1 // 211 | // 200 coin +1 // 212 | // ... // 213 | /////////////////////// 214 | 215 | useEffect(() => { 216 | if (catchCoinCounter !== 0 && catchCoinCounter % 100 === 0) { 217 | setCoinScore(coinScore + 1); 218 | } 219 | setCatchCoinCounter(catchCoinCounter + 1); 220 | }, [currentScore]); 221 | 222 | /////////////////////// 223 | // // 224 | // BUTTON // 225 | // CLICK EVENT // 226 | // // 227 | /////////////////////// 228 | 229 | const changePos = ( 230 | direction: string, 231 | count: number, 232 | position: number, 233 | fakeWid: number = 0 234 | ) => { 235 | setAutoReceiveImage(direction); 236 | setAutoReceiveCount(count); 237 | setAutoReceivePosition(position); 238 | 239 | // 1 : 1 = 1 240 | // 1 : -1 = 0 241 | // -1 : 1 = 3 242 | // -1 : -1 = 2 243 | setPos({ direction }); 244 | [...showingItems].forEach((item) => { 245 | if ( 246 | (count === 1 && position === 1 && item.location === 1) || 247 | (count === 1 && position === -1 && item.location === 0) || 248 | (count === -1 && position === 1 && item.location === 3) || 249 | (count === -1 && position === -1 && item.location === 2) 250 | ) { 251 | if (item.wid === 108 || item.wid === 81 || fakeWid === 108) { 252 | // setShowingItems((prevItems) => 253 | // prevItems.filter(it => it !== item) // Remove this coin 254 | // ); 255 | if (typeof item.score == `number`) { 256 | // coin 257 | if (currentScore + item.score >= fianllyScore) { 258 | winOrFailModal("win"); 259 | setCurrentScore((preScore) => 260 | boosterScore2x 261 | ? preScore + item.score * 2 262 | : preScore + item.score 263 | ); // add the coin's score 264 | } else { 265 | setCurrentScore((preScore) => 266 | boosterScore2x 267 | ? preScore + item.score * 2 268 | : preScore + item.score 269 | ); // add the coin's score 270 | } 271 | } else { 272 | if (item.score === "x2") { 273 | console.log("x2 =====> 🚀", `x2`); 274 | if (currentScore < 300) setBoosterScore2x(true); 275 | setTimeout(() => { 276 | let width = item.wid; 277 | setBoosterIcons((prevItem) => { 278 | return [...prevItem].filter( 279 | (it) => it.url !== item.url || it.wid !== width 280 | ); 281 | }); 282 | }, 60000); 283 | } 284 | 285 | if (item.score === "bomb") { 286 | console.log("bomb =====> 🚀", `bomb`, boosterShield); 287 | if (!boosterShield) { 288 | setHealth((preHealth) => preHealth.map((item) => 0)); 289 | winOrFailModal("lose"); 290 | } 291 | } 292 | 293 | if (item.score === "speedup") { 294 | const speedupResult = boosterIcons.filter( 295 | (item) => item.score === "speedup" 296 | ); 297 | console.log("speedup =====> 🚀", speedupResult.length); 298 | if (speedupResult.length > 0) return; 299 | setSpeed((speed) => speed / 2); 300 | setTimeout(() => { 301 | let width = item.wid; 302 | setBoosterIcons((prevItem) => 303 | [...prevItem].filter( 304 | (it) => it.url !== item.url || it.wid !== width 305 | ) 306 | ); 307 | }, 60000); 308 | } 309 | 310 | if (item.score === "slow") { 311 | const slowResult = boosterIcons.filter( 312 | (item) => item.score === "slow" 313 | ); 314 | console.log("slow =====> 🚀", slowResult.length); 315 | if (slowResult.length > 0) return; 316 | setSpeed((speed) => speed * 2); 317 | setTimeout(() => { 318 | let width = item.wid; 319 | setBoosterIcons((prevItem) => 320 | [...prevItem].filter( 321 | (it) => it.url !== item.url || it.wid !== width 322 | ) 323 | ); 324 | }, 60000); 325 | } 326 | 327 | if (item.score === "fullhealth") { 328 | console.log("fullhealth =====> 🚀", `fullhealth`); 329 | setHealth((preHealth) => preHealth.map((it) => 1)); 330 | } 331 | 332 | if (item.score === "health") { 333 | setHealth((preHealth) => { 334 | let boosterHealth = true; 335 | const newHealth = preHealth.map((it) => { 336 | if (it === 0 && boosterHealth === true) { 337 | boosterHealth = false; 338 | return 1; 339 | } 340 | return it; 341 | }); 342 | return newHealth; 343 | }); 344 | } 345 | 346 | if (item.score === "shield") { 347 | console.log("shield =====> 🚀", `shield`); 348 | setBoosterShield(true); 349 | setTimeout(() => { 350 | let width = item.wid; 351 | setBoosterIcons((prevItem) => 352 | [...prevItem].filter( 353 | (it) => it.url !== item.url || it.wid !== width 354 | ) 355 | ); 356 | }, 60000); 357 | } 358 | 359 | if ( 360 | item.score !== "fullhealth" && 361 | item.score !== "health" && 362 | item.score !== `bomb` 363 | ) { 364 | setBoosterIcons((prevItems) => { 365 | let flage = true; 366 | let result = [...prevItems].map((it) => { 367 | if (it.url === item.url) { 368 | it.wid = item.wid; 369 | flage = false; 370 | } 371 | return it; 372 | }); 373 | return flage 374 | ? [ 375 | ...result, 376 | { url: item.url, wid: item.wid, score: item.score }, 377 | ] 378 | : [...result]; 379 | }); 380 | } 381 | } 382 | setShowingItems((prevItem) => prevItem.filter((it) => it !== item)); 383 | setGenerateEvent((prev) => prev + 1); 384 | } 385 | } 386 | }); 387 | }; 388 | 389 | /////////////////////// 390 | // // 391 | // BOOSTER // 392 | // EFFECT // 393 | // // 394 | /////////////////////// 395 | 396 | useEffect(() => { 397 | if (!isGameRunning) return; 398 | 399 | const x2result = boosterIcons.filter((item) => item.score === "x2"); 400 | if (x2result.length > 0) { 401 | setBoosterEffectx2(true); 402 | } else { 403 | if (boosterEffectx2) { 404 | if (x2result.length <= 0) { 405 | setBoosterScore2x(false); 406 | setBoosterEffectx2(false); 407 | } 408 | } 409 | } 410 | 411 | const speedupResult = boosterIcons.filter( 412 | (item) => item.score === "speedup" 413 | ); 414 | if (speedupResult.length > 0) { 415 | setBoosterEffectup(true); 416 | } else { 417 | if (boosterEffectup) { 418 | if (speedupResult.length <= 0) { 419 | setSpeed(speed * 2); 420 | setBoosterEffectup(false); 421 | } 422 | } 423 | } 424 | 425 | const slowResult = boosterIcons.filter((item) => item.score === "slow"); 426 | if (slowResult.length > 0) { 427 | setBoosterEffectSlow(true); 428 | } else { 429 | if (boosterEffectSlow) { 430 | if (slowResult.length <= 0) { 431 | setSpeed(speed / 2); 432 | setBoosterEffectSlow(false); 433 | } 434 | } 435 | } 436 | 437 | const shieldResult = boosterIcons.filter((item) => item.score === "shield"); 438 | if (shieldResult.length > 0) { 439 | setBoosterEffectShield(true); 440 | } else { 441 | if (boosterEffectShield) { 442 | if (shieldResult.length <= 0) { 443 | setBoosterShield(false); 444 | setBoosterEffectShield(false); 445 | } 446 | } 447 | } 448 | }, [time]); 449 | 450 | ///////////////////////// 451 | // // 452 | // COIN // 453 | // GENERATE // 454 | // // 455 | ///////////////////////// 456 | 457 | const [score, setScore] = useState(1); 458 | const [url, setUrl] = useState(firstCoin); 459 | const [item, setItem] = useState( 460 |
461 | boost item 462 |
463 | ); 464 | 465 | const generateCoins = () => { 466 | if (generateMulti === generateSpeed) return; 467 | generateMulti = generateSpeed; 468 | 469 | const interval = setTimeout(() => { 470 | setTime((pre) => pre + 1); 471 | setGenerateSpeed((prev) => prev - 5); 472 | }, generateSpeed); 473 | 474 | const choose = Math.random(); 475 | const id = Date.now().toString(); 476 | const coins = coin(); 477 | const boosterCoins = booster(); 478 | const bomb = bombCoin(); 479 | setCoinCounter(coinCounter + 1); 480 | 481 | if (coinCounter !== 0 && coinCounter % 50 === 0) 482 | setCurrentShowItems((prev) => prev + 1); 483 | if (coinCounter !== 0 && coinCounter % 10 === 0) { 484 | if (bombChance < 0.3) { 485 | setBombChance(bombChance + 0.02); 486 | } 487 | if (boosterChance > 0.02) setBoosterChance(boosterChance - 0.02); 488 | if (speed > 200) setSpeed(speed - 10); 489 | } 490 | 491 | console.log( 492 | `choose -----------------------------------------------------------------------------------------${choose}` 493 | ); 494 | console.log( 495 | `speed ------------------------------------------------------------------------------------------${speed}` 496 | ); 497 | console.log( 498 | `bombChance -------------------------------------------------------------------------------------${bombChance}` 499 | ); 500 | console.log( 501 | `boosterChance ----------------------------------------------------------------------------------${boosterChance}` 502 | ); 503 | 504 | if (choose < bombChance) { 505 | const tem = ( 506 |
507 | bomb item 512 |
513 | ); 514 | setBombTime(1); 515 | setItem(tem); 516 | setScore(bomb.score); 517 | setUrl(bomb.item); 518 | } else if (choose < boosterChance + bombChance) { 519 | const tem = ( 520 |
521 | boost item 526 |
527 | ); 528 | setItem(tem); 529 | setScore(boosterCoins.score); 530 | setUrl(boosterCoins.item); 531 | } else { 532 | const tem = ( 533 |
534 | item 539 |
540 | ); 541 | setItem(tem); 542 | setScore(coins.score); 543 | setUrl(coins.item); 544 | } 545 | 546 | const location = Math.floor(Math.random() * 4); 547 | // if (previousLocation !== location || (previousLocation === location && typeof score != 'string')) { 548 | setShowingItems((prevItems) => [ 549 | ...prevItems, 550 | { 551 | id, 552 | item, 553 | top: location % 2 ? 10 : 160, 554 | wid: 0, 555 | pos: location < 2 ? 0 : 1, 556 | location: location, 557 | score, 558 | url, 559 | }, 560 | ]); 561 | // } 562 | 563 | // setPreviousLocation(location); 564 | return () => clearInterval(interval); 565 | }; 566 | 567 | useEffect(() => { 568 | if (!isGameRunning) return; 569 | if (showingItems.length === currentShowItems) return; 570 | if (firstCoinDelay) { 571 | setTimeout(() => { 572 | setFirstCoinDelay(false); 573 | generateCoins(); 574 | }, 2000); 575 | } else { 576 | generateCoins(); 577 | } 578 | }, [time, generateEvent]); 579 | 580 | /////////////////////// 581 | // // 582 | // LOSE !! // 583 | // CONDITION // 584 | // // 585 | /////////////////////// 586 | 587 | useEffect(() => { 588 | const dieResult = health.every((item) => item === 0); 589 | if (dieResult) { 590 | winOrFailModal("lose"); 591 | } 592 | }, [health]); 593 | 594 | /////////////////////// 595 | // // 596 | // COIN // 597 | // KILL OR AUTO // 598 | // // 599 | /////////////////////// 600 | 601 | useEffect(() => { 602 | const interval = setInterval(() => { 603 | let flage = true; 604 | setShowingItems( 605 | (prevItems) => 606 | prevItems 607 | .map(({ id, item, top, wid, pos, location, score, url }) => ({ 608 | id, 609 | item, 610 | top: top + 17, 611 | wid: wid + 27, 612 | pos, 613 | location, 614 | score, 615 | url, 616 | })) // Move items down 617 | .filter(({ wid, score, location }) => { 618 | if (wid === 108 && score !== 0) { 619 | if (location === 1) { 620 | if (autoReceiveCount === 1 && autoReceivePosition === 1) { 621 | changePos( 622 | autoReceiveImage, 623 | autoReceiveCount, 624 | autoReceivePosition, 625 | wid 626 | ); 627 | } else { 628 | if (typeof score == "number" && flage === true) { 629 | setHealth((preHealth) => { 630 | let newD = [...preHealth]; 631 | newD.shift(); 632 | newD.push(0); 633 | return newD; 634 | }); 635 | flage = false; 636 | } 637 | } 638 | } 639 | if (location === 0) { 640 | if (autoReceiveCount === 1 && autoReceivePosition === -1) { 641 | changePos( 642 | autoReceiveImage, 643 | autoReceiveCount, 644 | autoReceivePosition, 645 | wid 646 | ); 647 | } else { 648 | if (typeof score == "number" && flage === true) { 649 | setHealth((preHealth) => { 650 | let newD = [...preHealth]; 651 | newD.shift(); 652 | newD.push(0); 653 | return newD; 654 | }); 655 | flage = false; 656 | } 657 | } 658 | } 659 | if (location === 3) { 660 | if (autoReceiveCount === -1 && autoReceivePosition === 1) { 661 | changePos( 662 | autoReceiveImage, 663 | autoReceiveCount, 664 | autoReceivePosition, 665 | wid 666 | ); 667 | } else { 668 | if (typeof score == "number" && flage === true) { 669 | setHealth((preHealth) => { 670 | let newD = [...preHealth]; 671 | newD.shift(); 672 | newD.push(0); 673 | return newD; 674 | }); 675 | flage = false; 676 | } 677 | } 678 | } 679 | if (location === 2) { 680 | if (autoReceiveCount === -1 && autoReceivePosition === -1) { 681 | changePos( 682 | autoReceiveImage, 683 | autoReceiveCount, 684 | autoReceivePosition, 685 | wid 686 | ); 687 | } else { 688 | if (typeof score == "number" && flage === true) { 689 | setHealth((preHealth) => { 690 | let newD = [...preHealth]; 691 | newD.shift(); 692 | newD.push(0); 693 | return newD; 694 | }); 695 | flage = false; 696 | } 697 | } 698 | } 699 | } 700 | if (wid < 90) return wid; 701 | }) // Remove if off-screen 702 | ); 703 | }, speed); 704 | 705 | return () => clearInterval(interval); 706 | }, [autoReceiveCount, autoReceiveImage, autoReceivePosition]); 707 | 708 | useEffect(() => { 709 | setTimeout(() => { 710 | setBombTime(0); 711 | }, 1500); 712 | }, [bombTime]); 713 | 714 | return ( 715 |
716 | {/* Header */} 717 |
718 |
719 | {avatarUrl} 720 |

{displayName}

721 |
722 |
723 |
Общая прибыль
724 |

1000 $King

725 |
726 |
727 | 728 | {/* Main Content */} 729 |
730 | {/* Background and blur elements */} 731 |
732 |
733 |
734 | 735 | {/* Main Effect */} 736 |
737 |
738 |
739 |
740 |
741 | 742 | {/* Down Gradient */} 743 |
744 | 745 | {/* Content */} 746 |
747 |
748 |
749 | {health.slice(0, 4).map((item, index) => ( 750 | heart 755 | ))} 756 | {health.length > 4 && ( 757 |

758 | {health.filter((item) => item === 1).length > 4 759 | ? `+${health.filter((item) => item === 1).length - 4}` 760 | : ""} 761 |

762 | )} 763 |
764 |
765 | {currentScore}/ 766 | {fianllyScore} 767 |
768 |
769 | {boosterIcons.map((item) => ( 770 | booster Items 776 | ))} 777 |
778 |
779 | {bombTime === 1 && ( 780 | Bomb Effect w-[40px] h-[40px] 781 | )} 782 |
783 |
784 |
785 | {/* Background Glow */} 786 |
787 | 788 | {/* Boxlions */} 789 |
790 | Boxlion Left 795 |
796 |
797 | 798 | {/* Overlay with Footprint and Icons */} 799 |
807 |
808 | {/* Left Icons */} 809 |
810 | Vector Left Icon 1 815 | Vector Left Icon 2 820 |
821 | 822 | {/* Right Icons */} 823 |
824 | Vector Right Icon 1 829 | Vector Right Icon 2 834 |
835 | {showingItems.map(({ id, item, top, wid, pos }) => 836 | pos ? ( 837 |
842 | {item} 843 |
844 | ) : ( 845 |
850 | {item} 851 |
852 | ) 853 | )} 854 |
855 |
856 | 857 | {/* Button Section */} 858 |
859 |
860 | 878 | 896 |
897 |
898 | 916 | 934 |
935 |
936 |
937 |
938 | 939 | {/* Win Modal */} 940 | 945 |
946 | ); 947 | }; 948 | 949 | export default Play; 950 | -------------------------------------------------------------------------------- /src/pages/Quest.tsx: -------------------------------------------------------------------------------- 1 | import { BackImg } from "@/components/custom/backImg"; 2 | import { BackImgCommon } from "@/components/custom/backImgCommon"; 3 | import { CatBtn } from "@/components/custom/catBtn"; 4 | import { FootPrint } from "@/assets/imgs"; 5 | import { IoIosArrowForward } from "react-icons/io"; 6 | 7 | const tasks = [ 8 | { 9 | name: "Task name", 10 | check: true, 11 | points: "0.00", 12 | }, 13 | { 14 | name: "Task name", 15 | check: true, 16 | points: "0.00", 17 | }, 18 | { 19 | name: "Task name", 20 | check: false, 21 | points: "0.00", 22 | }, 23 | { 24 | name: "Task name", 25 | check: true, 26 | points: "0.00", 27 | }, 28 | { 29 | name: "Task name", 30 | check: true, 31 | points: "0.00", 32 | }, 33 | ]; 34 | 35 | const Quests = () => { 36 | return ( 37 |
38 |
46 | {/*main content */} 47 |
48 |

Quests

49 |

50 | Complete tasks, get rewarded,

move to the top and be the best. 51 |

52 | 57 |
58 |

Tasks list

59 |
60 | {tasks?.map((item, idx) => ( 61 | 66 |
67 |
68 |
69 |
70 |

{item.name}

71 |

72 | {item.points} points 73 |

74 |
75 |
76 |
77 | {item.check && ( 78 | 81 | )} 82 | 83 |
84 |
85 |
86 |
87 | ))} 88 |
89 |
90 |
91 | {/* Top Gradient Overlay */} 92 |
93 | {/* Bottom Gradient Overlay */} 94 |
95 | 96 | {/* Bottom Gradient-1 Overlay */} 97 |
98 |
99 | ); 100 | }; 101 | 102 | export default Quests; 103 | -------------------------------------------------------------------------------- /src/pages/Shop.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useContext } from "react"; 2 | import axios from "axios"; 3 | import { FootPrint } from "@/assets/imgs"; 4 | import { Drawer } from "@/components/custom/drawer"; 5 | import { CatBtn } from "@/components/custom/catBtn"; 6 | import { ShopItem } from "@/components/custom/shop_item"; 7 | import { TelegramContext, TelegramUser } from "../contexts/TelegramContext"; 8 | import WebApp from "@twa-dev/sdk"; 9 | 10 | interface ShopCard { 11 | itemname: string; 12 | id: number; 13 | imageurl: string; 14 | } 15 | 16 | interface CardDetail { 17 | itemname: string; 18 | description: string; 19 | price: number; 20 | imageurl: string; 21 | } 22 | 23 | const Shop = () => { 24 | const [drawerOpen, setDrawerOpen] = useState(false); 25 | const [index, setIndex] = useState(null); 26 | const [shopCards, setShopCards] = useState([]); 27 | const [cardDetail, setCardDetail] = useState(null); 28 | const [error, setError] = useState(null); 29 | const currentUser = useContext(TelegramContext); 30 | const chatId = currentUser ? currentUser.id : null; 31 | useEffect(() => { 32 | const fetchShopCards = async () => { 33 | try { 34 | const response = await axios.get( 35 | "https://simon.billtears76.workers.dev/item/info" 36 | ); 37 | setShopCards(response.data.items); 38 | } catch (err) { 39 | setError("Failed to fetch users."); 40 | } 41 | }; 42 | 43 | fetchShopCards(); 44 | }, []); 45 | 46 | useEffect(() => { 47 | setIndex(index); 48 | }, [index]); 49 | 50 | useEffect(() => { 51 | if (index !== null) { 52 | const fetchCardDetail = async () => { 53 | try { 54 | const response = await axios.post( 55 | "https://simon.billtears76.workers.dev/item/item-info", 56 | { itemId: index } 57 | ); 58 | setCardDetail(response.data.item); 59 | } catch (err) { 60 | setError("Failed to fetch card details."); 61 | } 62 | }; 63 | 64 | fetchCardDetail(); 65 | } 66 | }, [index]); 67 | 68 | if (error) return

{error}

; 69 | 70 | const handleDrawerOpen = (idx: number) => { 71 | setCardDetail(null); 72 | setIndex(idx); 73 | setDrawerOpen(true); 74 | }; 75 | 76 | const handleDrawerClose = () => { 77 | setDrawerOpen(false); 78 | setTimeout(() => { 79 | setIndex(null); 80 | }, 200); 81 | }; 82 | 83 | const handleBuy = async () => { 84 | if (!chatId) { 85 | alert("Please login to buy."); 86 | return; 87 | } 88 | 89 | try { 90 | const amount = 50; 91 | 92 | const response = await axios.post( 93 | "https://simon.billtears76.workers.dev/stars/buy_product", 94 | { chatId, amount } 95 | ); 96 | const data = response.data; 97 | if (data.ok) { 98 | WebApp.openInvoice(data.result); 99 | console.log("Invoice opended successfully"); 100 | } else { 101 | window.location.href = data.result; 102 | } 103 | } catch (error) { 104 | console.error("Error during payment process:", error); 105 | } 106 | 107 | setDrawerOpen(false); 108 | setTimeout(() => { 109 | setIndex(null); 110 | }, 200); 111 | }; 112 | 113 | return ( 114 | <> 115 |
116 | {/* Main Content */} 117 |
118 | {/* Navigation Toggle */} 119 | 124 | {/* Shop Items */} 125 |
126 | {shopCards.map((item, idx) => ( 127 | handleDrawerOpen(item.id)} 132 | /> 133 | ))} 134 |
135 |
136 | 137 | {/* Top Effect Overlay */} 138 |
139 | 140 | {/* Bottom Gradient Overlay */} 141 |
142 | 143 | {/* FootPrint Effect */} 144 |
152 | 153 | {/* Bottom Gradient-1 Overlay */} 154 |
155 |
156 | 157 | {/* Drawer Component */} 158 | {index !== null && cardDetail && ( 159 |
160 | 169 |
170 | )} 171 | 172 | ); 173 | }; 174 | 175 | export default Shop; 176 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /src/router/ProtectedRoute.tsx: -------------------------------------------------------------------------------- 1 | import { useContext, useEffect, useState } from "react"; 2 | import { Navigate, useLocation } from "react-router-dom"; 3 | import { TelegramContext } from '../contexts/TelegramContext'; 4 | import axios from "axios"; 5 | // import { calculateDateDifference } from "@/lib/utils"; 6 | 7 | interface ProtectedRouteProps { 8 | children: React.ReactNode; 9 | } 10 | 11 | const ProtectedRoute = ({ children }: ProtectedRouteProps) => { 12 | const [shouldRedirect, setShouldRedirect] = useState(null); 13 | const currentUser = useContext(TelegramContext); 14 | const location = useLocation(); 15 | const displayName = currentUser?.username || currentUser?.first_name || 'Guest'; 16 | 17 | useEffect(() => { 18 | const checkUserAccess = async () => { 19 | try { 20 | const response = await axios.post( 21 | "https://simon.billtears76.workers.dev/score/difference_in_days", 22 | { username: displayName } 23 | ); 24 | // const response = await axios.post( 25 | // "https://simon.billtears76.workers.dev/score/get_last_check_date", 26 | // { username: displayName } 27 | // ); 28 | // const currentServerDate = await axios.get( 29 | // "https://simon.billtears76.workers.dev/score/get_current_date_time" 30 | // ); 31 | 32 | const differenceDays = response.data.difference; 33 | // const fetchedCurrentDate = currentServerDate.data.currentDateTime; 34 | // const differenceDays = calculateDateDifference(fetchedClaimDate, fetchedCurrentDate ); 35 | 36 | if (differenceDays !== 0) { 37 | // If user hasn't claimed today, redirect to claim page unless already there 38 | if (location.pathname !== "/claim") { 39 | setShouldRedirect("/claim"); 40 | } 41 | } else { 42 | // If user has claimed today, prevent access to claim page 43 | if (location.pathname === "/claim") { 44 | setShouldRedirect("/"); 45 | } 46 | } 47 | } catch (error) { 48 | console.error("Error checking user access:", error); 49 | } 50 | }; 51 | checkUserAccess(); 52 | }, [displayName, location.pathname]); 53 | 54 | if (shouldRedirect) { 55 | return ; 56 | } 57 | 58 | return <>{children}; 59 | }; 60 | 61 | export default ProtectedRoute; -------------------------------------------------------------------------------- /src/router/index.tsx: -------------------------------------------------------------------------------- 1 | import { Route, Routes } from "react-router-dom"; 2 | import ProtectedRoute from "@/router/ProtectedRoute"; 3 | import Claim from "@/pages/Claim"; 4 | import Home from "@/pages/Home"; 5 | import Play from "@/pages/Play"; 6 | import Shop from "@/pages/Shop"; 7 | import Leaderboard from "@/pages/Leaderboard"; 8 | import Friends from "@/pages/Friends"; 9 | import Quests from "@/pages/Quest"; 10 | import Card from "@/pages/Card"; 11 | 12 | const Router = () => { 13 | return ( 14 | 15 | } /> 16 | 20 | 21 | 22 | } 23 | /> 24 | 28 | 29 | 30 | } 31 | /> 32 | 36 | 37 | 38 | } 39 | /> 40 | 44 | 45 | 46 | } 47 | /> 48 | 52 | 53 | 54 | } 55 | /> 56 | 60 | 61 | 62 | } 63 | /> 64 | 68 | 69 | 70 | } 71 | /> 72 | 73 | ); 74 | }; 75 | 76 | export default Router; 77 | -------------------------------------------------------------------------------- /src/styles/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | .main { 16 | min-height: 100vh; 17 | color: white; 18 | } 19 | 20 | .App-link { 21 | color: #61dafb; 22 | } 23 | 24 | @keyframes App-logo-spin { 25 | from { 26 | transform: rotate(0deg); 27 | } 28 | to { 29 | transform: rotate(360deg); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | darkMode: ["class"], 4 | content: [ 5 | "./src/**/*.{html,js,jsx,ts,tsx}", 6 | "./src/components/**/*.{html,js,jsx,ts,tsx}", 7 | "./src/pages/**/*.{html,js,jsx,ts,tsx}", 8 | "./public/index.html", 9 | ], 10 | prefix: "", 11 | theme: { 12 | container: { 13 | center: true, 14 | padding: "2rem", 15 | screens: { 16 | "2xl": "1400px", 17 | }, 18 | }, 19 | extend: { 20 | backdropBlur: { 21 | "25px": "25px", 22 | }, 23 | colors: { 24 | border: "hsl(var(--border))", 25 | input: "hsl(var(--input))", 26 | ring: "hsl(var(--ring))", 27 | background: "hsl(var(--background))", 28 | foreground: "hsl(var(--foreground))", 29 | primary: { 30 | DEFAULT: "hsl(var(--primary))", 31 | foreground: "hsl(var(--primary-foreground))", 32 | }, 33 | secondary: { 34 | DEFAULT: "hsl(var(--secondary))", 35 | foreground: "hsl(var(--secondary-foreground))", 36 | }, 37 | destructive: { 38 | DEFAULT: "hsl(var(--destructive))", 39 | foreground: "hsl(var(--destructive-foreground))", 40 | }, 41 | muted: { 42 | DEFAULT: "hsl(var(--muted))", 43 | foreground: "hsl(var(--muted-foreground))", 44 | }, 45 | accent: { 46 | DEFAULT: "hsl(var(--accent))", 47 | foreground: "hsl(var(--accent-foreground))", 48 | }, 49 | popover: { 50 | DEFAULT: "hsl(var(--popover))", 51 | foreground: "hsl(var(--popover-foreground))", 52 | }, 53 | card: { 54 | DEFAULT: "hsl(var(--card))", 55 | foreground: "hsl(var(--card-foreground))", 56 | }, 57 | }, 58 | borderRadius: { 59 | lg: "var(--radius)", 60 | md: "calc(var(--radius) - 2px)", 61 | sm: "calc(var(--radius) - 4px)", 62 | }, 63 | keyframes: { 64 | slideIn: { 65 | "0%": { transform: "translateY(100%)", opacity: "0" }, 66 | "100%": { transform: "translateY(0)", opacity: "1" }, 67 | }, 68 | slideOut: { 69 | "0%": { transform: "translateY(0)", opacity: "1" }, 70 | "100%": { transform: "translateY(100%)", opacity: "0" }, 71 | }, 72 | slideRotateOut: { 73 | "0%": { transform: "translateY(0) rotate(0deg)", opacity: "1" }, 74 | "100%": { transform: "translateY(100%) rotate(180deg)", opacity: "0" }, 75 | }, 76 | 77 | rotateCustomRight: { 78 | "0%": { transform: "rotate(0deg)" }, 79 | "100%": { transform: "rotate(360deg)" }, 80 | }, 81 | rotateCustomLeft: { 82 | "0%": { transform: "rotate(0deg)" }, 83 | "100%": { transform: "rotate(-360deg)" }, 84 | }, 85 | }, 86 | animation: { 87 | slideIn: "slideIn 0.3s ease-out", 88 | slideOut: "slideOut 0.3s ease-in", 89 | slideRotateOut : "slideRotateOut 0.5s ease-in", 90 | rotateCustomRight: "rotateCustomRight 3s linear infinite", 91 | rotateCustomLeft: "rotateCustomLeft 3s linear infinite", 92 | }, 93 | }, 94 | }, 95 | plugins: [require("tailwindcss-animate")], 96 | }; 97 | -------------------------------------------------------------------------------- /test.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "1741042943171", 4 | "item": { 5 | "type": "div", 6 | "key": null, 7 | "ref": null, 8 | "props": { 9 | "className": "w-[40px] h-[40px]", 10 | "children": { 11 | "type": "img", 12 | "key": null, 13 | "ref": null, 14 | "props": { 15 | "src": "data:image/png;base64,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", 16 | "alt": "boost itme", 17 | "className": "w-full h-full object-cover" 18 | }, 19 | "_owner": null, 20 | "_store": {} 21 | } 22 | }, 23 | "_owner": null, 24 | "_store": {} 25 | }, 26 | "top": 52, 27 | "wid": 70, 28 | "pos": 0, 29 | "location": 1, 30 | "score": 1 31 | } 32 | ] -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "@/*": ["./src/*"] 6 | }, 7 | "target": "ES6", 8 | "lib": [ 9 | "dom", 10 | "dom.iterable", 11 | "esnext" 12 | ], 13 | "allowJs": true, 14 | "skipLibCheck": true, 15 | "esModuleInterop": true, 16 | "allowSyntheticDefaultImports": true, 17 | "strict": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "noFallthroughCasesInSwitch": true, 20 | "module": "esnext", 21 | "moduleResolution": "node", 22 | "resolveJsonModule": true, 23 | "isolatedModules": true, 24 | "noEmit": true, 25 | "jsx": "react-jsx" 26 | }, 27 | "include": [ 28 | "src", 29 | "**/*.ts", 30 | "**/*.tsx", 31 | ] 32 | } 33 | --------------------------------------------------------------------------------