diff --git a/package.json b/package.json index 222b8094..1eb64144 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,7 @@ "recharts": "^2.15.3", "rxjs": "^7.5.6", "swr": "^2.2.0", + "tsparticles-confetti": "^2.12.0", "unionize": "^3.1.0", "uuid": "^9.0.1", "yup": "^0.32.11", diff --git a/public/images/reward-icon.jpg b/public/images/reward-icon.jpg new file mode 100644 index 00000000..e3ef1588 Binary files /dev/null and b/public/images/reward-icon.jpg differ diff --git a/public/images/reward-icon.png b/public/images/reward-icon.png deleted file mode 100644 index d427a1e1..00000000 Binary files a/public/images/reward-icon.png and /dev/null differ diff --git a/src/features/Torque/components/TorqueClaimRewards.tsx b/src/features/Torque/components/TorqueClaimRewards.tsx index 982b5dc0..653e56c1 100644 --- a/src/features/Torque/components/TorqueClaimRewards.tsx +++ b/src/features/Torque/components/TorqueClaimRewards.tsx @@ -1,11 +1,29 @@ -import { Heading, HStack, Stack, Text, VStack } from '@chakra-ui/react' -import { useMemo } from 'react' +import { + Button, + Heading, + HStack, + ModalBody, + ModalCloseButton, + ModalContent, + ModalOverlay, + Modal, + Stack, + Text, + VStack, + ModalHeader, + useColorMode +} from '@chakra-ui/react' +import { useMemo, useState } from 'react' import TorqueOfferCard, { TorqueOfferCardSkeleton } from './TorqueOfferCard' import { colors } from '@/theme/cssVariables' import { TorqueCampaign } from '../types' import HistoryIcon from '@/icons/misc/History' import GiftIcon from '@/icons/misc/Gift' import { useWallet } from '@solana/wallet-adapter-react' +import Image from 'next/image' +import { genericConfetti } from './TorqueConfetti' +import { twitterShareUrl } from '../utils' + interface TorqueClaimRewardsProps { claimOffer: (offerId: string) => void campaigns: TorqueCampaign[] @@ -15,6 +33,11 @@ interface TorqueClaimRewardsProps { export default function TorqueClaimRewards({ claimOffer, campaigns, loading, error }: TorqueClaimRewardsProps) { const { wallet } = useWallet() + const [isClaimModalOpen, setIsClaimModalOpen] = useState(false) + const [shareAmount, setShareAmount] = useState('') + + const { colorMode } = useColorMode() + const isLight = colorMode === 'light' const activeCampaigns = useMemo(() => { return campaigns.filter((campaign) => campaign.offers.some((offer) => offer.status === 'ACTIVE')) @@ -37,6 +60,12 @@ export default function TorqueClaimRewards({ claimOffer, campaigns, loading, err }) }, [campaigns]) + const handleOpenClaimModal = (amount: string) => { + setShareAmount(amount) + setIsClaimModalOpen(true) + genericConfetti() + } + if (loading) { return ( @@ -69,49 +98,106 @@ export default function TorqueClaimRewards({ claimOffer, campaigns, loading, err } return ( - -
}> - {activeCampaigns.length > 0 ? ( - activeCampaigns.map((campaign) => ) - ) : ( - - {wallet?.adapter.publicKey ? "You don't have any available rewards." : 'Connect your wallet to view your rewards.'} - - )} -
+ <> + +
}> + {activeCampaigns.length > 0 ? ( + activeCampaigns.map((campaign) => ( + + )) + ) : ( + + + {wallet?.adapter.publicKey ? "You don't have any available rewards." : 'Connect your wallet to view your rewards.'} + + + )} +
-
}> - {historicalCampaigns.length > 0 ? ( - historicalCampaigns.map((campaign) => ) - ) : ( - - - {wallet?.adapter.publicKey ? 'Looks like there are no historical rewards.' : 'Connect your wallet to see historical rewards.'} - - - )} -
-
+
}> + {historicalCampaigns.length > 0 ? ( + historicalCampaigns.map((campaign) => ( + + )) + ) : ( + + + {wallet?.adapter.publicKey + ? 'Looks like there are no historical rewards.' + : 'Connect your wallet to see historical rewards.'} + + + )} +
+
+ {isClaimModalOpen && ( + { + setIsClaimModalOpen(false) + setShareAmount('') + }} + > + + + Hold Tight — Reward On The Way + + + + Share Reward + + Your reward's en route. While the system does it's magic, share your referral link on X for more chances to earn + rewards! + + + + + + + + + )} + ) } diff --git a/src/features/Torque/components/TorqueConfetti.ts b/src/features/Torque/components/TorqueConfetti.ts new file mode 100644 index 00000000..3d4b1ec9 --- /dev/null +++ b/src/features/Torque/components/TorqueConfetti.ts @@ -0,0 +1,18 @@ +import { confetti } from 'tsparticles-confetti' + +type ConfettiOptions = Parameters[0] +const confettiOptions: ConfettiOptions = { + // to layer on top of chakra overlay + zIndex: 10_000, + spread: 260, + ticks: 75, + gravity: 0.4, + decay: 0.95, + startVelocity: 30, + particleCount: 300, + scalar: 2 +} + +export const genericConfetti = () => { + return confetti(confettiOptions) +} diff --git a/src/features/Torque/components/TorqueOfferCard.tsx b/src/features/Torque/components/TorqueOfferCard.tsx index 3a3496c9..e78bf162 100644 --- a/src/features/Torque/components/TorqueOfferCard.tsx +++ b/src/features/Torque/components/TorqueOfferCard.tsx @@ -8,15 +8,11 @@ import Tooltip from '@/components/Tooltip' import ClockIcon from '@/icons/misc/Clock' import GiftIcon from '@/icons/misc/Gift' import ShareIcon from '@/icons/misc/ShareIcon' -import { displayNumber } from '../utils' +import { displayNumber, twitterShareUrl } from '../utils' +import { useWallet } from '@solana/wallet-adapter-react' interface TorqueOfferCardProps extends TorqueCampaign { claimOffer: (offerId: string) => void -} - -const twitterShareUrl = (amount: string) => { - const safeAmount = encodeURIComponent(amount) - // TODO: Need to add the final twitter copy here - return `https://twitter.com/intent/tweet?text=Thanks%20%40RaydiumProtocol%20for%20my%20${safeAmount},%20see%20if%20you%20are%20eligible%20for%20a%20reward%20too%20https%3A//raydium.io/launchpad/` + handleOpenClaimModal: (amount: string) => void } export default function TorqueOfferCard({ @@ -30,12 +26,14 @@ export default function TorqueOfferCard({ maxParticipants, startTime, endTime, - status + status, + handleOpenClaimModal }: TorqueOfferCardProps) { // State const [claiming, setClaiming] = useState(false) const [showAdditionalOffers, setShowAdditionalOffers] = useState(false) const explorerUrl = useAppStore((s) => s.explorerUrl) + const { wallet } = useWallet() const activeOffer = useMemo(() => { // A user should not be eligible for multiple active offers per campaign @@ -55,6 +53,8 @@ export default function TorqueOfferCard({ return } + handleOpenClaimModal(`${activeOffer.rewardPerUser} ${rewardDenomination}`) + setClaiming(true) await claimOffer(activeOffer.id) setClaiming(false) @@ -180,7 +180,10 @@ export default function TorqueOfferCard({ {pendingOrClaimedOffer?.rewardPerUser ? ( diff --git a/src/features/Torque/utils.ts b/src/features/Torque/utils.ts index 9327482c..d0292d16 100644 --- a/src/features/Torque/utils.ts +++ b/src/features/Torque/utils.ts @@ -168,3 +168,8 @@ export function formatBadDateString(date: string, makeUtc = false): string { return makeUtc ? baseDate + 'T00:00:00Z' : baseDate } + +export const twitterShareUrl = (amount: string, wallet: string) => { + const safeAmount = encodeURIComponent(amount) + return `https://twitter.com/intent/post?text=Just%20claimed%20${safeAmount}%20for%20trading%20on%20LaunchLab%20%40RaydiumProtocol%20%F0%9F%92%AA%0A%0ABeen%20in%20the%20trenches%3F%20You%20may%20have%20rewards%20waiting.%20Trade%20using%20my%20link%20for%20more%20chances%20to%20win%20RAY%20%F0%9F%91%89%20https%3A%2F%2Fraydium.io%2Flaunchpad%2F%3Flreferrer%3D${wallet}` +} diff --git a/yarn.lock b/yarn.lock index 54f5719f..df1b8760 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15519,6 +15519,186 @@ tslib@^2.3.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== +tsparticles-basic@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-basic/-/tsparticles-basic-2.12.0.tgz#39fd8cc31cf625b8c7c9dc517c4cb9943cafa5f4" + integrity sha512-pN6FBpL0UsIUXjYbiui5+IVsbIItbQGOlwyGV55g6IYJBgdTNXgFX0HRYZGE9ZZ9psEXqzqwLM37zvWnb5AG9g== + dependencies: + tsparticles-engine "^2.12.0" + tsparticles-move-base "^2.12.0" + tsparticles-shape-circle "^2.12.0" + tsparticles-updater-color "^2.12.0" + tsparticles-updater-opacity "^2.12.0" + tsparticles-updater-out-modes "^2.12.0" + tsparticles-updater-size "^2.12.0" + +tsparticles-confetti@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-confetti/-/tsparticles-confetti-2.12.0.tgz#c576fbc97f6b975d27044f361225468a6e477813" + integrity sha512-PsxBL1DjYNNZecFFcymivnPypuxHKh0ePz2/9CctKl6zwS+Z8cHBCoszg8jBx6PJDJkAxIa76taezd54caISYg== + dependencies: + tsparticles-basic "^2.12.0" + tsparticles-engine "^2.12.0" + tsparticles-plugin-emitters "^2.12.0" + tsparticles-plugin-motion "^2.12.0" + tsparticles-shape-cards "^2.12.0" + tsparticles-shape-heart "^2.12.0" + tsparticles-shape-image "^2.12.0" + tsparticles-shape-polygon "^2.12.0" + tsparticles-shape-square "^2.12.0" + tsparticles-shape-star "^2.12.0" + tsparticles-shape-text "^2.12.0" + tsparticles-updater-life "^2.12.0" + tsparticles-updater-roll "^2.12.0" + tsparticles-updater-rotate "^2.12.0" + tsparticles-updater-tilt "^2.12.0" + tsparticles-updater-wobble "^2.12.0" + +tsparticles-engine@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-engine/-/tsparticles-engine-2.12.0.tgz#4a52a8de4ab6085180abf27f4720f47caa1455fc" + integrity sha512-ZjDIYex6jBJ4iMc9+z0uPe7SgBnmb6l+EJm83MPIsOny9lPpetMsnw/8YJ3xdxn8hV+S3myTpTN1CkOVmFv0QQ== + +tsparticles-move-base@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-move-base/-/tsparticles-move-base-2.12.0.tgz#22a0bf5c5a6a21db868c31d3172c1434e3e9e45a" + integrity sha512-oSogCDougIImq+iRtIFJD0YFArlorSi8IW3HD2gO3USkH+aNn3ZqZNTqp321uB08K34HpS263DTbhLHa/D6BWw== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-plugin-emitters@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-plugin-emitters/-/tsparticles-plugin-emitters-2.12.0.tgz#625cf9ad946e9ba39afcb3320554726c90c6d15b" + integrity sha512-fbskYnaXWXivBh9KFReVCfqHdhbNQSK2T+fq2qcGEWpwtDdgujcaS1k2Q/xjZnWNMfVesik4IrqspcL51gNdSA== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-plugin-motion@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-plugin-motion/-/tsparticles-plugin-motion-2.12.0.tgz#bdaa3c41b44a895adaba99dbbe438c68ca99b983" + integrity sha512-VeS0VDV5wc9a4t0xkPi3lkHqOvKRlELq4mEEvaIk8WwgOcx05TUZcJIIbhftnNabqgpHrZ4iUP5Nb2wZ3DBwWQ== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-shape-cards@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-shape-cards/-/tsparticles-shape-cards-2.12.0.tgz#4bf99d5fecf3ef76b73084d17df2fe71b5f4559c" + integrity sha512-4mSV1C7c/7SsSbS4A5HJEZE5tB2fOAEUXm52uagzBVMbL/YI+XkjOpi7L6JtCNcBKrWnZ/IgnnLMyyFGhNc4pA== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-shape-circle@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-shape-circle/-/tsparticles-shape-circle-2.12.0.tgz#52757d222145c3f80b02d3c51e6158aee0af024c" + integrity sha512-L6OngbAlbadG7b783x16ns3+SZ7i0SSB66M8xGa5/k+YcY7zm8zG0uPt1Hd+xQDR2aNA3RngVM10O23/Lwk65Q== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-shape-heart@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-shape-heart/-/tsparticles-shape-heart-2.12.0.tgz#2031d55261aac35e3aeccbd5e1e343fc194b0fbd" + integrity sha512-OK8CJrCY0Z6YAedyfTQh52u7KsurkP8eLNWDW11BhqcvDQkfwJC5g25Y3VrcW9Rwc88hrbNwFQlsKbY6tOn7qA== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-shape-image@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-shape-image/-/tsparticles-shape-image-2.12.0.tgz#02273740d754a872f77434af8d57b5486b920c91" + integrity sha512-iCkSdUVa40DxhkkYjYuYHr9MJGVw+QnQuN5UC+e/yBgJQY+1tQL8UH0+YU/h0GHTzh5Sm+y+g51gOFxHt1dj7Q== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-shape-polygon@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-shape-polygon/-/tsparticles-shape-polygon-2.12.0.tgz#ab01b27f7c97f5fc1843ac0eef91e8dfa79bb3a2" + integrity sha512-5YEy7HVMt1Obxd/jnlsjajchAlYMr9eRZWN+lSjcFSH6Ibra7h59YuJVnwxOxAobpijGxsNiBX0PuGQnB47pmA== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-shape-square@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-shape-square/-/tsparticles-shape-square-2.12.0.tgz#53916baea090a6af1863cb8ec5f77bf0e993ef2a" + integrity sha512-33vfajHqmlODKaUzyPI/aVhnAOT09V7nfEPNl8DD0cfiNikEuPkbFqgJezJuE55ebtVo7BZPDA9o7GYbWxQNuw== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-shape-star@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-shape-star/-/tsparticles-shape-star-2.12.0.tgz#609f9eb7025ad30931ee115b17cee4cf5b91a13e" + integrity sha512-4sfG/BBqm2qBnPLASl2L5aBfCx86cmZLXeh49Un+TIR1F5Qh4XUFsahgVOG0vkZQa+rOsZPEH04xY5feWmj90g== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-shape-text@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-shape-text/-/tsparticles-shape-text-2.12.0.tgz#1edc78c174210be4152a095a21136fc420d125d5" + integrity sha512-v2/FCA+hyTbDqp2ymFOe97h/NFb2eezECMrdirHWew3E3qlvj9S/xBibjbpZva2gnXcasBwxn0+LxKbgGdP0rA== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-updater-color@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-updater-color/-/tsparticles-updater-color-2.12.0.tgz#56d2a45f42a1578fd3b75d91baa60f2744db26a4" + integrity sha512-KcG3a8zd0f8CTiOrylXGChBrjhKcchvDJjx9sp5qpwQK61JlNojNCU35xoaSk2eEHeOvFjh0o3CXWUmYPUcBTQ== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-updater-life@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-updater-life/-/tsparticles-updater-life-2.12.0.tgz#00e9929b6011821bdf2b37f27d211fdaf74e32d8" + integrity sha512-J7RWGHAZkowBHpcLpmjKsxwnZZJ94oGEL2w+wvW1/+ZLmAiFFF6UgU0rHMC5CbHJT4IPx9cbkYMEHsBkcRJ0Bw== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-updater-opacity@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-updater-opacity/-/tsparticles-updater-opacity-2.12.0.tgz#4e822dc43d80a3964e09056ff773214b619b18fc" + integrity sha512-YUjMsgHdaYi4HN89LLogboYcCi1o9VGo21upoqxq19yRy0hRCtx2NhH22iHF/i5WrX6jqshN0iuiiNefC53CsA== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-updater-out-modes@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-updater-out-modes/-/tsparticles-updater-out-modes-2.12.0.tgz#14b47c5dc7b9f2a485c819f03634656466249e5e" + integrity sha512-owBp4Gk0JNlSrmp12XVEeBroDhLZU+Uq3szbWlHGSfcR88W4c/0bt0FiH5bHUqORIkw+m8O56hCjbqwj69kpOQ== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-updater-roll@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-updater-roll/-/tsparticles-updater-roll-2.12.0.tgz#a44eb602609749506146c832d0c41902ae9100a3" + integrity sha512-dxoxY5jP4C9x15BxlUv5/Q8OjUPBiE09ToXRyBxea9aEJ7/iMw6odvi1HuT0H1vTIfV7o1MYawjeCbMycvODKQ== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-updater-rotate@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-updater-rotate/-/tsparticles-updater-rotate-2.12.0.tgz#fa2a977fbdcb13cbe2fa9632d6ab8766e1f83167" + integrity sha512-waOFlGFmEZOzsQg4C4VSejNVXGf4dMf3fsnQrEROASGf1FCd8B6WcZau7JtXSTFw0OUGuk8UGz36ETWN72DkCw== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-updater-size@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-updater-size/-/tsparticles-updater-size-2.12.0.tgz#c9e80c7a91487f2b58d2db0acffbffee517d51d5" + integrity sha512-B0yRdEDd/qZXCGDL/ussHfx5YJ9UhTqNvmS5X2rR2hiZhBAE2fmsXLeWkdtF2QusjPeEqFDxrkGiLOsh6poqRA== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-updater-tilt@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-updater-tilt/-/tsparticles-updater-tilt-2.12.0.tgz#fea652a4bc783f3af4240d4f9b5508aebb6ecb30" + integrity sha512-HDEFLXazE+Zw+kkKKAiv0Fs9D9sRP61DoCR6jZ36ipea6OBgY7V1Tifz2TSR1zoQkk57ER9+EOQbkSQO+YIPGQ== + dependencies: + tsparticles-engine "^2.12.0" + +tsparticles-updater-wobble@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/tsparticles-updater-wobble/-/tsparticles-updater-wobble-2.12.0.tgz#cd1e991629eec1db12fe963c7d9d2b6f9f4fb739" + integrity sha512-85FIRl95ipD3jfIsQdDzcUC5PRMWIrCYqBq69nIy9P8rsNzygn+JK2n+P1VQZowWsZvk0mYjqb9OVQB21Lhf6Q== + dependencies: + tsparticles-engine "^2.12.0" + tss-react@^4.5.2: version "4.9.12" resolved "https://registry.yarnpkg.com/tss-react/-/tss-react-4.9.12.tgz#beaae5459cae2dd966af4c97f6dc6dd6655e183d"