diff --git a/.pnp.cjs b/.pnp.cjs index b0dbdff2..84274479 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -4175,6 +4175,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@svgr/core", "npm:8.1.0"],\ ["@svgr/plugin-jsx", "virtual:f6fc21e1196a5e36ccf7110701b6043e0b913ea4ae1d1deb9368d1ebef4cb8924deb4e8e07aafc9678d844b070003814a4413e37134a210b07db139914fa76a4#npm:8.1.0"],\ ["@svgr/plugin-prettier", "virtual:f6fc21e1196a5e36ccf7110701b6043e0b913ea4ae1d1deb9368d1ebef4cb8924deb4e8e07aafc9678d844b070003814a4413e37134a210b07db139914fa76a4#npm:8.1.0"],\ + ["@tanstack/query-core", "npm:4.36.1"],\ ["@tanstack/react-query", "virtual:8ec4233c825b2c709f2ff549456a05fb98060d621f5df14748cda36fdb51190eccc2e438466f7464c85557cdad97eb73aa6580e78bca957a1149bfc58c6ddf34#npm:4.33.0"],\ ["@tanstack/react-query-devtools", "virtual:8ec4233c825b2c709f2ff549456a05fb98060d621f5df14748cda36fdb51190eccc2e438466f7464c85557cdad97eb73aa6580e78bca957a1149bfc58c6ddf34#npm:4.33.0"],\ ["@types/node", "npm:20.5.7"],\ @@ -5310,6 +5311,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@tanstack/query-core", "npm:4.33.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.36.1", {\ + "packageLocation": "./.yarn/cache/@tanstack-query-core-npm-4.36.1-7594b7a096-47672094da.zip/node_modules/@tanstack/query-core/",\ + "packageDependencies": [\ + ["@tanstack/query-core", "npm:4.36.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@tanstack/react-query", [\ diff --git a/apps/jurumarble/package.json b/apps/jurumarble/package.json index ac1cf536..fa8a46ba 100644 --- a/apps/jurumarble/package.json +++ b/apps/jurumarble/package.json @@ -18,6 +18,7 @@ "@monorepo/ui": "workspace:*", "@next/bundle-analyzer": "13.3.5-canary.9", "@react-hookz/web": "^23.1.0", + "@tanstack/query-core": "^4.36.1", "@tanstack/react-query": "^4.33.0", "@tanstack/react-query-devtools": "^4.33.0", "axios": "^1.5.0", diff --git a/apps/jurumarble/src/app/main/components/Banner.tsx b/apps/jurumarble/src/app/main/components/Banner.tsx index 2864e860..7834ea76 100644 --- a/apps/jurumarble/src/app/main/components/Banner.tsx +++ b/apps/jurumarble/src/app/main/components/Banner.tsx @@ -1,3 +1,5 @@ +"use client"; + import styled, { css } from "styled-components"; import Image from "next/image"; import { MainBannerImage } from "public/images"; diff --git a/apps/jurumarble/src/app/main/components/HotDrinkContainer.tsx b/apps/jurumarble/src/app/main/components/HotDrinkContainer.tsx index 62dcacae..ede1db69 100644 --- a/apps/jurumarble/src/app/main/components/HotDrinkContainer.tsx +++ b/apps/jurumarble/src/app/main/components/HotDrinkContainer.tsx @@ -1,3 +1,5 @@ +"use client"; + import styled, { css } from "styled-components"; import useGetHotDrinkListService from "../services/useGetHotDrinkListService"; import Carousel from "./Carousel"; diff --git a/apps/jurumarble/src/app/main/components/HotDrinkVoteContainer.tsx b/apps/jurumarble/src/app/main/components/HotDrinkVoteContainer.tsx index 790b540b..6fd51361 100644 --- a/apps/jurumarble/src/app/main/components/HotDrinkVoteContainer.tsx +++ b/apps/jurumarble/src/app/main/components/HotDrinkVoteContainer.tsx @@ -1,8 +1,10 @@ +"use client"; + import Path from "lib/Path"; import Image from "next/image"; import { useRouter } from "next/navigation"; import styled, { css } from "styled-components"; -import useGetHotDrinkVoteService from "../services/useGetHotDrinkVoteService"; +import { useGetHotDrinkVoteService } from "../services/useGetHotDrinkVoteService"; function HotDrinkVoteContainer() { const router = useRouter(); diff --git a/apps/jurumarble/src/app/main/components/SearchInputWrapper.tsx b/apps/jurumarble/src/app/main/components/SearchInputWrapper.tsx index 40aac6a9..86884ae9 100644 --- a/apps/jurumarble/src/app/main/components/SearchInputWrapper.tsx +++ b/apps/jurumarble/src/app/main/components/SearchInputWrapper.tsx @@ -1,3 +1,5 @@ +"use client"; + import SearchInput from "components/SearchInput"; import useInput from "hooks/useInput"; import Path from "lib/Path"; diff --git a/apps/jurumarble/src/app/main/components/TodayDrinkRecommendation.tsx b/apps/jurumarble/src/app/main/components/TodayDrinkRecommendation.tsx index b35cf607..6f82b012 100644 --- a/apps/jurumarble/src/app/main/components/TodayDrinkRecommendation.tsx +++ b/apps/jurumarble/src/app/main/components/TodayDrinkRecommendation.tsx @@ -1,3 +1,5 @@ +"use client"; + import { useEffect, useRef, useState } from "react"; import { SvgStamp } from "src/assets/icons/components"; import styled, { css, useTheme } from "styled-components"; diff --git a/apps/jurumarble/src/app/main/containers/HydratedDrinkVoteContainer.tsx b/apps/jurumarble/src/app/main/containers/HydratedDrinkVoteContainer.tsx new file mode 100644 index 00000000..49e7a02c --- /dev/null +++ b/apps/jurumarble/src/app/main/containers/HydratedDrinkVoteContainer.tsx @@ -0,0 +1,17 @@ +import { dehydrate } from "@tanstack/query-core"; +import { getHotDrinkVote } from "lib/apis/vote/getHotDrinkVote"; +import getQueryClient from "src/modules/getQueryClient"; +import HydrateOnClient from "src/modules/hydrateOnClient"; +import HotDrinkVoteContainer from "../components/HotDrinkVoteContainer"; +import { hotDrinkVoteQueryKey } from "../services/queryKey"; + +export const HydratedDrinkVoteContainer = async () => { + const qc = getQueryClient(); + await qc.prefetchQuery([hotDrinkVoteQueryKey], getHotDrinkVote); + const dehydratedState = dehydrate(qc); + return ( + + + + ); +}; diff --git a/apps/jurumarble/src/app/main/containers/HydratedHotDrinkContainer.tsx b/apps/jurumarble/src/app/main/containers/HydratedHotDrinkContainer.tsx new file mode 100644 index 00000000..6a5f69ac --- /dev/null +++ b/apps/jurumarble/src/app/main/containers/HydratedHotDrinkContainer.tsx @@ -0,0 +1,17 @@ +import { dehydrate } from "@tanstack/query-core"; +import { getHotDrinkList } from "lib/apis/vote/getHotDrinkList"; +import getQueryClient from "src/modules/getQueryClient"; +import HydrateOnClient from "src/modules/hydrateOnClient"; +import HotDrinkContainer from "../components/HotDrinkContainer"; +import { hotDrinkListQueryKey } from "../services/queryKey"; + +export const HydratedHotDrinkContainer = async () => { + const qc = getQueryClient(); + await qc.prefetchQuery([hotDrinkListQueryKey], getHotDrinkList); + const dehydratedState = dehydrate(qc); + return ( + + + + ); +}; diff --git a/apps/jurumarble/src/app/main/services/queryKey.ts b/apps/jurumarble/src/app/main/services/queryKey.ts new file mode 100644 index 00000000..24c5e757 --- /dev/null +++ b/apps/jurumarble/src/app/main/services/queryKey.ts @@ -0,0 +1,2 @@ +export const hotDrinkVoteQueryKey = "hotDrinkVote"; +export const hotDrinkListQueryKey = "searchDrinkList"; diff --git a/apps/jurumarble/src/app/main/services/useGetHotDrinkListService.ts b/apps/jurumarble/src/app/main/services/useGetHotDrinkListService.ts index 090aa9b7..087dbddf 100644 --- a/apps/jurumarble/src/app/main/services/useGetHotDrinkListService.ts +++ b/apps/jurumarble/src/app/main/services/useGetHotDrinkListService.ts @@ -1,11 +1,10 @@ import { useQuery } from "@tanstack/react-query"; import { getHotDrinkList } from "lib/apis/drink"; import { queryKeys } from "lib/queryKeys"; - -const getQueryKey = () => [queryKeys.SEARCH_DRINK_LIST]; +import { hotDrinkListQueryKey } from "./queryKey"; export default function useGetHotDrinkListService() { - const { data } = useQuery(getQueryKey(), getHotDrinkList); + const { data } = useQuery([hotDrinkListQueryKey], getHotDrinkList); return { data }; } diff --git a/apps/jurumarble/src/app/main/services/useGetHotDrinkVoteService.ts b/apps/jurumarble/src/app/main/services/useGetHotDrinkVoteService.ts index 0e484036..03954153 100644 --- a/apps/jurumarble/src/app/main/services/useGetHotDrinkVoteService.ts +++ b/apps/jurumarble/src/app/main/services/useGetHotDrinkVoteService.ts @@ -1,11 +1,11 @@ import { useQuery } from "@tanstack/react-query"; -import { getHotDrinkVote } from "lib/apis/vote"; -import { queryKeys } from "lib/queryKeys"; - -const getQueryKey = () => [queryKeys.HOT_DRINK_VOTE]; - -export default function useGetHotDrinkVoteService() { - const { data: hotDrinkVote } = useQuery(getQueryKey(), getHotDrinkVote); +import { getHotDrinkVote } from "lib/apis/vote/getHotDrinkVote"; +import { hotDrinkVoteQueryKey } from "./queryKey"; +export const useGetHotDrinkVoteService = () => { + const { data: hotDrinkVote } = useQuery({ + queryKey: [hotDrinkVoteQueryKey], + queryFn: getHotDrinkVote, + }); return { hotDrinkVote }; -} +}; diff --git a/apps/jurumarble/src/app/page.module.css b/apps/jurumarble/src/app/page.module.css new file mode 100644 index 00000000..d9c5d3e7 --- /dev/null +++ b/apps/jurumarble/src/app/page.module.css @@ -0,0 +1,15 @@ +.main-top-section { + padding: 0 20px; +} + +.main-bottom-section { + padding: 0 20px 96px; + margin-top: 8px; + overflow: auto; +} + +.main-divide-line { + height: 8px; + margin: 40px 0 8px 0; + background-color: var(--bg_01); +} diff --git a/apps/jurumarble/src/app/page.tsx b/apps/jurumarble/src/app/page.tsx index c55050cb..57d1c69c 100644 --- a/apps/jurumarble/src/app/page.tsx +++ b/apps/jurumarble/src/app/page.tsx @@ -1,13 +1,10 @@ -"use client"; - import BottomBar from "components/BottomBar"; import Header from "components/Header"; -import styled, { css } from "styled-components"; import dynamic from "next/dynamic"; - -const DynamicHotDrinkVoteContainer = dynamic( - () => import("./main/components/HotDrinkVoteContainer"), -); +import { getClassNames } from "lib/styles/getClassNames"; +import styles from "./page.module.css"; +import { HydratedDrinkVoteContainer } from "./main/containers/HydratedDrinkVoteContainer"; +import { HydratedHotDrinkContainer } from "./main/containers/HydratedHotDrinkContainer"; const DynamicHotDrinkContainer = dynamic(() => import("./main/components/HotDrinkContainer"), { ssr: false, @@ -28,41 +25,27 @@ const DynamicSearchInputWrapper = dynamic(() => import("./main/components/Search const DynamicBanner = dynamic(() => import("./main/components/Banner")); +const cx = getClassNames(styles); + function MainPage() { return ( <>
- +
- - - - - - + {/* @ts-expect-error Server Component */} + +
+
+
+ {/* @ts-expect-error Server Component */} + +
); } -const TopSection = styled.section` - padding: 0 20px; -`; - -const BottomSection = styled.section` - padding: 0 20px 96px; // 64(BottomBar height) + 32(margin) = 96 - margin-top: 8px; - overflow: auto; -`; - -const DivideLine = styled.div` - ${({ theme }) => css` - background-color: ${theme.colors.bg_01}; - height: 8px; - margin: 40px 0 8px 0; - `} -`; - export default MainPage; diff --git a/apps/jurumarble/src/lib/apis/vote.ts b/apps/jurumarble/src/lib/apis/vote.ts index 1717f625..9449bcbc 100644 --- a/apps/jurumarble/src/lib/apis/vote.ts +++ b/apps/jurumarble/src/lib/apis/vote.ts @@ -163,18 +163,6 @@ export const getVotingCheck = async (voteId: number) => { return response.data; }; -interface GetHotDrinkVoteResponse { - voteId: number; - voteTitle: string; - drinkAImage: string; - drinkBImage: string; -} - -export const getHotDrinkVote = async () => { - const response = await baseApi.get("api/votes/drinks/hot"); - return response.data; -}; - export const deleteVote = async (voteId: number) => { const response = await http.delete(`api/votes/${voteId}/`); return response.data; diff --git a/apps/jurumarble/src/lib/apis/vote/getHotDrinkList.ts b/apps/jurumarble/src/lib/apis/vote/getHotDrinkList.ts new file mode 100644 index 00000000..71235d2f --- /dev/null +++ b/apps/jurumarble/src/lib/apis/vote/getHotDrinkList.ts @@ -0,0 +1,13 @@ +import { SERVER_URL } from "lib/env"; + +export interface GetHotDrinkResponse { + drinkId: number; + name: string; + manufactureAddress: string; + image: string; +} +export const getHotDrinkList = async () => { + const res = await fetch(`${SERVER_URL}api/drinks/hot`); + const data = await res.json(); + return data as GetHotDrinkResponse[]; +}; diff --git a/apps/jurumarble/src/lib/apis/vote/getHotDrinkVote.ts b/apps/jurumarble/src/lib/apis/vote/getHotDrinkVote.ts new file mode 100644 index 00000000..9db46fa4 --- /dev/null +++ b/apps/jurumarble/src/lib/apis/vote/getHotDrinkVote.ts @@ -0,0 +1,14 @@ +import { SERVER_URL } from "lib/env"; + +interface GetHotDrinkVoteResponse { + voteId: number; + voteTitle: string; + drinkAImage: string; + drinkBImage: string; +} + +export const getHotDrinkVote = async () => { + const res = await fetch(`${SERVER_URL}api/votes/drinks/hot`); + const data = await res.json(); + return data as GetHotDrinkVoteResponse; +}; diff --git a/apps/jurumarble/src/lib/env.ts b/apps/jurumarble/src/lib/env.ts new file mode 100644 index 00000000..7c668ef4 --- /dev/null +++ b/apps/jurumarble/src/lib/env.ts @@ -0,0 +1,19 @@ +import Path from "./Path"; + +export const CLIENT_URL = process.env.NEXT_PUBLIC_CLIENT_URL || ""; +export const SERVER_URL = process.env.NEXT_PUBLIC_SERVER_URL || ""; + +export const KAKAO_CLIENT_ID = process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID || ""; +export const NAVER_CLIENT_ID = process.env.NEXT_PUBLIC_NAVER_CLIENT_ID || ""; + +export const KAKAO_MAP_API_KEY = process.env.NEXT_PUBLIC_KAKAO_MAP_API_KEY || ""; +export const KAKAO_LOGIN_REDIRECT_URL = + process.env.NODE_ENV === "development" + ? `http://localhost:3000/${Path.KAKAO_LOGIN_PROCESS}` + : `${CLIENT_URL}${Path.KAKAO_LOGIN_PROCESS}`; +export const NAVER_LOGIN_REDIRECT_URL = + process.env.NODE_ENV === "development" + ? `http://localhost:3000${Path.NAVER_LOGIN_PROCESS}` + : `${CLIENT_URL}${Path.NAVER_LOGIN_PROCESS}`; + +export const DATA_GO_API_KEY = process.env.NEXT_PUBLIC_DATA_GO_API_KEY || ""; diff --git a/apps/jurumarble/src/modules/getQueryClient.tsx b/apps/jurumarble/src/modules/getQueryClient.tsx new file mode 100644 index 00000000..33283bbf --- /dev/null +++ b/apps/jurumarble/src/modules/getQueryClient.tsx @@ -0,0 +1,5 @@ +import { QueryClient } from "@tanstack/query-core"; +import { cache } from "react"; + +const getQueryClient = cache(() => new QueryClient()); +export default getQueryClient; diff --git a/apps/jurumarble/src/modules/hydrateOnClient.tsx b/apps/jurumarble/src/modules/hydrateOnClient.tsx new file mode 100644 index 00000000..7ebaa6c9 --- /dev/null +++ b/apps/jurumarble/src/modules/hydrateOnClient.tsx @@ -0,0 +1,4 @@ +"use client"; + +import { Hydrate as HydrateOnClient } from "@tanstack/react-query"; +export default HydrateOnClient; diff --git a/yarn.lock b/yarn.lock index 74f5dc71..f516635f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1634,6 +1634,7 @@ __metadata: "@svgr/core": ^8.0.0 "@svgr/plugin-jsx": ^8.0.1 "@svgr/plugin-prettier": ^8.0.1 + "@tanstack/query-core": ^4.36.1 "@tanstack/react-query": ^4.33.0 "@tanstack/react-query-devtools": ^4.33.0 "@types/node": 20.5.7 @@ -2312,6 +2313,13 @@ __metadata: languageName: node linkType: hard +"@tanstack/query-core@npm:^4.36.1": + version: 4.36.1 + resolution: "@tanstack/query-core@npm:4.36.1" + checksum: 47672094da20d89402d9fe03bb7b0462be73a76ff9ca715169738bc600a719d064d106d083a8eedae22a2c22de22f87d5eb5d31ef447aba771d9190f2117ed10 + languageName: node + linkType: hard + "@tanstack/react-query-devtools@npm:^4.20.4, @tanstack/react-query-devtools@npm:^4.33.0": version: 4.33.0 resolution: "@tanstack/react-query-devtools@npm:4.33.0"