diff --git a/__tests__/src/apis/coh3stats-api.test.ts b/__tests__/src/apis/coh3stats-api.test.ts index c99320a3..b7e85f95 100644 --- a/__tests__/src/apis/coh3stats-api.test.ts +++ b/__tests__/src/apis/coh3stats-api.test.ts @@ -10,6 +10,7 @@ import { getStatsData, GET_ANALYSIS_STATS, } from "../../../src/apis/coh3stats-api"; +import config from "../../../config"; describe("coh3stats-api", () => { // Mock the fetch function @@ -306,7 +307,7 @@ describe("coh3stats-api", () => { const response = await getStatsData(123, "now", "gameStats", "cache-key-4"); expect(global.fetch).toBeCalledWith( - `https://cache.coh3stats.com/getAnalysisStatsHttp?startDate=123&endDate=now&type=gameStats&v=${GET_ANALYSIS_STATS}&ock=cache-key-4`, + `${config.BASE_CLOUD_FUNCTIONS_PROXY_URL}/getAnalysisStatsHttp?startDate=123&endDate=now&type=gameStats&v=${GET_ANALYSIS_STATS}&ock=cache-key-4`, { headers: undefined }, ); diff --git a/config.ts b/config.ts index 2422e108..97cf3264 100644 --- a/config.ts +++ b/config.ts @@ -365,7 +365,7 @@ const config = { BASE_CLOUD_FUNCTIONS_URL: useFirebaseEmulators ? firebaseFunctions.EMULATORS_URL : firebaseFunctions.CLOUD_URL, - BASED_CLOUD_FUNCTIONS_PROXY_URL: useFirebaseEmulators + BASE_CLOUD_FUNCTIONS_PROXY_URL: useFirebaseEmulators ? firebaseFunctions.EMULATORS_URL : "https://cache.coh3stats.com", patches, diff --git a/package.json b/package.json index d31b3e4c..0f2f684e 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "next:build": "next build", "build:analyze": "ANALYZE=true yarn build", "test": "TZ=UTC yarn jest", + "test:windows": "yarn jest", "lint": "next lint", "lint:eslint": "eslint **/*.{ts,tsx,js}", "lint:prettier": "prettier --check .", diff --git a/pages/search.tsx b/pages/search.tsx index 9acfc311..bafa4891 100644 --- a/pages/search.tsx +++ b/pages/search.tsx @@ -1,6 +1,15 @@ -import { GetServerSideProps, NextPage } from "next"; -import config from "../config"; -import { Center, Container, Divider, Flex, Input, Space, Stack, Text } from "@mantine/core"; +import { NextPage } from "next"; +import { + Center, + Container, + Divider, + Flex, + Input, + Loader, + Space, + Stack, + Text, +} from "@mantine/core"; import { IconSearch, IconDatabaseOff } from "@tabler/icons-react"; import Head from "next/head"; import React, { useEffect } from "react"; @@ -12,22 +21,21 @@ import { SearchPlayerCard } from "../components/search/search-player-card"; import ErrorCard from "../components/error-card"; import { getSearchRoute } from "../src/routes"; import { SearchPageUsed, SearchPageView } from "../src/firebase/analytics"; +import { getSearchUrl } from "../src/apis/coh3stats-api"; /** * * Example URL http://localhost:3000/search?q=Thomas * * - * @param searchQuery - * @param data - * @param error * @constructor */ -const Search: NextPage<{ - data: Array | null; - error: string | null; -}> = ({ data, error }) => { +const Search: NextPage = () => { + const [loading, setLoading] = React.useState(false); + const [error, setError] = React.useState(null); + const [data, setData] = React.useState | null>(null); + const { query, push } = useRouter(); const { q } = query; @@ -39,6 +47,32 @@ const Search: NextPage<{ useEffect(() => { q ? setSearchValue(q as string) : setSearchValue(""); SearchPageUsed(q as string); + + (async () => { + if (q) { + try { + setLoading(true); + + const searchRes = await fetch(getSearchUrl(q as string)); + + if (searchRes.status !== 200) { + const resData = await searchRes.json(); + throw new Error( + `Failed getting data for player id ${q}: ${JSON.stringify(resData)} `, + ); + } else { + setData(convertSearchResultsToPlayerCardData(await searchRes.json())); + setError(null); + } + } catch (e: any) { + console.error(`Failed getting data for player id ${q}`); + console.error(e); + setError(e.message); + } finally { + setLoading(false); + } + } + })(); }, [q]); const description = "Search for any players in Company of Heroes 3."; @@ -46,7 +80,7 @@ const Search: NextPage<{ const debouncedSearch = debounce((value) => { if (value.length > 1) { - push(getSearchRoute(value)); + push(getSearchRoute(value), undefined, { shallow: true }); } }, 600); @@ -58,7 +92,12 @@ const Search: NextPage<{ {q && ( <> - {data && ( + {loading && ( +
+ +
+ )} + {data && !loading && ( {data.length === 0 && ( @@ -138,41 +177,4 @@ const convertSearchResultsToPlayerCardData = ( return foundProfiles; }; -export const getServerSideProps: GetServerSideProps = async ({ query, res }) => { - let { q } = query; - - q = q || ""; - - let data = null; - let error = null; - - if (q) { - try { - const searchRes = await fetch( - `${config.BASE_CLOUD_FUNCTIONS_URL}/searchPlayers2Http?alias=${encodeURIComponent(q as string)}`, - ); - - if (searchRes.status !== 200) { - data = await searchRes.json(); - throw new Error(`Failed getting data for player id ${q}: ${JSON.stringify(data)} `); - } else { - data = convertSearchResultsToPlayerCardData(await searchRes.json()); - } - - res.setHeader( - "Cache-Control", - "public, max-age=600, s-maxage=1800, stale-while-revalidate=3600", - ); - } catch (e: any) { - console.error(`Failed getting data for player id ${q}`); - console.error(e); - error = e.message; - } - } - - return { - props: { data: data, error }, // will be passed to the page component as props - }; -}; - export default Search; diff --git a/src/apis/coh3stats-api.ts b/src/apis/coh3stats-api.ts index 71c675e0..76dc18e3 100644 --- a/src/apis/coh3stats-api.ts +++ b/src/apis/coh3stats-api.ts @@ -24,7 +24,7 @@ const getPlayerCardInfoUrl = (playerID: string | number, cache_proxy = false) => const path = `/getPlayerCardInfoHttp?relicId=${playerID}`; return cache_proxy - ? encodeURI(`${config.BASED_CLOUD_FUNCTIONS_PROXY_URL}${path}`) + ? encodeURI(`${config.BASE_CLOUD_FUNCTIONS_PROXY_URL}${path}`) : encodeURI(`${config.BASE_CLOUD_FUNCTIONS_URL}${path}`); }; @@ -32,7 +32,7 @@ const getPlayerCardStatsUrl = (playerID: string | number, cache_proxy = true) => const path = `/getPlayerCardStatsHttp?relicId=${playerID}`; return cache_proxy - ? encodeURI(`${config.BASED_CLOUD_FUNCTIONS_PROXY_URL}${path}`) + ? encodeURI(`${config.BASE_CLOUD_FUNCTIONS_PROXY_URL}${path}`) : encodeURI(`${config.BASE_CLOUD_FUNCTIONS_URL}${path}`); }; @@ -41,7 +41,7 @@ const getPlayerRecentMatchesUrl = (playerID: string | number) => { }; const getMatchUrl = (matchID: string | number, profileIDs?: Array) => { - let url = `${config.BASED_CLOUD_FUNCTIONS_PROXY_URL}/getMatchHttp?matchID=${matchID}`; + let url = `${config.BASE_CLOUD_FUNCTIONS_PROXY_URL}/getMatchHttp?matchID=${matchID}`; if (profileIDs && profileIDs.length > 0) { url += `&profileIDs=[${profileIDs.join(",")}]`; @@ -54,11 +54,17 @@ const getTwitchStreamsUrl = () => { return encodeURI(`${config.BASE_CLOUD_FUNCTIONS_URL}/getTwitchStreamsHttp`); }; +const getSearchUrl = (searchQuery: string) => { + return encodeURI( + `${config.BASE_CLOUD_FUNCTIONS_PROXY_URL}/searchPlayers2Http?alias=${encodeURIComponent(searchQuery)}`, + ); +}; + const getGlobalAchievementsUrl = (cache_proxy = true) => { const path = `/getGlobalAchievementsHttp`; return cache_proxy - ? encodeURI(`${config.BASED_CLOUD_FUNCTIONS_PROXY_URL}${path}`) + ? encodeURI(`${config.BASE_CLOUD_FUNCTIONS_PROXY_URL}${path}`) : encodeURI(`${config.BASE_CLOUD_FUNCTIONS_URL}${path}`); }; @@ -69,7 +75,7 @@ const getReplayUrl = (matchID: string | number) => { const setReplayFileUrl = () => { return encodeURI( // This will be in the browser / we don't want to touch our GCP directly without proxy - `${config.BASED_CLOUD_FUNCTIONS_PROXY_URL}/setReplayFileHttp`, + `${config.BASE_CLOUD_FUNCTIONS_PROXY_URL}/setReplayFileHttp`, ); }; @@ -84,7 +90,7 @@ const getStatsUrl = ( filters = undefined; } - let url = `${config.BASED_CLOUD_FUNCTIONS_PROXY_URL}/getAnalysisStatsHttp?startDate=${startDate}&endDate=${endDate}&type=${type}&v=${GET_ANALYSIS_STATS}&ock=${ock}`; + let url = `${config.BASE_CLOUD_FUNCTIONS_PROXY_URL}/getAnalysisStatsHttp?startDate=${startDate}&endDate=${endDate}&type=${type}&v=${GET_ANALYSIS_STATS}&ock=${ock}`; if (filters && filters.length > 0) { const filtersString = filters.join(","); @@ -339,7 +345,7 @@ const getPlayersCardsConfigsHttp = async (): Promise<{ profiles: Array }> = }; const getYouTubeVideosHttp = async (): Promise> => { - const path = encodeURI(`${config.BASED_CLOUD_FUNCTIONS_PROXY_URL}/getYouTubeVideosHttp`); + const path = encodeURI(`${config.BASE_CLOUD_FUNCTIONS_PROXY_URL}/getYouTubeVideosHttp`); try { const response = await fetch(path, { @@ -365,7 +371,7 @@ const getYouTubeVideosHttp = async (): Promise> => { const triggerPlayerNemesisAliasesUpdate = async (playerID: string | number) => { const path = encodeURI( - `${config.BASED_CLOUD_FUNCTIONS_PROXY_URL}/getPlayerNemesisUpdatesHttp?relicId=${playerID}`, + `${config.BASE_CLOUD_FUNCTIONS_PROXY_URL}/getPlayerNemesisUpdatesHttp?relicId=${playerID}`, ); const response = await fetch(path, { @@ -540,4 +546,5 @@ export { triggerPlayerNemesisAliasesUpdate, getOldLeaderboardData, generateReplayUrl, + getSearchUrl, };