Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GGFE-141] coin animation css #914

Merged
merged 11 commits into from
Aug 7, 2023
7 changes: 3 additions & 4 deletions components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { useRouter } from 'next/router';
import { useEffect } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { useRecoilValue } from 'recoil';
import { colorModeState } from 'utils/recoil/colorMode';
import { loginState } from 'utils/recoil/login';
import { userState } from 'utils/recoil/layout';
import { openCurrentMatchState } from 'utils/recoil/match';
import Statistics from 'pages/statistics';
Expand Down Expand Up @@ -34,10 +32,11 @@ export default function AppLayout({ children }: AppLayoutProps) {
const openCurrentMatch = useRecoilValue(openCurrentMatchState);

useAxiosResponse();
useGetUserSeason();
useGetUserSeason(presentPath);
useSetAfterGameModal();
useLiveCheck(presentPath);
useAnnouncementCheck(presentPath);

const onClickMatch = () => {
router.replace('/');
router.push(`/match`);
Expand Down
8 changes: 2 additions & 6 deletions components/LoginChecker.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Login from 'pages/login';
import WelcomeModal from './modal/event/WelcomeModal';
import styles from 'styles/Layout/Layout.module.scss';

import useLoginCheck from 'hooks/Login/useLoginCheck';
Expand All @@ -8,13 +7,10 @@ interface LoginCheckerProps {
}

export default function LoginChecker({ children }: LoginCheckerProps) {
const [isLoading, loggedIn, firstVisited] = useLoginCheck();
const [isLoading, loggedIn] = useLoginCheck();

return loggedIn ? (
<>
{firstVisited && <WelcomeModal />}
{children}
</>
<>{children}</>
) : (
<div className={styles.appContainer}>
<div className={styles.background}>{!isLoading && <Login />}</div>
Expand Down
38 changes: 38 additions & 0 deletions components/modal/CoinAnimation.tsx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ด ํŒŒ์ผ ์™œ์ธ์ง€ prettier๊ฐ€ ๋™์ž‘ํ•˜์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™๋„ค์š”...?? Prettier ์„ค์ • ํ•œ๋ฒˆ ํ™•์ธํ•ด๋ณด์‹œ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ ์šฉ์™„๋ฃŒ

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import styles from 'styles/modal/CoinAnimation.module.scss';
import CoinIcon from './CoinIcon';

interface amountProps {
amount: number;
}

export default function CoinAnimation({ amount }: amountProps) {
const tilts = ['l', 'r', 'none'];

const moneyamount = Array.from({ length: amount }).map((_, index) => {
const randomTilt = tilts[Math.floor(Math.random() * 3)];
const stackStyle =
randomTilt === 'none'
? styles.stack
: randomTilt === 'l'
? styles.stackl
: styles.stackr;

return (
<div key={index} className={`${stackStyle} ${styles.fall}`}>
<svg className={`${styles.coin}`}>
<CoinIcon />
</svg>
</div>
);
});

return (
<div id='stage-coins' className={`${styles.stageCoins}`}>
<div className={`${styles.stage}`}>
<div className={`${styles.column}`}>{moneyamount}</div>
<div className={`${styles.appear}`}>+{amount}</div>
</div>
</div>
);
}
38 changes: 38 additions & 0 deletions components/modal/CoinIcon.tsx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ด ํŒŒ์ผ๋„ prettier ์ ์šฉ์ด ์•ˆ๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค!!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ ์šฉ์™„๋ฃŒ

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';

const CoinIcon = () => (
<svg
xmlns='http://www.w3.org/2000/svg'
xmlnsXlink='http://www.w3.org/1999/xlink'
viewBox='0 0 194 120'
>
<defs>
<symbol viewBox='0 0 194 120' id='icon-coin'>
<g>
<g>
<path
fill='#ffdc00'
d='M188.5 43.2C185.4 23.3 145.6 7.6 97 7.6 46.4 7.6 5.3 24.7 5.3 45.7c0 0 0 20.3 0 28.6 0 21 41.1 38.1 91.7 38.1s91.7-17.1 91.7-38.1c0-9.2 0-31 0-31C188.6 43.3 188.6 43.3 188.5 43.2z'
/>
</g>
</g>
<path
fill='none'
stroke='#000000'
strokeWidth='0.5'
strokeMiterlimit='10'
d='M97 60'
/>
<g>
<path d='M87.8 35.1c0 1.1 0.5 2 1.6 2.7 0.9 0.6 2.4 1.2 4.6 1.9l0.8 0.2v-8.7l-0.7 0.1C89.9 31.7 87.8 33 87.8 35.1zM93.5 38.3c-1.6-0.5-2.8-1-3.5-1.5 -0.7-0.5-1-1-1-1.7 0-1.3 1.5-2.2 4.6-2.6V38.3z' />
<path d='M112.9 44.4c-2.4-1.1-6.5-2.4-12.1-3.9v-8c4.6 0.3 9.2 1.1 13.5 2.4l0.4 0.1 4.9-8.3 -0.7-0.2c-5.3-1.6-11.4-2.6-18.1-2.9v-4.6h-7.3v4.8c-5.8 0.5-10.5 1.6-13.8 3.6 -3.6 2-5.4 4.6-5.4 7.8 0 3.1 1.3 5.6 3.9 7.6 2.5 1.9 6.8 3.7 12.8 5.4l2.6 0.7v8.5c-2.7-0.2-5.7-0.6-9.1-1.2 -3.6-0.7-6.7-1.5-9.2-2.3l-0.8-0.3v9.5l0.4 0.1c5.4 1.7 11.7 2.6 18.7 2.7v6.2h7.3v-6.4c5.9-0.4 10.7-1.6 14.1-3.6 3.6-2.1 5.5-4.9 5.5-8.4 0-2-0.6-3.7-1.9-5.2C117.3 46.8 115.4 45.5 112.9 44.4zM114.3 60.8c-3.3 1.9-8.1 3.1-14.1 3.5l-0.6 0v6.3h-4.9v-6.2l-0.6 0c-6.9-0.1-13.2-0.9-18.5-2.5V55c2.4 0.8 5.3 1.5 8.6 2.1 3.7 0.7 7 1.1 9.9 1.2l0.6 0V47.7l-3.4-0.9c-5.8-1.6-10-3.3-12.3-5.1 -2.3-1.8-3.4-3.9-3.4-6.7 0-2.7 1.6-4.9 4.8-6.7 3.3-1.9 8-3 13.9-3.4l0.6 0V20h4.9v4.6l0.6 0c6.5 0.2 12.4 1.1 17.6 2.6l-3.6 6.2c-4.5-1.3-9.2-2-13.9-2.3l-0.6 0v10.2l0.4 0.1c5.8 1.5 9.9 2.9 12.3 4 2.4 1.1 4.1 2.3 5.2 3.6 1.1 1.3 1.6 2.7 1.6 4.4C119.2 56.5 117.6 58.9 114.3 60.8z' />
<path d='M105.2 51.2c-1-0.6-2.6-1.3-4.8-2L99.6 49v9.2l0.7-0.1c4.4-0.5 6.6-1.9 6.6-4.2C106.9 52.8 106.3 51.9 105.2 51.2zM100.8 56.9v-6.2c1.7 0.6 2.9 1.1 3.7 1.6 0.8 0.5 1.2 1 1.2 1.7C105.7 55.4 104.1 56.4 100.8 56.9z' />
<path d='M97 7C46.1 7 4.7 24.4 4.7 45.7v28.6C4.7 95.6 46.1 113 97 113s92.3-17.4 92.3-38.7V45.7C189.3 24.4 147.9 7 97 7zM19 93.7C10.7 88 5.9 81.4 5.9 74.3V51.9c2 5.3 6.6 10.1 13.1 14.5V93.7zM28.5 99c-3.1-1.4-5.8-3-8.3-4.6V67.1c2.5 1.6 5.4 3.1 8.4 4.5L28.5 99zM188.1 74.3c0 20.7-40.9 37.5-91.1 37.5 -26.6 0-50.6-4.7-67.3-12.3l0.1-27.4C46.7 79.7 70.5 84.4 97 84.4c45.9 0 84-14.1 91.1-32.5V74.3zM97 83.2c-50.2 0-91.1-16.8-91.1-37.5S46.8 8.2 97 8.2s91.1 16.8 91.1 37.5S147.2 83.2 97 83.2z' />
</g>
</symbol>
</defs>
<use xlinkHref='#icon-coin' />
</svg>
);

export default CoinIcon;
6 changes: 6 additions & 0 deletions components/modal/ModalProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import AdminSeasonEdit from './admin/SeasonEdit';
import FeedbackDetailModal from './admin/FeedbackDetailModal';
import DeletePenaltyModal from './admin/DeletePenaltyModal';
import AdminModifyScoreModal from './admin/AdminModifyScoreModal';
import CoinChangeModal from './statChange/CoinChangeModal';
import WelcomeModal from './event/WelcomeModal';

import styles from 'styles/modal/Modal.module.scss';
import BuyModal from './store/purchase/BuyModal';
import GiftModal from './store/purchase/GiftModal';
Expand All @@ -40,6 +43,7 @@ export default function ModalProvider() {
penaltyId,
ISeason,
ModifyScore,
CoinResult,
},
setModal,
] = useRecoilState(modalState);
Expand Down Expand Up @@ -76,6 +80,8 @@ export default function ModalProvider() {
<AdminModifyScoreModal {...ModifyScore} />
) : null,
'USER-KAKAO_EDIT': <KakaoEditModal />,
'COIN-ANIMATION': CoinResult ? <CoinChangeModal {...CoinResult} /> : null,
'EVENT-WELCOME': <WelcomeModal />,
'PURCHASE-BUY': <BuyModal />,
'PURCHASE-GIFT': <GiftModal />,
};
Expand Down
76 changes: 60 additions & 16 deletions components/modal/event/WelcomeModal.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,82 @@
import { useSetRecoilState } from 'recoil';
import { firstVisitedState } from 'utils/recoil/modal';
import { Modal } from 'types/modalTypes';
import useAxiosGet from 'hooks/useAxiosGet';
import { useMockAxiosGet } from 'hooks/useAxiosGet';
import { useState, useEffect } from 'react';
import { instance } from 'utils/axios';
import { CoinResult } from 'types/coinTypes';
import { modalState } from 'utils/recoil/modal';
import { errorState } from 'utils/recoil/error';
import styles from 'styles/modal/event/WelcomeModal.module.scss';
import modalStyles from 'styles/modal/Modal.module.scss';

export default function WelcomeModal() {
const setFirstVisited = useSetRecoilState(firstVisitedState);
const setModal = useSetRecoilState<Modal>(modalState);
const [coin, setCoin] = useState<CoinResult>();
const setError = useSetRecoilState(errorState);

const content = {
title: 'Welcome!',
message:
'42GG์— ์˜ค์‹ ๊ฑธ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.\n๋‹น์‹ ์˜ ํ–‰๋ณตํ•œ ํƒ๊ตฌ ์ƒํ™œ์„\n์‘์›ํ•ฉ๋‹ˆ๋‹ค! ์ด์ด์ด...',
};

/* const postCoinHandler = async() => {
try {
const res = await instance.post(
`/pingpong/users/attendance`
);
setCoin(res.data);
} catch (error) {
setError('SM01');
}
};

useEffect(() => {
postCoinHandler();
}, []); */

const getCoinHandler = useMockAxiosGet({
url: `/users/attendance`,
setState: setCoin,
err: 'SM01',
type: 'setError',
});

useEffect(() => {
getCoinHandler();
}, []);

const openPageManual = () => {
window.open(
'https://github.com/42organization/42arcade.gg.client/wiki/42gg.kr--%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B0%80%EC%9D%B4%EB%93%9C'
);
};

const closeModalBackdropHandler = (e: React.MouseEvent) => {
if (e.target instanceof HTMLDivElement && e.target.id === 'modalOutside') {
setFirstVisited(false);
}
if (!coin) return null;

const openAttendanceCoin = () => {
setModal({
modalName: 'COIN-ANIMATION',
CoinResult: {
afterCoin: coin?.afterCoin,
beforeCoin: coin?.beforeCoin,
coinIncrement: coin?.coinIncrement,
},
});
};

const closeModalButtonHandler = () => {
setFirstVisited(false);
const openStatChangeModal = () => {
setModal({
modalName: 'FIXED-STAT',
exp: {
gameId: 0,
mode: 'RANK',
},
});
};

return (
<div
className={modalStyles.backdrop}
id='modalOutside'
onClick={closeModalBackdropHandler}
>
<div>
<div className={styles.container}>
<div className={styles.phrase}>
<div className={styles.emoji}></div>
Expand All @@ -49,9 +93,9 @@ export default function WelcomeModal() {
</div>
<div className={styles.positive}>
<input
onClick={closeModalButtonHandler}
onClick={openStatChangeModal}
type='button'
value='ํ™ˆ์œผ๋กœ'
value='์ถœ์„ํ•˜๊ธฐ'
/>
</div>
</div>
Expand Down
30 changes: 30 additions & 0 deletions components/modal/statChange/CoinChangeModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useSetRecoilState } from 'recoil';
import { modalState } from 'utils/recoil/modal';
import { reloadMatchState } from 'utils/recoil/match';
import { CoinResult } from 'types/coinTypes';
import CoinAnimation from '../CoinAnimation';
import CoinStat from 'components/modal/statChange/CoinStatChange';
import styles from 'styles/modal/CoinChangeModal.module.scss';

export default function CoinChangeModal(coin: CoinResult) {
const setModal = useSetRecoilState(modalState);

const closeModal = () => {
setModal({ modalName: null });
};

return (
<div>
<div
className={`${styles.fixedContainer} ${styles.front}`}
onClick={closeModal}
/>
<div className={styles.container}>
<div className={styles.emoji}>๐Ÿ’ฒ</div>
<CoinStat before={coin?.beforeCoin} after={coin?.afterCoin} />
<CoinAnimation amount={coin?.coinIncrement} />
<div className={styles.guide}>ํ™”๋ฉด์„ ํด๋ฆญํ•ด์ฃผ์„ธ์š”!</div>
</div>
</div>
);
}
32 changes: 32 additions & 0 deletions components/modal/statChange/CoinStatChange.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { sleep } from 'utils/sleep';
import { useEffect, useState } from 'react';
import styles from 'styles/modal/CoinChangeAnimation.module.scss';

interface CoinChangeProps {
after: number;
before: number;
}

export default function CoinStatChange({ after, before }: CoinChangeProps) {
const [coin, setCoin] = useState<number>(before);

useEffect(() => {
CoinChangeAnimation();
}, []);

const CoinChangeAnimation = () => {
const toAdd = 1;
for (let i = before; i < after; i++) {
sleep(i * 500).then(() => setCoin((thisCoin) => thisCoin + toAdd));
}
};

return (
<div className={styles.coinWrap}>
<div className={styles.coin}>
<span>{coin}&nbsp;</span>
<span>[{(after >= 0 ? '+' : '') + (after - before)}]</span>
</div>
</div>
);
}
28 changes: 27 additions & 1 deletion components/modal/statChange/StatChangeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { reloadMatchState } from 'utils/recoil/match';
import ExpStat from './ExpStat';
import PppStat from 'components/modal/statChange/PppStat';
import useAxiosGet from 'hooks/useAxiosGet';
import { useMockAxiosGet } from 'hooks/useAxiosGet';
import { CoinResult } from 'types/coinTypes';
import styles from 'styles/modal/afterGame/StatChangeModal.module.scss';

export default function StatChangeModal({ gameId, mode }: Exp) {
Expand All @@ -17,20 +19,44 @@ export default function StatChangeModal({ gameId, mode }: Exp) {
getExpHandler();
}, []);

const getExpHandler = useAxiosGet({
/* const getExpHandler = useAxiosGet({
url: `/pingpong/games/${gameId}/result/${mode?.toLowerCase()}`,
setState: setStat,
err: 'KP03',
type: 'setError',
}); */

const getExpHandler = useMockAxiosGet({
url: `/games/normal`,
setState: setStat,
err: 'KP03',
type: 'setError',
});

const closeModal = () => {
setReloadMatch(true);
setModal({ modalName: null });
openCoin();
};

/* async function openChangeModal() {
await new Promise((resolve) => setTimeout(resolve, 2000)); // 2์ดˆ ๋Œ€๊ธฐ
openStatChangeModal();
} */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ด ๋ถ€๋ถ„ ํ˜น์‹œ ์ด์ œ ์•ˆ์“ฐ๋Š” ๋ถ€๋ถ„์ด๋ผ๋ฉด ์‚ญ์ œํ•ด์ฃผ์„ธ์š”~!


if (!stat) return null;

const openCoin = () => {
setModal({
modalName: 'COIN-ANIMATION',
CoinResult: {
afterCoin: stat.afterCoin,
beforeCoin: stat.beforeCoin,
coinIncrement: stat.coinIncrement,
},
});
};

return (
<div>
<div
Expand Down
Loading