From 166265c417da619fc2dc83bf5531900793c67da2 Mon Sep 17 00:00:00 2001 From: jongwooha98 Date: Wed, 8 Dec 2021 22:53:19 +0900 Subject: [PATCH 01/16] update: mission image src url (s3 bucket) --- src/pages/Mission/Mission.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/Mission/Mission.tsx b/src/pages/Mission/Mission.tsx index 2f984a281..01cf94289 100644 --- a/src/pages/Mission/Mission.tsx +++ b/src/pages/Mission/Mission.tsx @@ -91,8 +91,8 @@ export const Mission: React.FC = () => { }} > mission-description @@ -106,8 +106,8 @@ export const Mission: React.FC = () => { }} > mission-list From cbb29d4baf2f946fdb36eadaa01144fcfe890ab0 Mon Sep 17 00:00:00 2001 From: jongwooha98 Date: Wed, 8 Dec 2021 23:40:28 +0900 Subject: [PATCH 02/16] fix: prevent iphone user from pinch zoom Add 'user-scalable=no' to meta tag --- public/index.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index cd3bf771d..1c10b58ed 100644 --- a/public/index.html +++ b/public/index.html @@ -2,7 +2,10 @@ - + From 6553fa962581c093b612d5a2a0fd9fcc8682e9d6 Mon Sep 17 00:00:00 2001 From: jongwooha98 Date: Wed, 8 Dec 2021 23:53:04 +0900 Subject: [PATCH 03/16] delete: subscribe button on platform page - Decided to take subscribe button out of platform page since there's no unsubscribe functionality yet. Being unable to unsubscribe could not be a good experience for user as user might feel that they are forced to be subscribed once they are subscribed. --- src/pages/Home.tsx | 68 ++++------------------------------------------ 1 file changed, 6 insertions(+), 62 deletions(-) diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 6aec5c4ec..8dbe63346 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -18,16 +18,11 @@ import WhatsNextCardImgUrl from 'assets/svg/whats_next_card_img.svg'; import ComingSoonCardImgUrl from 'assets/svg/coming_soon_card_img.svg'; import ArrowGame2048Url from 'assets/svg/arrow_game_2048.svg'; import ArrowKarrotClickerUrl from 'assets/svg/arrow_karrot_clicker.svg'; -import { ReactComponent as Bookmark } from 'assets/svg/bookmark_icon.svg'; -import { ReactComponent as BookmarkDone } from 'assets/svg/bookmark_done_icon.svg'; import { ReactComponent as Share } from 'assets/svg/share_icon.svg'; import { ReactComponent as Circle2048Puzzle } from 'assets/svg/platform/comment_icon_2048_puzzle.svg'; import { ReactComponent as CircleKarrotClicker } from 'assets/svg/platform/comment_icon_karrot_clicker.svg'; import { NotificationRequestDtoTypeEnum } from 'services/openapi_generator'; -import { - SubscribeToastContainer, - subscribeToastEmitter, -} from 'components/Toast'; +import { SubscribeToastContainer } from 'components/Toast'; import { Swiper, SwiperSlide } from 'swiper/react/swiper-react.js'; import 'swiper/swiper.scss'; import { Autoplay } from 'swiper'; @@ -43,22 +38,10 @@ export const Home: React.FC = () => { const minigameApi = useMinigameApi(); const { isTop } = useCurrentScreen(); const { push } = useNavigator(); - const { - isInWebEnvironment, - ejectApp, - handleThirdPartyAgreement, - handleSubscribe, - shareApp, - } = useMini(); + const { isInWebEnvironment, ejectApp, handleThirdPartyAgreement, shareApp } = + useMini(); const { accessToken } = useAccessToken(); - const { - userId, - nickname, - setUserInfo, - townName3, - isInstalled, - setIsInstalled, - } = useUserData(); + const { userId, nickname, setUserInfo, townName3 } = useUserData(); const { updateMyScore: updateMyGame2048Score, updateMyComment: updateMyGame2048Comment, @@ -332,31 +315,6 @@ export const Home: React.FC = () => { } }; - // Installation handler - // ================================================================= - const onSubscribeSucess = () => { - analytics.logEvent('click_subscribe_button', { - location: 'platform_page', - is_voluntary: true, - }); - setIsInstalled(true); - subscribeToastEmitter(); - }; - const runOnSuccess = () => { - analytics.logEvent('click_third_party_agreement_button', { - location: 'platform_page', - button_type: 'subscribe_button', - }); - handleSubscribe(onSubscribeSucess); - }; - const triggerInstallationHandler = () => { - if (accessToken) { - handleSubscribe(onSubscribeSucess); - } else { - handleThirdPartyAgreement(runOnSuccess); - } - }; - // New game notification handler // ================================================================= const onSuccessHandler = () => { @@ -463,22 +421,8 @@ export const Home: React.FC = () => { border={`1px solid #ECECEC`} appendLeft={} onClickLeft={leaveMiniApp} - appendRight={ -
- - {isInstalled ? ( - - ) : ( - - )} -
- } + appendRight={} + onClickRight={triggerShareHandler} style={{ background: `#fff`, }} From e101cb616737d509287dec3685dae4eabad88ab1 Mon Sep 17 00:00:00 2001 From: jongwooha98 Date: Thu, 9 Dec 2021 00:00:04 +0900 Subject: [PATCH 04/16] fix: Assign index as key to items in list --- .../Leaderboard/DistrictLeaderboard.tsx | 12 ++++++------ .../LeaderboardTabs/Leaderboard/UserLeaderboard.tsx | 8 ++++---- .../Leaderboard/DistrictLeaderboard.tsx | 9 ++++----- .../Leaderboard/IndividualLeaderboard.tsx | 8 ++++---- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/pages/Game2048/Leaderboard/LeaderboardTabs/Leaderboard/DistrictLeaderboard.tsx b/src/pages/Game2048/Leaderboard/LeaderboardTabs/Leaderboard/DistrictLeaderboard.tsx index c66b9294b..d2fa98145 100644 --- a/src/pages/Game2048/Leaderboard/LeaderboardTabs/Leaderboard/DistrictLeaderboard.tsx +++ b/src/pages/Game2048/Leaderboard/LeaderboardTabs/Leaderboard/DistrictLeaderboard.tsx @@ -29,10 +29,10 @@ const DistrictLeaderboard: React.FC = (props) => { }} > - {props.districtLeaderboardData.slice(0, 10).map((district) => { + {props.districtLeaderboardData.slice(0, 10).map((district, i) => { return myTown === district.name2 ? ( = (props) => { /> ) : ( = (props) => { /> ); })} - {props.districtLeaderboardData.slice(10).map((district) => { + {props.districtLeaderboardData.slice(10).map((district, i) => { return myTown === district.name2 ? ( = (props) => { /> ) : ( = (props) => { }} > - {props.userLeaderboardData.slice(0, 10).map((user) => { + {props.userLeaderboardData.slice(0, 10).map((user, i) => { return ( = (props) => { 이웃들에게 한 마디를 남겨보세요!

- {props.userLeaderboardData.slice(10).map((user) => { + {props.userLeaderboardData.slice(10).map((user, i) => { return ( {
- {districtRankData.slice(0, 10).map((district) => { + {districtRankData.slice(0, 10).map((district, i) => { return ( ); })} - {districtRankData.slice(10).map((district) => { + {districtRankData.slice(10).map((district, i) => { return ( { - {individualRankData.slice(0, 10).map((user) => { + {individualRankData.slice(0, 10).map((user, i) => { return ( {
이웃들에게 한 마디를 남겨보세요!

- {individualRankData.slice(10).map((user) => { + {individualRankData.slice(10).map((user, i) => { return ( Date: Thu, 9 Dec 2021 00:54:48 +0900 Subject: [PATCH 05/16] fix: inconsistent variable name change uUID to uuid (change variable name) --- src/pages/Home.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 8dbe63346..d8c2530e9 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -91,11 +91,11 @@ export const Home: React.FC = () => { // Track user with uuid const trackUser = useCallback( async ({ - uUID, + uuid, regionId, referer, }: { - uUID: string; + uuid: string; regionId: string; referer?: | 'FEED' @@ -113,7 +113,7 @@ export const Home: React.FC = () => { try { analytics.setUserId(uuid); const data = await minigameApi.visitorApi.visitUsingPOST( - uUID, + uuid, regionId, referer ); @@ -123,11 +123,11 @@ export const Home: React.FC = () => { console.error(error); } }, - [analytics, minigameApi.visitorApi, uuid] + [analytics, minigameApi.visitorApi] ); useEffect(() => { - trackUser({ uUID: uuid, regionId: regionId, referer: referer }); + trackUser({ uuid: uuid, regionId: regionId, referer: referer }); }, [referer, regionId, trackUser, uuid]); // const checkNotificationStatus = useCallback(async () => { From 9d373b391cbceed7d73ed19f73b32788cbacbfbb Mon Sep 17 00:00:00 2001 From: jongwooha98 Date: Thu, 9 Dec 2021 17:36:37 +0900 Subject: [PATCH 06/16] Update BackIcon.tsx --- src/assets/Icon/BackIcon.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/Icon/BackIcon.tsx b/src/assets/Icon/BackIcon.tsx index 2750aa545..0f0abaaf2 100644 --- a/src/assets/Icon/BackIcon.tsx +++ b/src/assets/Icon/BackIcon.tsx @@ -43,9 +43,9 @@ export const CircleBackIcon: React.FC = () => { width="48" height="48" filterUnits="userSpaceOnUse" - color-interpolation-filters="sRGB" + colorInterpolationFilters="sRGB" > - + Date: Thu, 9 Dec 2021 17:39:54 +0900 Subject: [PATCH 07/16] Update base.ts --- src/services/openapi_generator/base.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/services/openapi_generator/base.ts b/src/services/openapi_generator/base.ts index f3a920129..2d9056c7f 100644 --- a/src/services/openapi_generator/base.ts +++ b/src/services/openapi_generator/base.ts @@ -21,9 +21,7 @@ import globalAxios, { AxiosRequestConfig, } from 'axios'; - -export const BASE_PATH = "https://api.daangn-game.com".replace(/\/+$/, ""); - +export const BASE_PATH = 'https://alpha.daangn-game.com'.replace(/\/+$/, ''); /** * From 2ba2cdb8a5058b0e4512e3ba5ad43352ea70562a Mon Sep 17 00:00:00 2001 From: jongwooha98 Date: Thu, 9 Dec 2021 21:12:02 +0900 Subject: [PATCH 08/16] delete: karrotMarketMini context - delete unnecessary karrot-market-mini context - mini functions are accessed using custom hook: useMini --- src/App.tsx | 73 ++++++------------- src/components/Button/NavigationButton.tsx | 39 ---------- src/components/Button/index.ts | 1 - src/components/Navigation/TopNav.tsx | 54 -------------- src/services/karrotMarket/mini/index.ts | 2 +- .../karrotMarket/mini/karrotMarketMini.ts | 66 ----------------- src/services/karrotMarket/mini/mini.ts | 11 +++ src/services/karrotMarketMini.ts | 26 ------- 8 files changed, 35 insertions(+), 237 deletions(-) delete mode 100644 src/components/Button/NavigationButton.tsx delete mode 100644 src/components/Navigation/TopNav.tsx delete mode 100644 src/services/karrotMarket/mini/karrotMarketMini.ts create mode 100644 src/services/karrotMarket/mini/mini.ts delete mode 100644 src/services/karrotMarketMini.ts diff --git a/src/App.tsx b/src/App.tsx index 50feb8e73..916887ed2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -17,20 +17,12 @@ import { loadFromEnv as loadFirebaseAnalyticsConfig, } from 'services/analytics/firebase'; import { AnalyticsContext, emptyAnalytics } from 'services/analytics'; -import { - KarrotMarketMiniContext, - emptyKarrotMarketMini, -} from 'services/karrotMarketMini'; -import { - createKarrotMarketMini, - loadFromEnv as loadKarrotMarketMiniConfig, -} from 'services/karrotMarket/mini'; - import { useAccessToken, useSignAccessToken, useUserData, useUser, + useMini, } from 'hooks'; import { useMinigameApi } from 'services/api/minigameApi'; @@ -38,14 +30,12 @@ import { v4 as uuidv4 } from 'uuid'; const App: React.FC = () => { // const dispatch = useDispatch(); + const karrotMini = useMini(); const minigameApi = useMinigameApi(); const { setRegionInfo, setTownInfo, setIsInstalled } = useUserData(); const { accessToken } = useAccessToken(); const { signAccessToken, removeCookie } = useSignAccessToken(); const [analytics, setAnalytics] = useState(emptyAnalytics); - const [karrotMarketMini, setKarrotMarketMini] = useState( - emptyKarrotMarketMini - ); const { saveUserInfo, setMissionPreference } = useUser(); @@ -60,18 +50,6 @@ const App: React.FC = () => { console.error(error); } }, []); - // Mini... - useEffect(() => { - try { - // check karrot-mini - const karrotMarketMiniConfig = loadKarrotMarketMiniConfig(); - const karrotMarketMini = createKarrotMarketMini(karrotMarketMiniConfig); - setKarrotMarketMini(karrotMarketMini); - } catch (error) { - console.error(error); - // no-op - } - }, []); const getQueryParams = () => { const searchParams = new URLSearchParams(window.location.search); @@ -177,32 +155,27 @@ const App: React.FC = () => { return ( - - { - karrotMarketMini.close(); - }} - > - - {/* Game 2048 */} - - - - {/* Karrot Clicker */} - - - - - - - + { + karrotMini.ejectApp(); + }} + > + + {/* Game 2048 */} + + + + {/* Karrot Clicker */} + + + + + + ); }; diff --git a/src/components/Button/NavigationButton.tsx b/src/components/Button/NavigationButton.tsx deleted file mode 100644 index d2dfb0ab6..000000000 --- a/src/components/Button/NavigationButton.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import styled from '@emotion/styled'; -import { useNavigator } from '@karrotframe/navigator'; -import { BackIcon, CloseIcon } from 'assets/Icon'; - -import { useKarrotMarketMini } from 'services/karrotMarketMini'; - -const Button = styled.button` - border: none; - background: none; - color: inherit; - border: none; - padding: 0; - font: inherit; - outline: none; - user-select: none; -`; -export const AppEjectionButton = () => { - const karrotMarketMini = useKarrotMarketMini(); - const handleAppEjection = () => { - karrotMarketMini.close(); - }; - return ( - - ); -}; - -export const BackButton = () => { - const { pop } = useNavigator(); - const goBackOnePage = () => { - pop(); - }; - return ( - - ); -}; diff --git a/src/components/Button/index.ts b/src/components/Button/index.ts index 62c111a69..5ca96532c 100644 --- a/src/components/Button/index.ts +++ b/src/components/Button/index.ts @@ -1,3 +1,2 @@ export * from './Button'; -export * from './NavigationButton'; export * from './RefreshButton'; diff --git a/src/components/Navigation/TopNav.tsx b/src/components/Navigation/TopNav.tsx deleted file mode 100644 index 7a202d1ba..000000000 --- a/src/components/Navigation/TopNav.tsx +++ /dev/null @@ -1,54 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import { css } from '@emotion/react'; -import styled from '@emotion/styled'; -import { BackIcon } from 'assets/Icon'; -import { AppEjectionButton } from 'components/Button'; -const Nav = styled.div` - left: 0; - width: 100%; - top: 0; - display: flex; - flex-flow: row; - align-items: center; - justify-content: space-between; - width: 100%; - height: 80px; - padding: 0 30px; - background: transparent; -`; - -const customNavIcon = css` - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - opacity: 1; - transition: opacity 300ms; - width: 2.25rem; - height: 2.75rem; - text-decoration: none; - outline: none; - z-index: 10; -`; - -interface TopNavprops { - action: string; - handleNavBackAction?: () => void; -} -const TopNav = ({ action, handleNavBackAction }: TopNavprops) => { - return ( - - ); -}; - -export default TopNav; diff --git a/src/services/karrotMarket/mini/index.ts b/src/services/karrotMarket/mini/index.ts index 0d80311f0..10d1767e7 100644 --- a/src/services/karrotMarket/mini/index.ts +++ b/src/services/karrotMarket/mini/index.ts @@ -1,2 +1,2 @@ export * from './config'; -export * from './karrotMarketMini'; +export * from './mini'; diff --git a/src/services/karrotMarket/mini/karrotMarketMini.ts b/src/services/karrotMarket/mini/karrotMarketMini.ts deleted file mode 100644 index 99afe0f50..000000000 --- a/src/services/karrotMarket/mini/karrotMarketMini.ts +++ /dev/null @@ -1,66 +0,0 @@ -import Mini from '@karrotmarket/mini'; -import { - emptyKarrotMarketMini, - KarrotMarketMini, -} from 'services/karrotMarketMini'; - -import { KarrotMarketMiniConfig } from './config'; - -let mini: Mini; -export const getMini = () => { - if (mini) { - return mini; - } else { - return (mini = new Mini()); - } -}; - -export function createKarrotMarketMini( - config: KarrotMarketMiniConfig -): KarrotMarketMini { - const mini = getMini(); - const presetUrl: string = config.presetUrl!; - const appId: string = config.appId!; - - async function startPreset(runOnSuccess: (code: string) => void) { - mini.startPreset({ - preset: presetUrl, - params: { - appId: appId, - }, - onSuccess: async function (result) { - if (result && result.code) { - try { - runOnSuccess(result.code); - } catch (error) { - console.error(error); - } - } - }, - onFailure() { - throw new Error('mini-app preset failed'); - }, - }); - } - - async function close() { - mini.close(); - } - - async function share(url: string, text: string) { - mini.share({ - url: url, - text: text, - }); - } - - if (mini.environment === 'Web') { - return emptyKarrotMarketMini; - } else { - return { - startPreset, - close, - share, - }; - } -} diff --git a/src/services/karrotMarket/mini/mini.ts b/src/services/karrotMarket/mini/mini.ts new file mode 100644 index 000000000..9090318dd --- /dev/null +++ b/src/services/karrotMarket/mini/mini.ts @@ -0,0 +1,11 @@ +import Mini from '@karrotmarket/mini'; + +let mini: Mini; + +export const getMini = () => { + if (mini) { + return mini; + } else { + return (mini = new Mini()); + } +}; diff --git a/src/services/karrotMarketMini.ts b/src/services/karrotMarketMini.ts deleted file mode 100644 index 0fe2380ca..000000000 --- a/src/services/karrotMarketMini.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { createContext, useContext } from 'react'; - -export interface KarrotMarketMini { - startPreset(runOnSuccess: (code: string) => void): void; - close(): void; - share(url: string, text: string): void; - // configuration(): { presetUrl: string; appId: string }; - // appId: string; - // presetUrl: string; -} - -// wow, such empty... -export const emptyKarrotMarketMini: KarrotMarketMini = { - startPreset(...args) { - console.log(...args); - }, - close(...args) { - console.log(...args); - }, - share(...args) { - console.log(...args); - }, -}; - -export const KarrotMarketMiniContext = createContext(emptyKarrotMarketMini); -export const useKarrotMarketMini = () => useContext(KarrotMarketMiniContext); From 5aba31165a59e7f3b47c64c2fb66eb776f83ab74 Mon Sep 17 00:00:00 2001 From: jongwooha98 Date: Thu, 9 Dec 2021 22:43:00 +0900 Subject: [PATCH 09/16] refactor: analytics context --- src/App.tsx | 70 +++++++----------- src/index.tsx | 9 ++- src/services/analytics.ts | 20 ------ src/services/analytics/firebase/analytics.ts | 20 ------ src/services/analytics/firebase/analytics.tsx | 71 +++++++++++++++++++ src/services/analytics/index.ts | 1 + 6 files changed, 102 insertions(+), 89 deletions(-) delete mode 100644 src/services/analytics.ts delete mode 100644 src/services/analytics/firebase/analytics.ts create mode 100644 src/services/analytics/firebase/analytics.tsx create mode 100644 src/services/analytics/index.ts diff --git a/src/App.tsx b/src/App.tsx index 916887ed2..07433a0fe 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect } from 'react'; import '@karrotframe/navigator/index.css'; import { Navigator, Screen } from '@karrotframe/navigator'; import { Home } from 'pages/Home'; @@ -10,13 +10,6 @@ import { KarrotClickerGame } from 'pages/KarrotClicker/Game'; import { KarrotClickerLeaderboard } from 'pages/KarrotClicker/Leaderboard'; import { Survey } from 'pages/Survey'; import { Mission } from 'pages/Mission'; -// import { LoadingScreen } from 'components/LoadingScreen'; - -import { - createFirebaseAnalytics, - loadFromEnv as loadFirebaseAnalyticsConfig, -} from 'services/analytics/firebase'; -import { AnalyticsContext, emptyAnalytics } from 'services/analytics'; import { useAccessToken, useSignAccessToken, @@ -25,32 +18,19 @@ import { useMini, } from 'hooks'; import { useMinigameApi } from 'services/api/minigameApi'; - +import { useAnalytics } from 'services/analytics/firebase'; import { v4 as uuidv4 } from 'uuid'; const App: React.FC = () => { // const dispatch = useDispatch(); const karrotMini = useMini(); const minigameApi = useMinigameApi(); + const analytics = useAnalytics(); const { setRegionInfo, setTownInfo, setIsInstalled } = useUserData(); const { accessToken } = useAccessToken(); const { signAccessToken, removeCookie } = useSignAccessToken(); - const [analytics, setAnalytics] = useState(emptyAnalytics); - const { saveUserInfo, setMissionPreference } = useUser(); - // Firebase Analytics가 설정되어 있으면 인스턴스를 초기화하고 교체합니다. - useEffect(() => { - try { - // check analytics - const config = loadFirebaseAnalyticsConfig(); - const analytics = createFirebaseAnalytics(config); - setAnalytics(analytics); - } catch (error) { - console.error(error); - } - }, []); - const getQueryParams = () => { const searchParams = new URLSearchParams(window.location.search); const preload: string | null = searchParams.get('preload'); @@ -154,29 +134,27 @@ const App: React.FC = () => { }, []); return ( - - { - karrotMini.ejectApp(); - }} - > - - {/* Game 2048 */} - - - - {/* Karrot Clicker */} - - - - - - - + { + karrotMini.ejectApp(); + }} + > + + {/* Game 2048 */} + + + + {/* Karrot Clicker */} + + + + + + ); }; diff --git a/src/index.tsx b/src/index.tsx index cbb46f60d..b13a7bdc8 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,9 +1,10 @@ import React from 'react'; -import { CookiesProvider } from 'react-cookie'; import ReactDOM from 'react-dom'; +import { CookiesProvider } from 'react-cookie'; import { Provider } from 'react-redux'; -import { MinigameApiProvider } from 'services/api/minigameApi'; import store from 'store'; +import { MinigameApiProvider } from 'services/api/minigameApi'; +import { AnalyticsProvider } from 'services/analytics/firebase'; import App from './App'; import './index.css'; @@ -12,7 +13,9 @@ ReactDOM.render( - + + + diff --git a/src/services/analytics.ts b/src/services/analytics.ts deleted file mode 100644 index 60093d00f..000000000 --- a/src/services/analytics.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { AnalyticsCallOptions } from '@firebase/analytics'; -import { createContext, useContext } from 'react'; - -export interface Analytics { - logEvent(eventName: string, params?: Record): void; - setUserId(id: string, options?: AnalyticsCallOptions): void; -} - -// wow, such empty... -export const emptyAnalytics: Analytics = { - logEvent(...args) { - console.log(...args); - }, - setUserId(...args) { - console.log(...args); - }, -}; - -export const AnalyticsContext = createContext(emptyAnalytics); -export const useAnalytics = () => useContext(AnalyticsContext); diff --git a/src/services/analytics/firebase/analytics.ts b/src/services/analytics/firebase/analytics.ts deleted file mode 100644 index 213fc40b5..000000000 --- a/src/services/analytics/firebase/analytics.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { initializeApp } from 'firebase/app'; -import { getAnalytics, logEvent, setUserId } from 'firebase/analytics'; -import type { Analytics } from '../../analytics'; -import type { FirebaseAnalyticsConfig } from './config'; - -export function createFirebaseAnalytics( - config: FirebaseAnalyticsConfig -): Analytics { - const app = initializeApp(config); - const analytics = getAnalytics(app); - - return { - logEvent(eventName, params) { - logEvent(analytics, eventName, params); - }, - setUserId(id, options) { - setUserId(analytics, id, options); - }, - }; -} diff --git a/src/services/analytics/firebase/analytics.tsx b/src/services/analytics/firebase/analytics.tsx new file mode 100644 index 000000000..01ec1c2ef --- /dev/null +++ b/src/services/analytics/firebase/analytics.tsx @@ -0,0 +1,71 @@ +import React, { createContext, useContext, useMemo } from 'react'; +import { initializeApp } from 'firebase/app'; +import { + getAnalytics, + logEvent as firebaseLogEvent, + setUserId as firebaseSetUserId, +} from 'firebase/analytics'; +import { AnalyticsCallOptions } from '@firebase/analytics'; +import type { FirebaseAnalyticsConfig } from './config'; +import { loadFromEnv as firebaseAnalyticsEnv } from './config'; + +function createFirebaseAnalytics({ + config, +}: { + config?: FirebaseAnalyticsConfig; +}) { + if (config) { + console.log(config); + const app = initializeApp(config); + const analytics = getAnalytics(app); + console.log('analytics provider success'); + + const logEvent = ( + eventName: string, + params?: Record + ): void => { + firebaseLogEvent(analytics, eventName, params); + }; + const setUserId = (id: string, options?: AnalyticsCallOptions): void => { + firebaseSetUserId(analytics, id, options); + }; + + return { + logEvent, + setUserId, + }; + } else { + console.log('analytics provider fail'); + + const logEvent = (...args: any[]) => { + console.log(...args); + }; + const setUserId = (...args: any[]) => { + console.log(...args); + }; + return { + logEvent, + setUserId, + }; + } +} + +const AnalyticsContext = createContext< + ReturnType +>(null as any); + +export const AnalyticsProvider: React.FC = (props) => { + const config = firebaseAnalyticsEnv(); + const analytics = useMemo( + () => createFirebaseAnalytics({ config }), + [config] + ); + console.log('analytics provider initiated'); + return ( + + {props.children} + + ); +}; + +export const useAnalytics = () => useContext(AnalyticsContext); diff --git a/src/services/analytics/index.ts b/src/services/analytics/index.ts new file mode 100644 index 000000000..5588511bf --- /dev/null +++ b/src/services/analytics/index.ts @@ -0,0 +1 @@ +export * from './firebase'; From b7d6619488bc3a572a8db04a0f69d9f465019748 Mon Sep 17 00:00:00 2001 From: jongwooha98 Date: Thu, 9 Dec 2021 23:19:47 +0900 Subject: [PATCH 10/16] feat: override api basePath from env --- src/services/api/minigameApi/api.tsx | 42 +++++++++++++++++++++----- src/services/openapi_generator/base.ts | 2 +- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/services/api/minigameApi/api.tsx b/src/services/api/minigameApi/api.tsx index 192a99980..1a2c534d4 100644 --- a/src/services/api/minigameApi/api.tsx +++ b/src/services/api/minigameApi/api.tsx @@ -13,19 +13,45 @@ import { } from '../../openapi_generator/api'; import { Configuration } from '../../openapi_generator/configuration'; import { useAccessToken } from 'hooks'; -import { minigameApiConfig, loadFromEnv as minigameApiEnv } from './config'; +import { loadFromEnv as minigameApiEnv } from './config'; function CreateMinigameApi({ accessToken, - env, + basePath, }: { accessToken?: string; - env: minigameApiConfig; + basePath?: string; }) { - if (accessToken) { + if (accessToken && basePath) { const configuration = new Configuration({ apiKey: `Bearer ${accessToken}`, - basePath: env.baseUrl, + basePath: `${basePath.replace(/\/+$/, '')}`, + }); + const gamePlayApi = new GamePlayApi(configuration); + const gameTownApi = new GameTownApi(configuration); + const gameUserApi = new GameUserApi(configuration); + const notificationApi = new NotificationApi(configuration); + const oauth2Api = new Oauth2Api(configuration); + const regionApi = new RegionApi(configuration); + const surveyApi = new SurveyApi(configuration); + const userApi = new UserApi(configuration); + const visitorApi = new VisitorApi(configuration); + const scoreLogApi = new ScoreLogApi(configuration); + return { + oauth2Api, + userApi, + gameUserApi, + gameTownApi, + gamePlayApi, + regionApi, + surveyApi, + notificationApi, + visitorApi, + scoreLogApi, + }; + } else if (basePath) { + const configuration = new Configuration({ + basePath: `${basePath.replace(/\/+$/, '')}`, }); const gamePlayApi = new GamePlayApi(configuration); const gameTownApi = new GameTownApi(configuration); @@ -80,10 +106,10 @@ const MinigameApiContext = createContext>( ); export const MinigameApiProvider: React.FC = (props) => { const { accessToken } = useAccessToken(); - const env = minigameApiEnv(); + const basePath = minigameApiEnv().baseUrl; const api = useMemo( - () => CreateMinigameApi({ accessToken, env }), - [accessToken, env] + () => CreateMinigameApi({ accessToken, basePath }), + [accessToken, basePath] ); return ( diff --git a/src/services/openapi_generator/base.ts b/src/services/openapi_generator/base.ts index 2d9056c7f..eb9b51d26 100644 --- a/src/services/openapi_generator/base.ts +++ b/src/services/openapi_generator/base.ts @@ -21,7 +21,7 @@ import globalAxios, { AxiosRequestConfig, } from 'axios'; -export const BASE_PATH = 'https://alpha.daangn-game.com'.replace(/\/+$/, ''); +export const BASE_PATH = 'http://alpha.daangn-game.com'.replace(/\/+$/, ''); /** * From 1e13a0a44a120d9fa24e3f5ded7edef6cd0a971c Mon Sep 17 00:00:00 2001 From: jongwooha98 Date: Fri, 10 Dec 2021 00:54:36 +0900 Subject: [PATCH 11/16] refactor: subscription&mission redux states and reducers --- src/App.tsx | 14 +-- src/hooks/useUser.ts | 70 +++++------ src/hooks/useUserData.ts | 12 -- .../Game2048/Leaderboard/Leaderboard.tsx | 36 ++---- src/pages/Home.tsx | 27 ++-- src/pages/Mission/Mission.tsx | 15 ++- src/pages/Mission/Popup.tsx | 14 +-- src/reducers/userDataReducer.ts | 18 +-- src/redux/user/user.ts | 115 +++++++----------- 9 files changed, 114 insertions(+), 207 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 07433a0fe..8f7cecccd 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -22,14 +22,13 @@ import { useAnalytics } from 'services/analytics/firebase'; import { v4 as uuidv4 } from 'uuid'; const App: React.FC = () => { - // const dispatch = useDispatch(); const karrotMini = useMini(); const minigameApi = useMinigameApi(); const analytics = useAnalytics(); - const { setRegionInfo, setTownInfo, setIsInstalled } = useUserData(); + const { setRegionInfo, setTownInfo } = useUserData(); const { accessToken } = useAccessToken(); const { signAccessToken, removeCookie } = useSignAccessToken(); - const { saveUserInfo, setMissionPreference } = useUser(); + const { saveQueryString, setMission } = useUser(); const getQueryParams = () => { const searchParams = new URLSearchParams(window.location.search); @@ -84,9 +83,9 @@ const App: React.FC = () => { const missionPreference = localStorage.getItem('missionPreference'); if (missionPreference !== null) { const parsedMissionPreference = JSON.parse(missionPreference); - setMissionPreference({ - isMissionCheckedOut: parsedMissionPreference.isMissionCheckedOut, - hasMissionPopupSeen: parsedMissionPreference.hasMissionPopupSeen, + setMission({ + page: { isCheckedOut: parsedMissionPreference.isMissionCheckedOut }, + popup: { hasSeen: parsedMissionPreference.hasMissionPopupSeen }, }); } }; @@ -104,10 +103,9 @@ const App: React.FC = () => { setRegionInfo(regionId as string); getDistrictInfo(regionId as string); - setIsInstalled(isSubscribed(installed)); console.log(preload, code, regionId, installed, referer); - saveUserInfo({ + saveQueryString({ uuid: localStorage.getItem('uuid'), regionId: regionId as string, isSubscribed: isSubscribed(installed), diff --git a/src/hooks/useUser.ts b/src/hooks/useUser.ts index 294c2e329..ed46b1733 100644 --- a/src/hooks/useUser.ts +++ b/src/hooks/useUser.ts @@ -2,30 +2,28 @@ import { useCallback } from 'react'; import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import { RootState } from 'store'; import { - saveUserInfo as saveUserInfoAction, - trackVisitor as trackVisitorAction, - setMissionPreference as setMissionPreferenceAction, - setNotificationPreference as setNotificationPreferenceAction, + saveQueryString as saveQueryStringAction, + setMission as setMissionAction, + setSubscription as setSubscriptionAction, + setNotification as setNotificationAction, } from '../redux/user/user'; +import type { Mission, Subscription } from '../redux/user'; export const useUser = () => { - const { uuid, regionId, isSubscribed, referer } = useSelector( + const { uuid, regionId, referer } = useSelector( (state: RootState) => ({ uuid: state.user.uuid, regionId: state.user.regionId, - isSubscribed: state.user.isSubscribed, + referer: state.user.referer, }), shallowEqual ); - const { isMissionCheckedOut, hasMissionPopupSeen } = useSelector( - (state: RootState) => ({ - isMissionCheckedOut: state.user.isMissionCheckedOut, - hasMissionPopupSeen: state.user.hasMissionPopupSeen, - }), - shallowEqual + const subscription = useSelector( + (state: RootState) => state.user.subscription ); + const mission = useSelector((state: RootState) => state.user.mission); const { notification } = useSelector((state: RootState) => ({ notification: { @@ -40,7 +38,7 @@ export const useUser = () => { const dispatch = useDispatch(); - const saveUserInfo = useCallback( + const saveQueryString = useCallback( ({ uuid, regionId, @@ -63,31 +61,26 @@ export const useUser = () => { | 'LOGIN' | 'UNKNOWN'; }) => { - dispatch(saveUserInfoAction({ uuid, regionId, isSubscribed, referer })); + dispatch( + saveQueryStringAction({ uuid, regionId, isSubscribed, referer }) + ); }, [dispatch] ); - const trackVisitor = () => { - dispatch(trackVisitorAction()); - }; - - const setMissionPreference = useCallback( - ({ - isMissionCheckedOut, - hasMissionPopupSeen, - }: { - isMissionCheckedOut?: boolean; - hasMissionPopupSeen?: boolean; - }) => { - dispatch( - setMissionPreferenceAction({ isMissionCheckedOut, hasMissionPopupSeen }) - ); + const setMission = useCallback( + ({ notification, page, popup }: Mission) => { + dispatch(setMissionAction({ notification, page, popup })); }, [dispatch] ); - - const setNotificationPreference = useCallback( + const setSubscription = useCallback( + ({ isSubscribed }: Subscription) => { + dispatch(setSubscriptionAction({ isSubscribed })); + }, + [dispatch] + ); + const setNotification = useCallback( ({ isNewGameNotificationOn, isNextMissionNotificationOn, @@ -96,7 +89,7 @@ export const useUser = () => { isNextMissionNotificationOn?: boolean; }) => { dispatch( - setNotificationPreferenceAction({ + setNotificationAction({ isNewGameNotificationOn, isNextMissionNotificationOn, }) @@ -107,14 +100,13 @@ export const useUser = () => { return { uuid, regionId, - isSubscribed, referer, - isMissionCheckedOut, - hasMissionPopupSeen, + subscription, + mission, notification, - saveUserInfo, - trackVisitor, - setMissionPreference, - setNotificationPreference, + saveQueryString, + setMission, + setSubscription, + setNotification, }; }; diff --git a/src/hooks/useUserData.ts b/src/hooks/useUserData.ts index 18a67809e..55158a363 100644 --- a/src/hooks/useUserData.ts +++ b/src/hooks/useUserData.ts @@ -5,7 +5,6 @@ import { setUserInfoAction, setRegionInfoAction, setTownInfoAction, - setIsInstalledAction, } from 'reducers/userDataReducer'; export const useUserData = () => { @@ -17,7 +16,6 @@ export const useUserData = () => { townName1, townName2, townName3, - isInstalled, } = useSelector((state: RootState) => ({ userId: state.userDataReducer.userId, nickname: state.userDataReducer.nickname, @@ -26,7 +24,6 @@ export const useUserData = () => { townName1: state.userDataReducer.townName1, townName2: state.userDataReducer.townName2, townName3: state.userDataReducer.townName3, - isInstalled: state.userDataReducer.isInstalled, })); const dispatch = useDispatch(); @@ -56,13 +53,6 @@ export const useUserData = () => { [dispatch] ); - const setIsInstalled = useCallback( - (isInstalled: boolean) => { - dispatch(setIsInstalledAction(isInstalled)); - }, - [dispatch] - ); - return { userId, nickname, @@ -71,11 +61,9 @@ export const useUserData = () => { townName1, townName2, townName3, - isInstalled, setRegionInfo, setTownInfo, setUserInfo, - setIsInstalled, }; }; diff --git a/src/pages/Game2048/Leaderboard/Leaderboard.tsx b/src/pages/Game2048/Leaderboard/Leaderboard.tsx index c02f37bab..c9e1e367a 100644 --- a/src/pages/Game2048/Leaderboard/Leaderboard.tsx +++ b/src/pages/Game2048/Leaderboard/Leaderboard.tsx @@ -9,7 +9,7 @@ import { CloseIcon } from 'assets/Icon'; import { MyInfo } from './MyInfo'; import { useMinigameApi } from 'services/api/minigameApi'; import { useMyGame2048Data } from '../hooks'; -import { useMini, useUserData } from 'hooks'; +import { useMini, useUserData, useUser } from 'hooks'; import { Refresh } from './Refresh'; import { useThrottledCallback } from 'use-debounce/lib'; import { useAnalytics } from 'services/analytics'; @@ -26,7 +26,8 @@ export const Leaderboard = () => { const minigameApi = useMinigameApi(); const analytics = useAnalytics(); const { shareApp, handleSubscribe } = useMini(); - const { nickname, isInstalled, setIsInstalled } = useUserData(); + const { nickname } = useUserData(); + const { subscription, setSubscription } = useUser(); const { rank, @@ -175,18 +176,19 @@ export const Leaderboard = () => { location: 'leaderboard_page', is_voluntary: false, }); - setIsInstalled(true); + setSubscription({ isSubscribed: true }); subscribeToastEmitter(); - }, [analytics, setIsInstalled]); + }, [analytics, setSubscription]); const turnOffSubscribeNotification = useCallback(async () => { await minigameApi.notificationApi.saveNotificationUsingPOST({ type: 'SUBSCRIBE_OFF' as NotificationRequestDtoTypeEnum, }); }, [minigameApi.notificationApi]); + useEffect(() => { const showSubscribe = async () => { - if (isInstalled === false) { + if (subscription.isSubscribed === false) { const response = await isSubscribeNotificationOff(); if (response !== undefined && response === false) { analytics.logEvent('show_subscribe_button', { @@ -202,30 +204,6 @@ export const Leaderboard = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - // const turnOffSubscribeSuggestion = () => { - // localStorage.setItem( - // 'subscribePreference', - // JSON.stringify({ - // hasSuggestionSeen: true, - // }) - // ); - // }; - // const showSubscribe = useCallback(() => { - // const subscribePreference = localStorage.getItem('subscribePreference'); - // const parsedSubscribePreference = JSON.parse(subscribePreference!); - // if (isInstalled === false && parsedSubscribePreference.hasSuggestionSeen) { - // analytics.logEvent('show_subscribe_button', { - // game_type: '2048_puzzle', - // location: 'leaderboard_page', - // is_voluntary: false, - // }); - // handleSubscribe(onSubscribeSuccess, turnOffSubscribeSuggestion); - // } - // }, [analytics, handleSubscribe, isInstalled, onSubscribeSuccess]); - - // useEffect(() => { - // showSubscribe(); - // }, [showSubscribe]); return (
{ updateMyComment: updateMyKarrotClickerComment, setGameTypeToKarrotClicker, } = useMyKarrotClickerData(); - const { - uuid, - regionId, - referer, - isMissionCheckedOut, - hasMissionPopupSeen, - notification, - setNotificationPreference, - } = useUser(); + const { uuid, regionId, referer, mission, notification, setNotification } = + useUser(); const [shouldMissionPopupShown, setShouldMissionPopupShown] = - useState(!hasMissionPopupSeen); + useState(!mission.popup?.hasSeen); // Update user info const updateUserInfo = useCallback( @@ -141,7 +134,7 @@ export const Home: React.FC = () => { // 'OPEN_GAME' // ); // if (data && data.check) { - // setNotificationPreference({ + // setNotification({ // isNewGameNotificationOn: data.check, // }); // } @@ -152,7 +145,7 @@ export const Home: React.FC = () => { // }, [ // minigameApi.notificationApi, // notification.newGame.isNotificationOn, - // setNotificationPreference, + // setNotification, // ]); // const newGameNotificationPromise = () => { @@ -178,14 +171,14 @@ export const Home: React.FC = () => { ]); try { const notificationStatus = await notificationPromise; - setNotificationPreference({ + setNotification({ isNewGameNotificationOn: notificationStatus[0].data.data?.check, isNextMissionNotificationOn: notificationStatus[1].data.data?.check, }); } catch (error) { console.error(error); } - }, [minigameApi.notificationApi, setNotificationPreference]); + }, [minigameApi.notificationApi, setNotification]); useEffect(() => { updateUserInfo({ userId: userId }); @@ -322,7 +315,7 @@ export const Home: React.FC = () => { location: 'platform_page', button_type: 'notification_button', }); - setNotificationPreference({ + setNotification({ isNewGameNotificationOn: true, }); }; @@ -336,7 +329,7 @@ export const Home: React.FC = () => { analytics.logEvent('click_notification_button', { notification_type: 'new_game', }); - setNotificationPreference({ + setNotification({ isNewGameNotificationOn: true, }); } @@ -661,7 +654,7 @@ export const Home: React.FC = () => { onClick={goToMissionPage} style={{ position: `absolute`, right: 0, bottom: 0, zIndex: 99 }} > - {isMissionCheckedOut ? ( + {mission.notification?.isOn ? ( mission-button ) : ( { const minigameApi = useMinigameApi(); const { accessToken } = useAccessToken(); const { handleThirdPartyAgreement } = useMini(); - const { notification, setMissionPreference, setNotificationPreference } = - useUser(); + const { notification, setMission, setNotification } = useUser(); useEffect(() => { if (isTop) { @@ -34,12 +33,12 @@ export const Mission: React.FC = () => { hasMissionPopupSeen: true, }) ); - setMissionPreference({ - isMissionCheckedOut: true, - hasMissionPopupSeen: true, + setMission({ + page: { isCheckedOut: true }, + popup: { hasSeen: true }, }); } - }, [setMissionPreference, isTop]); + }, [setMission, isTop]); const goBackToPlatform = () => { pop(); @@ -51,7 +50,7 @@ export const Mission: React.FC = () => { location: 'platform_page', button_type: 'notification_button', }); - setNotificationPreference({ + setNotification({ isNextMissionNotificationOn: true, }); }; @@ -65,7 +64,7 @@ export const Mission: React.FC = () => { analytics.logEvent('click_notification_button', { notification_type: 'next_mission', }); - setNotificationPreference({ + setNotification({ isNextMissionNotificationOn: true, }); } diff --git a/src/pages/Mission/Popup.tsx b/src/pages/Mission/Popup.tsx index b0e35de35..4e028f831 100644 --- a/src/pages/Mission/Popup.tsx +++ b/src/pages/Mission/Popup.tsx @@ -17,7 +17,7 @@ export const Popup: React.FC = (props) => { const { isTop } = useCurrentScreen(); const { push } = useNavigator(); const { nickname } = useUserData(); - const { setMissionPreference } = useUser(); + const { setMission } = useUser(); useEffect(() => { if (isTop) { analytics.logEvent('view_mission_popup'); @@ -32,9 +32,9 @@ export const Popup: React.FC = (props) => { hasMissionPopupSeen: true, }) ); - setMissionPreference({ - isMissionCheckedOut: false, - hasMissionPopupSeen: true, + setMission({ + page: { isCheckedOut: false }, + popup: { hasSeen: true }, }); props.setShouldMissionPopupShown(false); }; @@ -50,9 +50,9 @@ export const Popup: React.FC = (props) => { hasMissionPopupSeen: true, }) ); - setMissionPreference({ - isMissionCheckedOut: true, - hasMissionPopupSeen: true, + setMission({ + page: { isCheckedOut: true }, + popup: { hasSeen: true }, }); props.setShouldMissionPopupShown(false); push(`/mission`); diff --git a/src/reducers/userDataReducer.ts b/src/reducers/userDataReducer.ts index 4896eb0cc..c972c255e 100644 --- a/src/reducers/userDataReducer.ts +++ b/src/reducers/userDataReducer.ts @@ -35,18 +35,10 @@ export const setTownInfoAction = ( }, }); -export const setIsInstalledAction = (isInstalled: boolean) => ({ - type: SET_IS_INSTALLED, - payload: { - isInstalled, - }, -}); - type UserDataAction = | ReturnType | ReturnType - | ReturnType - | ReturnType; + | ReturnType; // initial state type UserDataState = { @@ -57,7 +49,6 @@ type UserDataState = { townName1: string; townName2: string; townName3: string; - isInstalled: boolean; }; const initialState: UserDataState = { userId: '', @@ -67,7 +58,6 @@ const initialState: UserDataState = { townName1: '', townName2: '', townName3: '', - isInstalled: false, }; // reducer @@ -96,11 +86,7 @@ const userDataReducer = ( townName2: action.payload.townName2, townName3: action.payload.townName3, }; - case SET_IS_INSTALLED: - return { - ...state, - isInstalled: action.payload.isInstalled, - }; + default: return state; } diff --git a/src/redux/user/user.ts b/src/redux/user/user.ts index 4ec2a5fa8..1a52c5beb 100644 --- a/src/redux/user/user.ts +++ b/src/redux/user/user.ts @@ -1,48 +1,23 @@ -import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'; -import { useMinigameApi } from 'services/api/minigameApi'; +import { createSlice } from '@reduxjs/toolkit'; -const MinigameApi = () => { - const minigameApi = useMinigameApi(); - return { - minigameApi, - }; -}; - -export const trackVisitor = createAsyncThunk( - 'user/trackVisitor', - async (_args, { getState }) => { - const { uuid, regionId, referer } = getState() as { - uuid: string; - regionId: string; - referer: - | 'FEED' - | 'SUBSCRIBE_FEED_1' - | 'SUBSCRIBE_FEED_2' - | 'SUBSCRIBE_FEED_3' - | 'NEAR_BY' - | 'SHARE_GAME_2048' - | 'SHARE_GAME_KARROT' - | 'SHARE_PLATFORM' - | 'SHARE_COMMUNITY' - | 'LOGIN' - | 'UNKNOWN'; - }; - - console.log(uuid, regionId, referer); - const data = await MinigameApi().minigameApi.visitorApi.visitUsingPOST( - uuid, - regionId, - referer - ); - // .visitUsingPOST(uuid, regionId, referer); - return data; - } -); +export interface Subscription { + isSubscribed?: boolean; +} +export interface Mission { + notification?: { + isOn: boolean; + }; + page?: { + isCheckedOut: boolean; + }; + popup?: { + hasSeen: boolean; + }; +} interface UserState { uuid: string; regionId: string; - isSubscribed: boolean; referer: | 'FEED' | 'SUBSCRIBE_FEED_1' @@ -55,8 +30,8 @@ interface UserState { | 'SHARE_COMMUNITY' | 'LOGIN' | 'UNKNOWN'; - isMissionCheckedOut: boolean; - hasMissionPopupSeen: boolean; + subscription: Subscription; + mission: Mission; notification: { nextMission: { isNotificationOn: boolean; @@ -65,17 +40,27 @@ interface UserState { isNotificationOn: boolean; }; }; - status: string; - // payload: {}; } const initialState: UserState = { uuid: '', regionId: '', - isSubscribed: false, + referer: 'UNKNOWN', - isMissionCheckedOut: false, - hasMissionPopupSeen: false, + subscription: { + isSubscribed: false, + }, + mission: { + notification: { + isOn: false, + }, + page: { + isCheckedOut: false, + }, + popup: { + hasSeen: false, + }, + }, notification: { nextMission: { isNotificationOn: false, @@ -84,48 +69,36 @@ const initialState: UserState = { isNotificationOn: false, }, }, - - status: '', - // payload: {}, }; const userSlice = createSlice({ name: 'user', initialState, reducers: { - saveUserInfo(state, action) { + saveQueryString(state, action) { state.uuid = action.payload.uuid; state.regionId = action.payload.regionId; - state.isSubscribed = action.payload.isSubscribed; + state.subscription.isSubscribed = action.payload.isSubscribed; state.referer = action.payload.referer; }, - setMissionPreference(state, action) { - state.isMissionCheckedOut = action.payload.isMissionCheckedOut; - state.hasMissionPopupSeen = action.payload.hasMissionPopupSeen; + setMission(state, action) { + state.mission.notification = action.payload.notification; + state.mission.page = action.payload.page; + state.mission.popup = action.payload.popup; }, - setNotificationPreference(state, action) { + setSubscription(state, action) { + state.subscription.isSubscribed = action.payload.isSubscribed; + }, + setNotification(state, action) { state.notification.newGame.isNotificationOn = action.payload.isNewGameNotificationOn; state.notification.nextMission.isNotificationOn = action.payload.isNextMissionNotificationOn; }, }, - extraReducers: (builder) => { - builder.addCase(trackVisitor.pending, (state) => { - state.status = 'loading'; - }); - - builder.addCase(trackVisitor.fulfilled, (state, { payload }) => { - state.status = 'success'; - // state.payload = payload; - }); - - builder.addCase(trackVisitor.rejected, (state, { payload }) => { - state.status = 'failed'; - }); - }, }); -export const { saveUserInfo, setMissionPreference, setNotificationPreference } = +export const { saveQueryString, setMission, setSubscription, setNotification } = userSlice.actions; + export default userSlice.reducer; From bb0cb29c3948880b6791ecff7ab44e19f275c0d3 Mon Sep 17 00:00:00 2001 From: jongwooha98 Date: Fri, 10 Dec 2021 01:15:34 +0900 Subject: [PATCH 12/16] refactor: notification redux state&reducer --- src/hooks/useUser.ts | 40 +++++++---------------- src/pages/Home.tsx | 61 ++++++++--------------------------- src/pages/Mission/Mission.tsx | 12 +++---- src/redux/user/user.ts | 34 ++++++++----------- 4 files changed, 43 insertions(+), 104 deletions(-) diff --git a/src/hooks/useUser.ts b/src/hooks/useUser.ts index ed46b1733..4c861cef0 100644 --- a/src/hooks/useUser.ts +++ b/src/hooks/useUser.ts @@ -5,11 +5,12 @@ import { saveQueryString as saveQueryStringAction, setMission as setMissionAction, setSubscription as setSubscriptionAction, - setNotification as setNotificationAction, + setNewGame as setNewGameAction, } from '../redux/user/user'; -import type { Mission, Subscription } from '../redux/user'; +import type { Mission, Subscription, NewGame } from '../redux/user'; export const useUser = () => { + // state const { uuid, regionId, referer } = useSelector( (state: RootState) => ({ uuid: state.user.uuid, @@ -24,18 +25,9 @@ export const useUser = () => { (state: RootState) => state.user.subscription ); const mission = useSelector((state: RootState) => state.user.mission); + const newGame = useSelector((state: RootState) => state.user.newGame); - const { notification } = useSelector((state: RootState) => ({ - notification: { - newGame: { - isNotificationOn: state.user.notification.newGame.isNotificationOn, - }, - nextMission: { - isNotificationOn: state.user.notification.nextMission.isNotificationOn, - }, - }, - })); - + // dispatch const dispatch = useDispatch(); const saveQueryString = useCallback( @@ -80,20 +72,10 @@ export const useUser = () => { }, [dispatch] ); - const setNotification = useCallback( - ({ - isNewGameNotificationOn, - isNextMissionNotificationOn, - }: { - isNewGameNotificationOn?: boolean; - isNextMissionNotificationOn?: boolean; - }) => { - dispatch( - setNotificationAction({ - isNewGameNotificationOn, - isNextMissionNotificationOn, - }) - ); + + const setNewGame = useCallback( + ({ notification }: NewGame) => { + dispatch(setNewGameAction({ notification })); }, [dispatch] ); @@ -103,10 +85,10 @@ export const useUser = () => { referer, subscription, mission, - notification, + newGame, saveQueryString, setMission, setSubscription, - setNotification, + setNewGame, }; }; diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index f938f41ce..ec749db05 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -52,7 +52,7 @@ export const Home: React.FC = () => { updateMyComment: updateMyKarrotClickerComment, setGameTypeToKarrotClicker, } = useMyKarrotClickerData(); - const { uuid, regionId, referer, mission, notification, setNotification } = + const { uuid, regionId, referer, mission, newGame, setMission, setNewGame } = useUser(); const [shouldMissionPopupShown, setShouldMissionPopupShown] = @@ -123,41 +123,6 @@ export const Home: React.FC = () => { trackUser({ uuid: uuid, regionId: regionId, referer: referer }); }, [referer, regionId, trackUser, uuid]); - // const checkNotificationStatus = useCallback(async () => { - // if (notification.newGame.isNotificationOn) { - // return; - // } else { - // try { - // const { - // data: { data }, - // } = await minigameApi.notificationApi.checkNotificationUsingGET( - // 'OPEN_GAME' - // ); - // if (data && data.check) { - // setNotification({ - // isNewGameNotificationOn: data.check, - // }); - // } - // } catch (error) { - // console.error(error); - // } - // } - // }, [ - // minigameApi.notificationApi, - // notification.newGame.isNotificationOn, - // setNotification, - // ]); - - // const newGameNotificationPromise = () => { - // if (notification.newGame.isNotificationOn) { - // return notification.newGame.isNotificationOn; - // } else { - // const data = - // minigameApi.notificationApi.checkNotificationUsingGET('OPEN_GAME'); - // if (data !== undefined) return data; - // } - // }; - // Check user's notification status // available notifications: new-game, next-mission const checkNotificationStatus = useCallback(async () => { @@ -171,14 +136,20 @@ export const Home: React.FC = () => { ]); try { const notificationStatus = await notificationPromise; - setNotification({ - isNewGameNotificationOn: notificationStatus[0].data.data?.check, - isNextMissionNotificationOn: notificationStatus[1].data.data?.check, + setNewGame({ + notification: { + isOn: notificationStatus[0].data.data?.check as boolean, + }, + }); + setMission({ + notification: { + isOn: notificationStatus[1].data.data?.check as boolean, + }, }); } catch (error) { console.error(error); } - }, [minigameApi.notificationApi, setNotification]); + }, [minigameApi.notificationApi, setMission, setNewGame]); useEffect(() => { updateUserInfo({ userId: userId }); @@ -315,9 +286,7 @@ export const Home: React.FC = () => { location: 'platform_page', button_type: 'notification_button', }); - setNotification({ - isNewGameNotificationOn: true, - }); + setNewGame({ notification: { isOn: true } }); }; const handleNewGameNotification = async () => { if (accessToken) { @@ -329,9 +298,7 @@ export const Home: React.FC = () => { analytics.logEvent('click_notification_button', { notification_type: 'new_game', }); - setNotification({ - isNewGameNotificationOn: true, - }); + setNewGame({ notification: { isOn: true } }); } } else { handleThirdPartyAgreement(onSuccessHandler); @@ -590,7 +557,7 @@ export const Home: React.FC = () => {
새로운 게임을 준비 중이에요 - {notification.newGame.isNotificationOn ? ( + {newGame.notification?.isOn ? ( { const minigameApi = useMinigameApi(); const { accessToken } = useAccessToken(); const { handleThirdPartyAgreement } = useMini(); - const { notification, setMission, setNotification } = useUser(); + const { mission, setMission } = useUser(); useEffect(() => { if (isTop) { @@ -50,9 +50,7 @@ export const Mission: React.FC = () => { location: 'platform_page', button_type: 'notification_button', }); - setNotification({ - isNextMissionNotificationOn: true, - }); + setMission({ notification: { isOn: true } }); }; const turnNextMissionNotificationOn = async () => { if (accessToken) { @@ -64,9 +62,7 @@ export const Mission: React.FC = () => { analytics.logEvent('click_notification_button', { notification_type: 'next_mission', }); - setNotification({ - isNextMissionNotificationOn: true, - }); + setMission({ notification: { isOn: true } }); } } else { handleThirdPartyAgreement(onSuccessHandler); @@ -110,7 +106,7 @@ export const Mission: React.FC = () => { style={{ width: `100%`, maxWidth: `100vw`, maxHeight: `100%` }} /> - {notification.nextMission.isNotificationOn ? ( + {mission.notification?.isOn ? (