├── .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 | # l i o n _ k i n g _ g a m e
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 |
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 |
--------------------------------------------------------------------------------
/src/assets/icons/src/friendFullIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/src/friendIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/src/assets/icons/src/heartIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/src/homeFullIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/src/homeIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/src/leadersFullIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/src/leadersIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/src/menuFullIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/src/menuIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/src/questsFullIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/src/questsIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/src/shopFullIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/src/shopIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/src/assets/icons/src/vectorRightIcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/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 |
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 |
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 |
90 |
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 |

58 |
59 | {description}
60 |
61 |
62 | Cost: {cost}$King
63 |
64 |
65 |
71 |
76 |
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 |
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 &&

}
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 && }
25 | {children}
26 |
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 |
54 |
59 | Main
60 |
61 |
62 |
63 |
64 | {/* Quests */}
65 |
66 |
67 |
72 |
79 | Quests
80 |
81 |
82 |
83 |
84 | {/* Cards */}
85 |
86 |
87 |
92 |
97 | Cards
98 |
99 |
100 |
101 |
102 | {/* Shop */}
103 |
104 |
105 |
110 |
115 | Shop
116 |
117 |
118 |
119 |
120 | {/* Friends */}
121 |
122 |
123 |
128 |
135 | Friends
136 |
137 |
138 |
139 |
140 | {/* Leaders */}
141 |
142 |
143 |
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 |
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 |
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 |
172 |
173 |
174 | ) : (
175 |
181 |
setIndex(idx)}
184 | >
185 |
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 |
60 |
61 |
62 | You got:
63 |
64 |
200 $King
65 |
66 |
72 |
77 |
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 |
90 |
91 |
92 | Common User
93 |
94 |
95 | +1000
96 |
97 |
98 |
99 |
100 | {/* Decorative Image */}
101 |
106 |
107 |
108 | {/* User Info */}
109 |
110 |
115 |
116 |
117 | Premium User
118 |
119 |
120 | +5000
121 |
122 |
123 |
124 |
125 | {/* Decorative Image */}
126 |
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 |
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 |
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 |
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 |
87 |
88 |
89 |
90 | {/* Right Icons */}
91 |
92 |
93 |
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 |
74 |
75 |
{displayName}
76 |
77 | {userRank ? `${userRank.point} points` : "000 points"}
78 |
79 |
80 |
81 |
82 | #{userRank?.ranking}
83 |
84 |
85 | {/* Decorative Image */}
86 |
91 |
92 |
93 |
94 |
95 |
96 | {totalUsers} holders
97 |
98 |
99 |
100 | {users.map((data, index) => (
101 |
106 |
107 |
108 |
113 |
114 |
{data.username}
115 |
116 | {data.point} points
117 |
118 |
119 |
120 |
121 | {index === 0 ? (
122 |
123 | ) : index === 1 ? (
124 |
125 | ) : index === 2 ? (
126 |
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 |

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 |

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 |

526 |
527 | );
528 | setItem(tem);
529 | setScore(boosterCoins.score);
530 | setUrl(boosterCoins.item);
531 | } else {
532 | const tem = (
533 |
534 |

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 |
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 |
741 |
742 | {/* Down Gradient */}
743 |
744 |
745 | {/* Content */}
746 |
747 |
748 |
749 | {health.slice(0, 4).map((item, index) => (
750 |
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 |
776 | ))}
777 |
778 |
779 | {bombTime === 1 && (
780 |
781 | )}
782 |
783 |
784 |
785 | {/* Background Glow */}
786 |
787 |
788 | {/* Boxlions */}
789 |
790 |
795 |
796 |
797 |
798 | {/* Overlay with Footprint and Icons */}
799 |
807 |
808 | {/* Left Icons */}
809 |
810 |
815 |
820 |
821 |
822 | {/* Right Icons */}
823 |
824 |
829 |
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 |
--------------------------------------------------------------------------------