mirror of
https://github.com/MetaFam/TheGame.git
synced 2026-04-24 03:00:09 -04:00
Move Onboarding to new page + wip on Chiev claim
- Feedback suggested moving the onboarding page so, here it is - Also moved the effects toggle & connect buttons into the header
This commit is contained in:
@@ -5,22 +5,146 @@ import {
|
||||
Button,
|
||||
Flex,
|
||||
HStack,
|
||||
Icon,
|
||||
IconButton,
|
||||
Link,
|
||||
Spinner,
|
||||
Stack,
|
||||
Text,
|
||||
Tooltip,
|
||||
useBreakpointValue,
|
||||
usePrefersReducedMotion,
|
||||
useToast,
|
||||
VStack,
|
||||
} from '@metafam/ds';
|
||||
import OctoBg from 'assets/baby_octo.png';
|
||||
import MetaGameLogo from 'assets/logo.png';
|
||||
import { MetaLink } from 'components/Link';
|
||||
import { SetStateAction } from 'jotai';
|
||||
import { Dispatch, ReactNode, useState } from 'react';
|
||||
import { useWeb3 } from 'lib/hooks';
|
||||
import { get, set } from 'lib/store';
|
||||
import { Dispatch, ReactNode, useCallback, useEffect, useState } from 'react';
|
||||
import { FaToggleOff, FaToggleOn } from 'react-icons/fa';
|
||||
import { GoSignIn, GoSignOut } from 'react-icons/go';
|
||||
import { MdClose } from 'react-icons/md';
|
||||
|
||||
import { AnimatedWaves, upDownAnimation } from './animations';
|
||||
|
||||
export const LandingHeader: React.FC = () => {
|
||||
const [toggle, setToggle] = useState(false);
|
||||
const noMotion = usePrefersReducedMotion();
|
||||
const prefersReducedMotion = usePrefersReducedMotion();
|
||||
const savedMotionPreference = get('MotionPreference');
|
||||
const [noMotion, setNoMotion] = useState(
|
||||
savedMotionPreference === 'off'
|
||||
? true
|
||||
: savedMotionPreference === 'on'
|
||||
? false
|
||||
: prefersReducedMotion,
|
||||
);
|
||||
const reducedNoticeDismissed = get('ReducedMotionNotice') === 'dismissed';
|
||||
const root = typeof window !== 'undefined' ? document.body : null;
|
||||
const [effectsToggle, setEffectsToggle] = useState(noMotion);
|
||||
const toggleIcon = effectsToggle ? FaToggleOff : FaToggleOn;
|
||||
const [noticeOpen, setNoticeOpen] = useState(false);
|
||||
const { connect, disconnect, connected, connecting } = useWeb3();
|
||||
const spinnerSize = useBreakpointValue({ base: 'sm', '2xl': 'md' });
|
||||
const toast = useToast();
|
||||
|
||||
const handleCloseNotice = useCallback(() => {
|
||||
setNoticeOpen(false);
|
||||
set('ReducedMotionNotice', 'dismissed');
|
||||
}, []);
|
||||
|
||||
/** TODO: Toggle works 100% except on first load when
|
||||
* the switch renders as 'on' but is actually 'off' if no motion pref is saved */
|
||||
const handleToggleEffects = useCallback(() => {
|
||||
set('MotionPreference', !noMotion ? 'off' : 'on');
|
||||
setNoMotion(!noMotion);
|
||||
setEffectsToggle(!effectsToggle);
|
||||
toast({
|
||||
title: `Motion ${noMotion ? 'enabled' : 'disabled'}`,
|
||||
description: `Toggle to turn effects & animations ${
|
||||
noMotion ? 'off' : 'on'
|
||||
}.`,
|
||||
status: 'info',
|
||||
duration: 5000,
|
||||
isClosable: true,
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [effectsToggle, noMotion]);
|
||||
|
||||
// eslint-disable-next-line no-promise-executor-return
|
||||
// const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));
|
||||
|
||||
// const handleDisconnect = () => {
|
||||
// disconnect();
|
||||
|
||||
// sleep(1000).then(() => {
|
||||
// console.log('disconnected?');
|
||||
|
||||
// if (!connected) {
|
||||
// toast({
|
||||
// title: 'Wallet disconnected',
|
||||
// description: 'Any local data has been removed. See you soon, Anon! 🐙',
|
||||
// status: 'success',
|
||||
// duration: 5000,
|
||||
// isClosable: true,
|
||||
// });
|
||||
// console.log('disconnected');
|
||||
// }
|
||||
|
||||
// }).catch(() => {
|
||||
// toast({
|
||||
// title: 'Wallet disconnect',
|
||||
// description: 'We couldn\'t disconnect your wallet. Please try again.',
|
||||
// status: 'error',
|
||||
// duration: 5000,
|
||||
// isClosable: true,
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
|
||||
/** Initially set the motion pref if it's not already set */
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined' && window.matchMedia !== undefined) {
|
||||
if (savedMotionPreference === null) {
|
||||
set('MotionPreference', prefersReducedMotion ? 'off' : 'on');
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
/** set noMotion so we can turn off animations if preferred
|
||||
* Check for window to make sure we know window.matchMedia is availabe if supported
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
// setNoMotion(prefersReducedMotion);
|
||||
if (noMotion && !reducedNoticeDismissed) {
|
||||
setNoticeOpen(true);
|
||||
} else {
|
||||
setNoticeOpen(false);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined' && window.matchMedia !== undefined) {
|
||||
if (noMotion) {
|
||||
root?.classList.add('no-motion');
|
||||
setNoMotion(true);
|
||||
if (!reducedNoticeDismissed) {
|
||||
setNoticeOpen(true);
|
||||
}
|
||||
} else {
|
||||
root?.classList.remove('no-motion');
|
||||
setNoMotion(false);
|
||||
setNoticeOpen(false);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [effectsToggle, prefersReducedMotion]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -77,62 +201,157 @@ export const LandingHeader: React.FC = () => {
|
||||
</HStack>
|
||||
</MetaLink>
|
||||
</HStack>
|
||||
|
||||
<Button
|
||||
onClick={() => setToggle(!toggle)}
|
||||
sx={{
|
||||
alignSelf: 'center',
|
||||
justifySelf: 'right',
|
||||
position: 'relative',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-around',
|
||||
w: { base: '2.25rem', xl: '2.5rem', '4xl': '3.1rem' },
|
||||
h: { base: '2.25rem', xl: '2.5rem', '4xl': '3.1rem' },
|
||||
borderRadius: { base: '0.25rem', xl: '1rem', '4xl': '1.25rem' },
|
||||
background: 'transparent',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
padding: 0,
|
||||
marginRight: 0,
|
||||
zIndex: 401,
|
||||
'&:hover, &:focus, &[data-hover]': {
|
||||
outline: 'none',
|
||||
background: 'transparent',
|
||||
boxShadow: 'none',
|
||||
},
|
||||
div: {
|
||||
w: 'full',
|
||||
h: 'full',
|
||||
borderRadius: { base: '0.25rem', xl: '1rem', '4xl': '1.25rem' },
|
||||
transition: 'all 0.3s linear',
|
||||
position: 'relative',
|
||||
transformOrigin: '1px',
|
||||
},
|
||||
'path, circle': {
|
||||
fill: toggle ? 'transparent' : 'transparent',
|
||||
transition: noMotion ? 'none' : 'all 0.2s 0.2s ease',
|
||||
stroke: toggle ? 'landing600' : 'white',
|
||||
},
|
||||
'.top-line': {
|
||||
transition: noMotion ? 'none' : 'all 0.6s ease',
|
||||
transform: toggle
|
||||
? 'rotate(-405deg) translate3d(1px, 3px, 0)'
|
||||
: 'rotate(0)',
|
||||
transformOrigin: 'center',
|
||||
},
|
||||
'.bottom-line': {
|
||||
transition: noMotion ? 'none' : 'all 0.6s ease',
|
||||
transform: toggle
|
||||
? 'rotate(405deg) translate3d(0px, -4px, 0)'
|
||||
: noMotion
|
||||
? 'none'
|
||||
: 'rotate(0)',
|
||||
transformOrigin: 'center',
|
||||
},
|
||||
}}
|
||||
<HStack
|
||||
alignItems="center"
|
||||
alignContent="center"
|
||||
// position="absolute"
|
||||
// bottom={{ base: 20, xl: 4 }}
|
||||
// right={4}
|
||||
zIndex={401}
|
||||
pointerEvents="auto"
|
||||
>
|
||||
<MenuIcon2SVG toggle={toggle} />
|
||||
</Button>
|
||||
<Tooltip
|
||||
label={`Turn effects ${noMotion ? 'On' : 'Off'}`}
|
||||
hasArrow
|
||||
placement="bottom"
|
||||
>
|
||||
<Button
|
||||
onClick={handleToggleEffects}
|
||||
variant="ghost"
|
||||
display="inline-block"
|
||||
fontWeight="normal"
|
||||
color="white"
|
||||
// textShadow={`0 0 8px var(--chakra-colors-landing500)`}
|
||||
borderRadius="inherit inherit 0 0"
|
||||
opacity={0.3}
|
||||
px={{ base: 1, xl: 2 }}
|
||||
sx={{
|
||||
// svg: {
|
||||
// filter: 'drop-shadow(0 0 10px var(--chakra-colors-diamond))',
|
||||
// },
|
||||
'&:hover': {
|
||||
backgroundColor: 'transparent',
|
||||
color: 'var(--chakra-colors-landing300)',
|
||||
opacity: 1,
|
||||
svg: {
|
||||
filter:
|
||||
'drop-shadow(0 0 10px var(--chakra-colors-landing300))',
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Icon as={toggleIcon} h={{ base: 8, '2xl': 10 }} w="auto" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip
|
||||
label={`${connected ? 'Disconnect' : 'Connect'} wallet`}
|
||||
hasArrow
|
||||
placement="bottom"
|
||||
>
|
||||
<Button
|
||||
onClick={connected ? disconnect : connect}
|
||||
variant="ghost"
|
||||
display="inline-flex"
|
||||
alignItems="center"
|
||||
fontWeight="normal"
|
||||
color="white"
|
||||
// textShadow={`0 0 8px var(--chakra-colors-landing500)`}
|
||||
borderRadius="inherit inherit 0 0"
|
||||
opacity={0.3}
|
||||
px={{ base: 1, xl: 2 }}
|
||||
sx={{
|
||||
// svg: {
|
||||
// filter: 'drop-shadow(0 0 10px var(--chakra-colors-diamond))',
|
||||
// },
|
||||
'&:hover': {
|
||||
backgroundColor: 'transparent',
|
||||
color: 'var(--chakra-colors-landing300)',
|
||||
opacity: 1,
|
||||
svg: {
|
||||
filter:
|
||||
'drop-shadow(0 0 10px var(--chakra-colors-landing300))',
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{connecting ? (
|
||||
<Spinner size={spinnerSize} />
|
||||
) : (
|
||||
<Icon
|
||||
as={connected ? GoSignOut : GoSignIn}
|
||||
h={{ base: 6, '2xl': 8 }}
|
||||
w={{ base: 6, '2xl': 8 }}
|
||||
/>
|
||||
)}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
onClick={() => setToggle(!toggle)}
|
||||
sx={{
|
||||
alignSelf: 'center',
|
||||
justifySelf: 'right',
|
||||
position: 'relative',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-around',
|
||||
w: { base: '2.25rem', xl: '2.5rem', '4xl': '3.1rem' },
|
||||
h: { base: '2.25rem', xl: '2.5rem', '4xl': '3.1rem' },
|
||||
borderRadius: { base: '0.25rem', xl: '1rem', '4xl': 'full' },
|
||||
background: 'transparent',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
padding: 0,
|
||||
marginRight: 0,
|
||||
zIndex: 401,
|
||||
'&:hover, &:focus, &[data-hover]': {
|
||||
outline: 'none',
|
||||
background: 'transparent',
|
||||
boxShadow: 'none',
|
||||
},
|
||||
'&:hover, &[data-hover]': {
|
||||
svg: {
|
||||
filter:
|
||||
'drop-shadow(0 0 10px var(--chakra-colors-landing300))',
|
||||
},
|
||||
'path, circle': {
|
||||
// fill: 'var(--chakra-colors-landing300)',
|
||||
stroke: 'var(--chakra-colors-landing300)',
|
||||
},
|
||||
},
|
||||
div: {
|
||||
w: '99%',
|
||||
h: '99%',
|
||||
borderRadius: { base: '0.25rem', xl: '1rem', '4xl': 'full' },
|
||||
transition: 'all 0.2s linear',
|
||||
position: 'relative',
|
||||
transformOrigin: '1px',
|
||||
},
|
||||
'path, circle': {
|
||||
fill: toggle ? 'transparent' : 'transparent',
|
||||
transition: noMotion ? 'none' : 'all 0.2s ease',
|
||||
stroke: toggle ? 'landing600' : 'white',
|
||||
},
|
||||
'.top-line': {
|
||||
transition: noMotion ? 'none' : 'all 0.6s ease',
|
||||
transform: toggle
|
||||
? 'rotate(-405deg) translate3d(1px, 3px, 0)'
|
||||
: 'rotate(0)',
|
||||
transformOrigin: 'center',
|
||||
},
|
||||
'.bottom-line': {
|
||||
transition: noMotion ? 'none' : 'all 0.6s ease',
|
||||
transform: toggle
|
||||
? 'rotate(405deg) translate3d(0px, -4px, 0)'
|
||||
: noMotion
|
||||
? 'none'
|
||||
: 'rotate(0)',
|
||||
transformOrigin: 'center',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<MenuIcon2SVG toggle={toggle} />
|
||||
</Button>
|
||||
</HStack>
|
||||
</Flex>
|
||||
</Box>
|
||||
<Flex
|
||||
@@ -206,12 +425,8 @@ export const LandingHeader: React.FC = () => {
|
||||
6. What do?
|
||||
</NavLink>
|
||||
|
||||
<NavLink target="onboard" toggle={toggle} setToggle={setToggle}>
|
||||
7. Wake up, Anon...
|
||||
</NavLink>
|
||||
|
||||
<NavLink target="join-us" toggle={toggle} setToggle={setToggle}>
|
||||
8. Join us!
|
||||
7. Join us!
|
||||
</NavLink>
|
||||
</VStack>
|
||||
</Stack>
|
||||
@@ -242,6 +457,50 @@ export const LandingHeader: React.FC = () => {
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
|
||||
<Box
|
||||
position="fixed"
|
||||
top={0}
|
||||
left={0}
|
||||
width="full"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
flexFlow="row nowrap"
|
||||
py={1}
|
||||
textAlign="center"
|
||||
display={!noticeOpen ? 'none' : 'flex'}
|
||||
backgroundColor="silver"
|
||||
dropShadow={`0 0 10px black`}
|
||||
color="dark"
|
||||
zIndex={500}
|
||||
>
|
||||
<Text fontSize={{ base: 'xs', '2xl': 'sm' }}>
|
||||
Anon, I noticed that you prefer reduced motion on websites & apps,
|
||||
so disabled all unnecessary effects / animations for you. Hover on
|
||||
links & buttons remain. Love, Nova{' '}
|
||||
<span
|
||||
title="Nova. See The Lore of MetaGame"
|
||||
role="img"
|
||||
className="gradient-text"
|
||||
>
|
||||
🐙
|
||||
</span>{' '}
|
||||
</Text>
|
||||
<IconButton
|
||||
icon={<MdClose />}
|
||||
onClick={handleCloseNotice}
|
||||
aria-label="close motion notice"
|
||||
variant="ghost"
|
||||
width={6}
|
||||
height={6}
|
||||
sx={{
|
||||
'&:hover': {
|
||||
color: 'var(--chakra-colors-landing500)',
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -286,8 +545,8 @@ export const MenuIcon2SVG = ({ toggle }: { toggle: boolean }) => (
|
||||
as="svg"
|
||||
w={{ base: '2.25rem', xl: '2.5rem', '4xl': '2.9rem' }}
|
||||
position="absolute"
|
||||
ml={0.5}
|
||||
mt={0.5}
|
||||
ml={0}
|
||||
mt={0}
|
||||
left={0}
|
||||
bottom={0}
|
||||
top={0}
|
||||
|
||||
@@ -20,10 +20,9 @@ export interface IGameContext {
|
||||
gameState: (place?: string, reset?: boolean) => IGameState['state'];
|
||||
handleChoice: (choice: string) => Promise<string | undefined>;
|
||||
resetGame: () => boolean;
|
||||
// typeText: (name: string) => string;
|
||||
fetchGameData: () => Promise<void | GameProperties>;
|
||||
visitedElements: (increment?: boolean) => string;
|
||||
mintChiev: (tokenId: BigNumber) => Promise<string | undefined>;
|
||||
mintChiev: (tokenId: BigNumber) => Promise<any>;
|
||||
connect: Web3ContextType['connect'];
|
||||
disconnect: Web3ContextType['disconnect'];
|
||||
loading: boolean;
|
||||
|
||||
@@ -217,7 +217,7 @@ export const WhatDo: React.FC = () => {
|
||||
bottom={0}
|
||||
zIndex={1}
|
||||
/>
|
||||
<LandingNextButton section="onboard" />
|
||||
<LandingNextButton section="join-us" />
|
||||
</FullPageContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import { useToast } from '@metafam/ds';
|
||||
import type {
|
||||
GameProperties,
|
||||
@@ -5,7 +6,6 @@ import type {
|
||||
IGameContext,
|
||||
IGameState,
|
||||
} from 'components/Landing/OnboardingGame/gameTypes';
|
||||
import { CONFIG } from 'config';
|
||||
import { BigNumber, Contract, providers, utils } from 'ethers';
|
||||
import { useWeb3 } from 'lib/hooks';
|
||||
import React, {
|
||||
@@ -19,7 +19,7 @@ import { providerOptions } from 'utils/walletOptions';
|
||||
import Web3Modal from 'web3modal';
|
||||
|
||||
import ABI from '../components/Landing/OnboardingGame/chiev.abi.json';
|
||||
// import gameJson from '../components/Landing/OnboardingGame/metagame-onboarding-game.json';
|
||||
import gameJson from '../components/Landing/OnboardingGame/metagame-onboarding-game.json';
|
||||
import { get, remove, set } from '../lib/store';
|
||||
|
||||
export const GameContext = React.createContext<IGameContext>({
|
||||
@@ -77,8 +77,9 @@ export const GameContextProvider: React.FC = ({ children }) => {
|
||||
setIsLoading(true);
|
||||
console.log('Fetchng GameData...');
|
||||
|
||||
const response = await fetch(CONFIG.onboardingGameDataURL);
|
||||
const data = (await response.json()) as GameProperties;
|
||||
// const response = await fetch(gameJson);
|
||||
// const data = (await response.json()) as GameProperties;
|
||||
const data = gameJson as GameProperties;
|
||||
console.log('fetchGameData', data);
|
||||
|
||||
if (data) {
|
||||
@@ -229,11 +230,16 @@ export const GameContextProvider: React.FC = ({ children }) => {
|
||||
|
||||
const prov = await web3Modal.connect();
|
||||
const web3Provider = new providers.Web3Provider(prov);
|
||||
console.log('get provider/signer', { web3Provider, provider, prov });
|
||||
console.log(
|
||||
'get provider/signer',
|
||||
{ web3Provider, provider, prov },
|
||||
provider?.network.chainId,
|
||||
);
|
||||
// If user is not connected to the Rinkeby network, let them know and throw an error
|
||||
|
||||
if (chainId !== '0x013881') {
|
||||
throw new Error('Change network to Polygon Mumbai');
|
||||
if (provider && provider.network.chainId !== 80001) {
|
||||
throw new Error(
|
||||
`Change network to Polygon Mumbai. Current: ${chainId}/${provider.network.chainId}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (needSigner) {
|
||||
@@ -257,8 +263,27 @@ export const GameContextProvider: React.FC = ({ children }) => {
|
||||
[chainId, provider, toast],
|
||||
);
|
||||
|
||||
async function getNonce(signer: providers.JsonRpcSigner) {
|
||||
return (await signer).getTransactionCount();
|
||||
}
|
||||
|
||||
const getGasPrice = useCallback(async (): Promise<BigNumber | null> => {
|
||||
try {
|
||||
if (provider) {
|
||||
const feeData = await provider.getFeeData();
|
||||
console.log('getGasPrice', feeData);
|
||||
|
||||
return feeData.gasPrice;
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.log('getGasPrice error', { error });
|
||||
return null;
|
||||
}
|
||||
}, [provider]);
|
||||
|
||||
const mintChiev = useCallback(
|
||||
async (tokenId: BigNumber): Promise<string | undefined> => {
|
||||
async (tokenId: BigNumber): Promise<any> => {
|
||||
try {
|
||||
console.log('mintChiev', tokenId);
|
||||
|
||||
@@ -268,7 +293,7 @@ export const GameContextProvider: React.FC = ({ children }) => {
|
||||
|
||||
if (signerProvider === undefined) return undefined;
|
||||
|
||||
console.log('mintChiev', { account, provider });
|
||||
console.log('mintChiev account', { account, provider });
|
||||
const contractAddress = '0xa7787c91B35940AcC143E10C261A264f42F1e239';
|
||||
const currency = '0x0000000000000000000000000000000000001010';
|
||||
const quantity = BigNumber.from(1);
|
||||
@@ -284,45 +309,64 @@ export const GameContextProvider: React.FC = ({ children }) => {
|
||||
isClosable: true,
|
||||
});
|
||||
console.log('Wallet connected', { account, provider });
|
||||
const signer = provider?.getSigner();
|
||||
const signer = provider?.getSigner() as providers.JsonRpcSigner;
|
||||
const contract = new Contract(contractAddress, ABI, signer);
|
||||
const confirmations = 3;
|
||||
console.log('Contract', { contract, signer });
|
||||
|
||||
console.log('Contract', { contract, ABI, signer });
|
||||
const nonce = await getNonce(signer);
|
||||
const gasFee = await getGasPrice();
|
||||
const claimOptions = {
|
||||
payableAmount: utils.parseEther('0'),
|
||||
receiver: account,
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
tokenId: tokenId._hex,
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
quantity: quantity._hex,
|
||||
currency,
|
||||
tokenId,
|
||||
quantity,
|
||||
pricePerToken: utils.parseEther('0'),
|
||||
proofs: [''],
|
||||
currency,
|
||||
proofs: [utils.formatBytes32String('')],
|
||||
proofMax: BigNumber.from('1'),
|
||||
value: utils.parseEther('0')._hex,
|
||||
};
|
||||
const tx = await contract.claim(
|
||||
claimOptions.payableAmount,
|
||||
console.log('claim func', claimOptions, contract, gasFee, nonce);
|
||||
|
||||
const tx = await contract.functions.claim(
|
||||
claimOptions.receiver,
|
||||
claimOptions.tokenId,
|
||||
claimOptions.quantity,
|
||||
claimOptions.currency,
|
||||
claimOptions.pricePerToken,
|
||||
claimOptions.value,
|
||||
claimOptions.proofs,
|
||||
claimOptions.proofMax,
|
||||
{
|
||||
value: claimOptions.value,
|
||||
gasPrice: gasFee,
|
||||
gasLimit: BigNumber.from('9000000')._hex,
|
||||
nonce,
|
||||
},
|
||||
);
|
||||
if (tx) {
|
||||
console.log('tx', { claimOptions, tx });
|
||||
toast({
|
||||
title: 'Chiev claim',
|
||||
description: `Claim in progress: ${tx.hash}`,
|
||||
status: 'info',
|
||||
isClosable: true,
|
||||
duration: 5000,
|
||||
});
|
||||
setTxLoading(true);
|
||||
await tx.wait(confirmations);
|
||||
|
||||
setTxLoading(true);
|
||||
await tx.wait(confirmations);
|
||||
|
||||
toast({
|
||||
title: 'Chiev claimed',
|
||||
description: `Your receipt: ${tx.hash}`,
|
||||
status: 'success',
|
||||
isClosable: true,
|
||||
duration: 5000,
|
||||
});
|
||||
setTxLoading(false);
|
||||
return tx.hash;
|
||||
toast({
|
||||
title: 'Chiev claimed',
|
||||
description: `Your receipt: ${tx.hash}`,
|
||||
status: 'success',
|
||||
isClosable: true,
|
||||
duration: 5000,
|
||||
});
|
||||
setTxLoading(false);
|
||||
return tx.hash;
|
||||
}
|
||||
console.log('tx failed?', { claimOptions, tx });
|
||||
|
||||
return tx;
|
||||
// throw new Error('No account');
|
||||
} catch (error: any) {
|
||||
console.log('mintChiev error', { error });
|
||||
@@ -334,12 +378,20 @@ export const GameContextProvider: React.FC = ({ children }) => {
|
||||
isClosable: true,
|
||||
duration: 5000,
|
||||
});
|
||||
// disconnect();
|
||||
setTxLoading(false);
|
||||
return msg;
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
},
|
||||
[account, address, connect, getProviderOrSigner, provider, toast],
|
||||
[
|
||||
account,
|
||||
address,
|
||||
connect,
|
||||
getGasPrice,
|
||||
getProviderOrSigner,
|
||||
provider,
|
||||
toast,
|
||||
],
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,32 +1,16 @@
|
||||
/* eslint-disable no-nested-ternary */
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
HStack,
|
||||
Icon,
|
||||
IconButton,
|
||||
Spinner,
|
||||
Text,
|
||||
Tooltip,
|
||||
useBreakpointValue,
|
||||
usePrefersReducedMotion,
|
||||
useToast,
|
||||
VStack,
|
||||
} from '@metafam/ds';
|
||||
import { Box, Button, Text, Tooltip, VStack } from '@metafam/ds';
|
||||
import { PageContainer } from 'components/Container';
|
||||
import { Build } from 'components/Landing/Build';
|
||||
import { Game } from 'components/Landing/Game';
|
||||
import { Intro } from 'components/Landing/Intro';
|
||||
import { JoinUs } from 'components/Landing/JoinUs';
|
||||
import { LandingHeader } from 'components/Landing/LandingHeader';
|
||||
import { Onboard } from 'components/Landing/Onboard';
|
||||
import { WhatDo } from 'components/Landing/WhatDo';
|
||||
import { WhyAreWeHere } from 'components/Landing/WhyAreWeHere';
|
||||
import { WildWeb } from 'components/Landing/WildWeb';
|
||||
import { MetaLink } from 'components/Link';
|
||||
import { HeadComponent } from 'components/Seo';
|
||||
import { useWeb3 } from 'lib/hooks';
|
||||
import { get, set } from 'lib/store';
|
||||
// import { gsap } from "gsap";
|
||||
// import { ScrollToPlugin } from 'gsap/dist/ScrollToPlugin';
|
||||
// import { ScrollTrigger } from 'gsap/dist/ScrollTrigger';
|
||||
@@ -36,14 +20,10 @@ import {
|
||||
FaDiscord,
|
||||
FaGithub,
|
||||
FaHome,
|
||||
FaToggleOff,
|
||||
FaToggleOn,
|
||||
FaTrophy,
|
||||
FaTwitter,
|
||||
FaUserCircle,
|
||||
} from 'react-icons/fa';
|
||||
import { GoSignIn, GoSignOut } from 'react-icons/go';
|
||||
import { MdClose } from 'react-icons/md';
|
||||
|
||||
export const getStaticProps = async () => ({
|
||||
props: {
|
||||
@@ -81,23 +61,6 @@ const ArrowUp: React.FC = () => (
|
||||
);
|
||||
|
||||
const Landing: React.FC = () => {
|
||||
const prefersReducedMotion = usePrefersReducedMotion();
|
||||
const savedMotionPreference = get('MotionPreference');
|
||||
const [noMotion, setNoMotion] = useState(
|
||||
savedMotionPreference === 'off'
|
||||
? true
|
||||
: savedMotionPreference === 'on'
|
||||
? false
|
||||
: prefersReducedMotion,
|
||||
);
|
||||
const reducedNoticeDismissed = get('ReducedMotionNotice') === 'dismissed';
|
||||
const root = typeof window !== 'undefined' ? document.body : null;
|
||||
const [effectsToggle, setEffectsToggle] = useState(noMotion);
|
||||
const toggleIcon = effectsToggle ? FaToggleOff : FaToggleOn;
|
||||
const [noticeOpen, setNoticeOpen] = useState(false);
|
||||
const { connect, disconnect, connected, connecting } = useWeb3();
|
||||
const spinnerSize = useBreakpointValue({ base: 'sm', '2xl': 'md' });
|
||||
const toast = useToast();
|
||||
const scrollContainer =
|
||||
typeof document !== 'undefined'
|
||||
? document.getElementById('scroll-container')
|
||||
@@ -108,11 +71,6 @@ const Landing: React.FC = () => {
|
||||
hostName.current = host;
|
||||
}, []);
|
||||
|
||||
const handleCloseNotice = useCallback(() => {
|
||||
setNoticeOpen(false);
|
||||
set('ReducedMotionNotice', 'dismissed');
|
||||
}, []);
|
||||
|
||||
const handleScroll = useCallback(() => {
|
||||
if (!scrollContainer) return;
|
||||
const { scrollTop } = scrollContainer;
|
||||
@@ -139,80 +97,6 @@ const Landing: React.FC = () => {
|
||||
[scrollContainer],
|
||||
);
|
||||
|
||||
/** TODO: Toggle works 100% except on first load when
|
||||
* the switch renders as 'on' but is actually 'off' if no motion pref is saved */
|
||||
const handleToggleEffects = useCallback(() => {
|
||||
set('MotionPreference', !noMotion ? 'off' : 'on');
|
||||
setNoMotion(!noMotion);
|
||||
setEffectsToggle(!effectsToggle);
|
||||
toast({
|
||||
title: `Motion ${noMotion ? 'enabled' : 'disabled'}`,
|
||||
description: `Toggle to turn effects & animations ${
|
||||
noMotion ? 'off' : 'on'
|
||||
}.`,
|
||||
status: 'info',
|
||||
duration: 5000,
|
||||
isClosable: true,
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [effectsToggle, noMotion]);
|
||||
|
||||
// eslint-disable-next-line no-promise-executor-return
|
||||
// const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));
|
||||
|
||||
// const handleDisconnect = () => {
|
||||
// disconnect();
|
||||
|
||||
// sleep(1000).then(() => {
|
||||
// console.log('disconnected?');
|
||||
|
||||
// if (!connected) {
|
||||
// toast({
|
||||
// title: 'Wallet disconnected',
|
||||
// description: 'Any local data has been removed. See you soon, Anon! 🐙',
|
||||
// status: 'success',
|
||||
// duration: 5000,
|
||||
// isClosable: true,
|
||||
// });
|
||||
// console.log('disconnected');
|
||||
// }
|
||||
|
||||
// }).catch(() => {
|
||||
// toast({
|
||||
// title: 'Wallet disconnect',
|
||||
// description: 'We couldn\'t disconnect your wallet. Please try again.',
|
||||
// status: 'error',
|
||||
// duration: 5000,
|
||||
// isClosable: true,
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
|
||||
/** Initially set the motion pref if it's not already set */
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined' && window.matchMedia !== undefined) {
|
||||
if (savedMotionPreference === null) {
|
||||
set('MotionPreference', prefersReducedMotion ? 'off' : 'on');
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
/** set noMotion so we can turn off animations if preferred
|
||||
* Check for window to make sure we know window.matchMedia is availabe if supported
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
// setNoMotion(prefersReducedMotion);
|
||||
if (noMotion && !reducedNoticeDismissed) {
|
||||
setNoticeOpen(true);
|
||||
} else {
|
||||
setNoticeOpen(false);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
scrollContainer?.addEventListener('scroll', handleScroll);
|
||||
document.addEventListener('keydown', handleKeyDown);
|
||||
@@ -228,23 +112,6 @@ const Landing: React.FC = () => {
|
||||
};
|
||||
}, [handleScroll, handleKeyDown, scrollContainer, section, setHostName]);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined' && window.matchMedia !== undefined) {
|
||||
if (noMotion) {
|
||||
root?.classList.add('no-motion');
|
||||
setNoMotion(true);
|
||||
if (!reducedNoticeDismissed) {
|
||||
setNoticeOpen(true);
|
||||
}
|
||||
} else {
|
||||
root?.classList.remove('no-motion');
|
||||
setNoMotion(false);
|
||||
setNoticeOpen(false);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [effectsToggle, prefersReducedMotion]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<HeadComponent
|
||||
@@ -262,8 +129,7 @@ const Landing: React.FC = () => {
|
||||
<WildWeb /> {/* section 3 */}
|
||||
<WhyAreWeHere /> {/* section 4 */}
|
||||
<WhatDo /> {/* section 5 */}
|
||||
<Onboard /> {/* section 6 */}
|
||||
<JoinUs /> {/* section 7 */}
|
||||
<JoinUs /> {/* section 6 */}
|
||||
</PageContainer>
|
||||
<SectionWayPoints currentWaypoint={section} />
|
||||
<Socials />
|
||||
@@ -286,127 +152,6 @@ const Landing: React.FC = () => {
|
||||
Back to top
|
||||
</Button>
|
||||
</MetaLink>
|
||||
<HStack
|
||||
alignItems="center"
|
||||
alignContent="center"
|
||||
position="absolute"
|
||||
bottom={{ base: 20, xl: 4 }}
|
||||
left={4}
|
||||
zIndex={199}
|
||||
pointerEvents="auto"
|
||||
>
|
||||
<Tooltip label={`Turn effects ${noMotion ? 'On' : 'Off'}`}>
|
||||
<Button
|
||||
onClick={handleToggleEffects}
|
||||
variant="ghost"
|
||||
display="inline-block"
|
||||
fontWeight="normal"
|
||||
color="var(--chakra-colors-diamond)"
|
||||
textShadow={`0 0 8px var(--chakra-colors-landing500)`}
|
||||
borderRadius="inherit inherit 0 0"
|
||||
opacity={0.5}
|
||||
px={2}
|
||||
sx={{
|
||||
svg: {
|
||||
filter: 'drop-shadow(0 0 10px var(--chakra-colors-diamond))',
|
||||
},
|
||||
'&:hover': {
|
||||
backgroundColor: 'transparent',
|
||||
color: 'var(--chakra-colors-landing300)',
|
||||
opacity: 1,
|
||||
svg: {
|
||||
filter:
|
||||
'drop-shadow(0 0 10px var(--chakra-colors-landing300))',
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Icon as={toggleIcon} h={{ base: 8, '2xl': 10 }} w="auto" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip label={`${connected ? 'Disconnect' : 'Connect'} wallet`}>
|
||||
<Button
|
||||
onClick={connected ? disconnect : connect}
|
||||
variant="ghost"
|
||||
display="inline-flex"
|
||||
alignItems="center"
|
||||
fontWeight="normal"
|
||||
color="var(--chakra-colors-diamond)"
|
||||
textShadow={`0 0 8px var(--chakra-colors-landing500)`}
|
||||
borderRadius="inherit inherit 0 0"
|
||||
opacity={0.5}
|
||||
px={2}
|
||||
sx={{
|
||||
svg: {
|
||||
filter: 'drop-shadow(0 0 10px var(--chakra-colors-diamond))',
|
||||
},
|
||||
'&:hover': {
|
||||
backgroundColor: 'transparent',
|
||||
color: 'var(--chakra-colors-landing300)',
|
||||
opacity: 1,
|
||||
svg: {
|
||||
filter:
|
||||
'drop-shadow(0 0 10px var(--chakra-colors-landing300))',
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{connecting ? (
|
||||
<Spinner size={spinnerSize} />
|
||||
) : (
|
||||
<Icon
|
||||
as={connected ? GoSignOut : GoSignIn}
|
||||
h={{ base: 6, '2xl': 8 }}
|
||||
w={{ base: 6, '2xl': 8 }}
|
||||
/>
|
||||
)}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</HStack>
|
||||
<Box
|
||||
position="fixed"
|
||||
top={0}
|
||||
left={0}
|
||||
width="full"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
flexFlow="row nowrap"
|
||||
py={1}
|
||||
textAlign="center"
|
||||
display={!noticeOpen ? 'none' : 'flex'}
|
||||
backgroundColor="silver"
|
||||
dropShadow={`0 0 10px black`}
|
||||
color="dark"
|
||||
zIndex={100}
|
||||
>
|
||||
<Text fontSize="md">
|
||||
Anon, I noticed that you prefer reduced motion on websites & apps,
|
||||
so disabled all unnecessary effects / animations for you. Hover on
|
||||
links & buttons remain. Love, Nova{' '}
|
||||
<span
|
||||
title="Nova. See The Lore of MetaGame"
|
||||
role="img"
|
||||
className="gradient-text"
|
||||
>
|
||||
🐙
|
||||
</span>{' '}
|
||||
</Text>
|
||||
<IconButton
|
||||
icon={<MdClose />}
|
||||
onClick={handleCloseNotice}
|
||||
aria-label="close motion notice"
|
||||
variant="ghost"
|
||||
width={6}
|
||||
height={6}
|
||||
sx={{
|
||||
'&:hover': {
|
||||
color: 'var(--chakra-colors-landing500)',
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -626,16 +371,9 @@ export const SectionWayPoints = ({
|
||||
<Button
|
||||
className={currentWaypoint === 6 ? 'active' : ''}
|
||||
colorScheme="ghost"
|
||||
onClick={() => handleSectionNav('onboard')}
|
||||
>
|
||||
<Text as="span">07</Text>
|
||||
</Button>
|
||||
<Button
|
||||
className={currentWaypoint === 7 ? 'active' : ''}
|
||||
colorScheme="ghost"
|
||||
onClick={() => handleSectionNav('join-us')}
|
||||
>
|
||||
<Text as="span">08</Text>
|
||||
<Text as="span">07</Text>
|
||||
</Button>
|
||||
</VStack>
|
||||
</Box>
|
||||
|
||||
@@ -9057,16 +9057,11 @@ camelize@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b"
|
||||
integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=
|
||||
|
||||
caniuse-lite@^1.0.30001202, caniuse-lite@^1.0.30001219, caniuse-lite@^1.0.30001228, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001359:
|
||||
caniuse-lite@^1.0.30001202, caniuse-lite@^1.0.30001219, caniuse-lite@^1.0.30001228, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001359, caniuse-lite@^1.0.30001383:
|
||||
version "1.0.30001383"
|
||||
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001383.tgz"
|
||||
integrity sha512-swMpEoTp5vDoGBZsYZX7L7nXHe6dsHxi9o6/LKf/f0LukVtnrxly5GVb/fWdCDTqi/yw6Km6tiJ0pmBacm0gbg==
|
||||
|
||||
caniuse-lite@^1.0.30001383:
|
||||
version "1.0.30001383"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001383.tgz#aecf317ccd940690725ae3ae4f28293c5fb8050e"
|
||||
integrity sha512-swMpEoTp5vDoGBZsYZX7L7nXHe6dsHxi9o6/LKf/f0LukVtnrxly5GVb/fWdCDTqi/yw6Km6tiJ0pmBacm0gbg==
|
||||
|
||||
canonicalize@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/canonicalize/-/canonicalize-1.0.5.tgz#b43b390ce981d397908bb847c3a8d9614323a47b"
|
||||
|
||||
Reference in New Issue
Block a user