diff --git a/.env b/.env new file mode 100644 index 0000000..9598b19 --- /dev/null +++ b/.env @@ -0,0 +1,11 @@ +NEXT_PUBLIC_ENABLE_TESTNETS=true +NEXT_PUBLIC_CONTRACT_LOVE_FARM=0xb27D69d0097d9e59657C0dbbf59d3Da103845A2b +NEXT_PUBLIC_CONTRACT_LOVE_ETH_LP=0x88a464De7EFC2a4009dD9D2a113db7A87D20B1F6 +NEXT_PUBLIC_CONTRACT_LOVE_CLAIM=0xbFE325f40e5A19Ce2d7E0472B7CA5441e3F4aA2E +NEXT_PUBLIC_CONTRACT_LOVE=0xA530A26BF718689CDeBADDefB11dA54d81669E33 +NEXT_PUBLIC_CONTRACT_USDETHPoolAddy=0x28cee28a7C4b4022AC92685C07d2f33Ab1A0e122 +NEXT_PUBLIC_CONTRACT_ETHLOVEPoolAddy=0x88a464De7EFC2a4009dD9D2a113db7A87D20B1F6 +NEXT_PUBLIC_CONTRACT_USDCAddress=0x28cee28a7C4b4022AC92685C07d2f33Ab1A0e122 +NEXT_PUBLIC_API=http://localhost:3030 +NEXT_PUBLIC_JSON_RPC_URL= +MONGOO_URL= \ No newline at end of file diff --git a/assets/active-game-button.png b/assets/active-game-button.png new file mode 100644 index 0000000..e8798b5 Binary files /dev/null and b/assets/active-game-button.png differ diff --git a/assets/dead-game-button.png b/assets/dead-game-button.png new file mode 100644 index 0000000..9919187 Binary files /dev/null and b/assets/dead-game-button.png differ diff --git a/assets/half-heart-break.svg b/assets/half-heart-break.svg new file mode 100644 index 0000000..b1c5a28 --- /dev/null +++ b/assets/half-heart-break.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/heart-static.svg b/assets/heart-static.svg new file mode 100644 index 0000000..25a9ee0 --- /dev/null +++ b/assets/heart-static.svg @@ -0,0 +1,23 @@ + + + + + + + + + + diff --git a/assets/heart_beating.gif b/assets/heart_beating.gif new file mode 100644 index 0000000..6974d6c Binary files /dev/null and b/assets/heart_beating.gif differ diff --git a/components/bottombar.tsx b/components/bottombar.tsx index c5576e3..6489d37 100644 --- a/components/bottombar.tsx +++ b/components/bottombar.tsx @@ -29,6 +29,11 @@ const BottomBar = (props: Props) => { icon: Paper, name: "PAPER", }, + { + menu: "heartbreaker", + icon: "/assets/start-icon.png", + name: "HEARTBREAKER", + }, { menu: "cp", icon: Setting, diff --git a/components/heartbreaker.tsx b/components/heartbreaker.tsx new file mode 100644 index 0000000..bfa189a --- /dev/null +++ b/components/heartbreaker.tsx @@ -0,0 +1,19 @@ +import Control from "./heartbreaker/control"; +import Features from "./heartbreaker/features"; +import Game from "./heartbreaker/game"; + +export const HeartBreaker = () => { + return ( +
+
+
+ +
+ +
+
+ +
+
+ ); +}; diff --git a/components/heartbreaker/chatbox.tsx b/components/heartbreaker/chatbox.tsx new file mode 100644 index 0000000..64c0b19 --- /dev/null +++ b/components/heartbreaker/chatbox.tsx @@ -0,0 +1,19 @@ +const ChatBox = () => { + return ( +
+
+
+
0x23234..:
+
asdasd
+
+
+ +
+ ); +}; + +export default ChatBox; diff --git a/components/heartbreaker/connect.tsx b/components/heartbreaker/connect.tsx new file mode 100644 index 0000000..ea5574a --- /dev/null +++ b/components/heartbreaker/connect.tsx @@ -0,0 +1,66 @@ +import { ConnectButton } from "@rainbow-me/rainbowkit"; +import Image from "next/image"; + +export const ConnectHeartBreak = () => { + return ( + + {({ + account, + chain, + openAccountModal, + openChainModal, + openConnectModal, + authenticationStatus, + mounted, + }) => { + // Note: If your app doesn't use authentication, you + // can remove all 'authenticationStatus' checks + const ready = mounted && authenticationStatus !== "loading"; + const connected = + ready && + account && + chain && + (!authenticationStatus || authenticationStatus === "authenticated"); + return ( +
+ {(() => { + if (!connected) { + return ( + + ); + } + return ( +
+
+
Wallet Connected
+
{account.displayName}
+
+ +
+ ); + })()} +
+ ); + }} +
+ ); +}; diff --git a/components/heartbreaker/control.tsx b/components/heartbreaker/control.tsx new file mode 100644 index 0000000..b18ab79 --- /dev/null +++ b/components/heartbreaker/control.tsx @@ -0,0 +1,85 @@ +import Image from "next/image"; +import DeadButton from "../../assets/dead-game-button.png"; +import ActiveButton from "../../assets/active-game-button.png"; +import { useState } from "react"; +import { ConnectHeartBreak } from "./connect"; +const Control = () => { + const points = [10, 20, 30, 40]; + const [selectedPoint, setSelectedPoint] = useState(10); + const [active, setActive] = useState(false); + return ( +
+
+ +
+
+
+
+
$LOVE AVAILABLE
+
0
+
+
+ +
+ + +
+
+
+
+ +
+ {points.map((val, index) => { + return ( +
setSelectedPoint(val)} + key={index} + className={`${ + selectedPoint == val ? "bg-[#0A0080] text-white" : "" + } border-2 border-[#0A0080] text-[12px] text-[#0A0080] px-[6px] rounded-sm font-bold text-center flex flex-row items-center`} + > + {val} {"%"} +
+ ); + })} +
+
+ +
+
+
+
PLAY
+
0
+
+
+ +
+
+
+
+
+
+ ); +}; +export default Control; diff --git a/components/heartbreaker/features.tsx b/components/heartbreaker/features.tsx new file mode 100644 index 0000000..edd9418 --- /dev/null +++ b/components/heartbreaker/features.tsx @@ -0,0 +1,57 @@ +import { useState } from "react"; +import { StakingSelectTab } from "../ui/StakingSelectTab"; +import HeartBreakTable from "./table"; +import { HeartBreakTab } from "./tab"; +import ChatBox from "./chatbox"; + +const Features = () => { + const [tab, setTab] = useState("history"); + const tabList = [ + { + title: "History", + key: "history", + }, + { + title: "LeaderBoard", + key: "leaderboard", + }, + { + title: "Chat", + key: "chat", + }, + ]; + + const renderBody = () => { + switch (tab) { + case "history": + return ; + case "leaderboard": + return ; + case "chat": + return ; + default: + break; + } + }; + return ( +
+
+ {tabList.map((list, index) => { + return ( + { + setTab(list.key); + }} + isSelected={tab == list.key} + /> + ); + })} +
+
{renderBody()}
+
+ ); +}; + +export default Features; diff --git a/components/heartbreaker/game.tsx b/components/heartbreaker/game.tsx new file mode 100644 index 0000000..47c31e6 --- /dev/null +++ b/components/heartbreaker/game.tsx @@ -0,0 +1,174 @@ +import React, { useState, useRef, useEffect } from "react"; +import { gsap, TweenLite, TweenMax } from "gsap"; +import Image from "next/image"; +import Heart from "../../assets/heart_beating.gif"; +import HeartStatic from "../../assets/heart-static.svg"; +import HeartBreakImage from "../../assets/half-heart-break.svg"; + +gsap.registerPlugin(TweenLite); + +const Game = () => { + const [bgImage, setBgImage] = useState("/assets/screen-bg.jpg"); + const bgImage2 = "/assets/bg-loop.png"; + const [isAnimating, setIsAnimating] = useState(true); + const bgRef = useRef(null); + const heartRef: any = useRef(null); + const tween: any = useRef(null); + const heartTween: any = useRef(null); + const [dimensions, setDimensions] = useState({ width: 120, height: 120 }); + const [heartImage, setHeartImage] = useState(HeartStatic); + const [bottomSpace, setBottomSpace] = useState(false); + const startSound = useRef(new Audio("/assets/beat.mp3")); + const stopSound = useRef(new Audio("/assets/break.wav")); + + startSound.current.loop = true; + + useEffect(() => { + TweenLite.set(bgRef.current, { + backgroundPosition: "0 100%", + }); + + tween.current = TweenLite.to(bgRef.current, 20, { + backgroundPosition: "0 0%", + paused: true, + ease: "none", + onComplete: () => { + if (bgImage !== bgImage2) { + setBgImage(bgImage2); + } else { + setBgImage("/assets/screen-bg.png"); + } + tween.current.restart(); + }, + }); + + heartTween.current = gsap.to(heartRef.current.firstChild, 6, { + css: { + height: "200px", + width: "200px", + transformOrigin: "50% 50%", + transform: "translateY(16px)", + }, + onComplete: () => { + tween.current.restart(); + }, + paused: true, + }); + }, []); + + const handleStartStopClick = () => { + if (isAnimating) { + startSound.current.play(); + setHeartImage(Heart); + setBottomSpace(true); + heartTween.current.resume(); + } + }; + + const handleStop = () => { + if (isAnimating && bottomSpace) { + setDimensions({ + width: heartRef.current.firstChild.offsetWidth, + height: heartRef.current.firstChild.offsetHeight, + }); + + heartRef.current.firstChild.style.width = `${ + heartRef.current.firstChild.offsetWidth - 20 + }px`; + heartRef.current.firstChild.style.height = `${ + heartRef.current.firstChild.offsetHeight - 20 + }px`; + heartRef.current.firstChild.style.transform = `translateY(2px)`; + setIsAnimating(false); + tween.current.pause(); + heartTween.current.pause(); + setBottomSpace(false); + + startSound.current.pause(); + startSound.current.currentTime = 0; + stopSound.current.play(); + } + }; + + const handleResetClick = () => { + setBottomSpace(false); + setIsAnimating(true); + setHeartImage(HeartStatic); + setBgImage("/assets/screen-bg.jpg"); + TweenLite.set(bgRef.current, { + backgroundPosition: "0 100%", + }); + + if (tween.current) { + tween.current.progress(0).pause(); + } + + TweenLite.set(heartRef.current, { + scale: 1, + }); + + TweenLite.set(heartRef.current.firstChild, { + css: { + height: "120px", + width: "120px", + transformOrigin: "50% 50%", + }, + }); + + if (heartTween.current) { + heartTween.current.progress(0).pause(); + } + + startSound.current.pause(); + startSound.current.currentTime = 0; + }; + + return ( +
+
+
+ heart +
+
+ + + + +
+
+
+ ); +}; + +export default Game; diff --git a/components/heartbreaker/tab.tsx b/components/heartbreaker/tab.tsx new file mode 100644 index 0000000..59aa44b --- /dev/null +++ b/components/heartbreaker/tab.tsx @@ -0,0 +1,23 @@ +interface IStakingSelectTabProps { + onClick: () => void; + isSelected: boolean; + title: string; +} + +export const HeartBreakTab = ({ + onClick, + isSelected, + title, +}: IStakingSelectTabProps) => { + return ( +
+ {title} + {isSelected &&
} +
+ ); +}; diff --git a/components/heartbreaker/table.tsx b/components/heartbreaker/table.tsx new file mode 100644 index 0000000..60ce6dc --- /dev/null +++ b/components/heartbreaker/table.tsx @@ -0,0 +1,25 @@ +const HeartBreakTable = () => { + const headerList = ["Round", "Crash", "Date/Time", "Total Play", "Total Won"]; + return ( +
+
+
+
+ {headerList.map((item, index) => { + return ( +
+ {item} +
+ ); + })} +
+
+
+
+ ); +}; + +export default HeartBreakTable; diff --git a/package.json b/package.json index 475a597..612f27d 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "autoprefixer": "^10.4.14", "axios": "^1.4.0", "ethers": "5", + "gsap": "^3.12.1", "husky": "^8.0.3", "moment": "^2.29.4", "mongoose": "^7.3.0", diff --git a/pages/api/markle.ts b/pages/api/markle.ts index 3b84a38..39f1658 100644 --- a/pages/api/markle.ts +++ b/pages/api/markle.ts @@ -6,7 +6,7 @@ import Mongoose from "mongoose"; import { MONGOO_URL } from "../../utils/constant"; const uri = MONGOO_URL; -export const runtime = 'edge' +// export const runtime = 'edge' const handler = async (req: NextApiRequest, res: NextApiResponse) => { Mongoose.connect(uri) diff --git a/pages/win98/index.tsx b/pages/win98/index.tsx index 7764a3f..35667a0 100644 --- a/pages/win98/index.tsx +++ b/pages/win98/index.tsx @@ -32,6 +32,7 @@ import { PoolAbi } from "../../system/PoolAbi"; import { AppContracts } from "../../system/AppContracts"; import { CopyAddressButton } from "../../components/copyAddressButton"; import { useWrongNetwork } from "../../system/hooks/useWrongNetwork"; +import { HeartBreaker } from "../../components/heartbreaker"; interface Props { lock?: Boolean; @@ -181,6 +182,14 @@ const Win98 = (props: Props) => { height: "400px", icon: PaperIcon, }, + { + menu: "heartbreaker", + title: "HEARTBREAKER", + component: , + width: "60%", + height: "100%", + icon: PaperIcon, + }, { menu: "cp", title: "ERROR!", diff --git a/public/assets/beat.mp3 b/public/assets/beat.mp3 new file mode 100644 index 0000000..f23a256 Binary files /dev/null and b/public/assets/beat.mp3 differ diff --git a/public/assets/bg-loop.jpg b/public/assets/bg-loop.jpg new file mode 100644 index 0000000..0a76d98 Binary files /dev/null and b/public/assets/bg-loop.jpg differ diff --git a/public/assets/bg-loop.png b/public/assets/bg-loop.png new file mode 100644 index 0000000..2a3ef86 Binary files /dev/null and b/public/assets/bg-loop.png differ diff --git a/public/assets/break.wav b/public/assets/break.wav new file mode 100644 index 0000000..cbd73ff Binary files /dev/null and b/public/assets/break.wav differ diff --git a/public/assets/screen-bg.jpg b/public/assets/screen-bg.jpg new file mode 100644 index 0000000..bdb2ab0 Binary files /dev/null and b/public/assets/screen-bg.jpg differ diff --git a/public/assets/screen-bg.png b/public/assets/screen-bg.png new file mode 100644 index 0000000..e725d2a Binary files /dev/null and b/public/assets/screen-bg.png differ diff --git a/yarn.lock b/yarn.lock index 2ddfb78..760958e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3193,6 +3193,11 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +gsap@^3.12.1: + version "3.12.1" + resolved "https://registry.yarnpkg.com/gsap/-/gsap-3.12.1.tgz#e6482f336547cbab947e9f57071565bdce611f79" + integrity sha512-FXtb2YbBE9l8I9Pl5DFLpCMedaiMPztRlr0Ln0CMSnJn+pbTaeKlzgth8cLNPc7PzNwIZe+SEQiBBAWaBKJdVA== + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"