From c7c4ff6c1ae1b590fabd2192c319703afa67d52b Mon Sep 17 00:00:00 2001 From: Ngo Lap Nguyen Date: Fri, 10 Mar 2023 15:39:06 +0700 Subject: [PATCH] feat: bind get games from game store api --- package.json | 1 + src/stores/game.ts | 10 ++ src/types/games.ts | 26 +++- src/ui/components/Menu/MinigameMenu.tsx | 119 ++++++++++-------- src/ui/components/Pagination.tsx | 41 ++++++ .../components/minigames/MinigameIframes.tsx | 4 +- .../skeletons/MinigameGridSkeleton.tsx | 30 +++++ yarn.lock | 19 +++ 8 files changed, 189 insertions(+), 61 deletions(-) create mode 100644 src/ui/components/Pagination.tsx create mode 100644 src/ui/components/skeletons/MinigameGridSkeleton.tsx diff --git a/package.json b/package.json index ab8afb4..e3434e8 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@sentry/react": "^7.36.0", "@sentry/tracing": "^7.36.0", "@tanstack/react-virtual": "^3.0.0-beta.48", + "@tippyjs/react": "^4.2.6", "@unocss/preset-uno": "^0.48.3", "@unocss/transformer-variant-group": "^0.48.3", "@unocss/vite": "^0.48.3", diff --git a/src/stores/game.ts b/src/stores/game.ts index 3a2084d..f16d070 100644 --- a/src/stores/game.ts +++ b/src/stores/game.ts @@ -26,6 +26,7 @@ import { Socket, Channel } from "phoenix"; import { Ad } from "types/ads"; import produce from "immer"; import { Minigame } from "types/games"; +import { Pagination } from "types/apis"; export const DEFAULT_PLAYER = { name: "Nez", @@ -126,6 +127,9 @@ interface State { closeMenu: () => void; minigame?: Minigame; + getMinigames: ( + params: Partial + ) => Promise>; startMinigame: (game: Minigame) => void; stopMinigame: () => void; @@ -403,6 +407,12 @@ export const useGameState = create((set, get) => ({ }, minigame: undefined, + getMinigames: (params) => { + const queryString = new URLSearchParams(params as any); + return fetch( + `https://game-store-api.console.so/api/v1/games?${queryString.toString()}` + ).then((res) => res.json()); + }, startMinigame: (minigame: Minigame) => { const game = get().game; diff --git a/src/types/games.ts b/src/types/games.ts index 2114992..80d1ad1 100644 --- a/src/types/games.ts +++ b/src/types/games.ts @@ -1,10 +1,24 @@ -export interface Minigame { +export interface MinigamePublisher { + website: string; + updated_at: string; + name: string; + inserted_at: string; id: string; - src: string; + eth_address: string; + country: string; +} +export interface Minigame { + version: string; + updated_at: string; + thumbnail: string; + tags: string[]; + status: string; + runner_url: string; + publisher: MinigamePublisher; + platform: string; name: string; + inserted_at: string; + id: string; + icon: string; description: string; - type: "browser"; - tags: string[]; - thumbnailSrc: string; - logoSrc: string; } diff --git a/src/ui/components/Menu/MinigameMenu.tsx b/src/ui/components/Menu/MinigameMenu.tsx index aeeab99..21da0c5 100644 --- a/src/ui/components/Menu/MinigameMenu.tsx +++ b/src/ui/components/Menu/MinigameMenu.tsx @@ -2,38 +2,27 @@ import { useGameState } from "stores/game"; import { GradientContainer } from "../GradientContainer"; import { Minigame } from "types/games"; import { Fragment, useMemo, useState } from "react"; +import useSWR from "swr"; +import Tippy from "@tippyjs/react"; +import { Pagination } from "../Pagination"; +import { MinigameGridSkeleton } from "../skeletons/MinigameGridSkeleton"; +import "tippy.js/dist/tippy.css"; const CACHE_KEY = "pod-minigame-cache"; - -const mockData: Minigame[] = [ - { - thumbnailSrc: "/assets/images/title-screen-bg.jpeg", - logoSrc: "/minigames/tripod.png", - name: "Tripod", - description: - "A match-3 game where players progress by combining 3 pieces of the same type to get the next piece, all the way to the top!", - id: "tripod", - src: "https://tripod-web.vercel.app/", - type: "browser", - tags: ["puzzle", "strategy"], - }, - { - thumbnailSrc: "/assets/images/title-screen-bg.jpeg", - logoSrc: "/minigames/hunger-game.webp", - name: "Hunger Game", - description: - "Collect points while racing to find the portal before your opponents. Just watch out for explosions!", - id: "hunger-game", - src: "https://the-hunger-game.vercel.app/", - type: "browser", - tags: ["puzzle", "team"], - }, -]; +const PAGE_SIZE = 12; export const MinigameMenu = () => { - const { closeMenu, startMinigame, getActiveScene } = useGameState(); + const { closeMenu, startMinigame, getActiveScene, getMinigames } = + useGameState(); const [searchQuery, setSearchQuery] = useState(""); + const [page, setPage] = useState(1); + const { data, isLoading } = useSWR(["minigames", page], () => + getMinigames({ page, size: PAGE_SIZE }) + ); + const minigames = data?.data ?? []; + const isLastPage = minigames.length < PAGE_SIZE; + const updateCache = (game: Minigame) => { const cache = JSON.parse(window.localStorage.getItem(CACHE_KEY) || "{}"); if (Array.isArray(cache.recentlyPlayedGames)) { @@ -54,13 +43,26 @@ export const MinigameMenu = () => { }); }; + const renderTags = (tags: string[]) => { + return tags.map((tag) => { + return ( + + {tag} + + ); + }); + }; + const renderGameCard = (game: Minigame) => { return ( -
- +
+
- +
{game.name}
{ Play on browser
-
- {game.tags.map((tag) => ( - - {tag} - - ))} -
+ + {renderTags(game.tags)} +
+ } + > +
+ {renderTags(game.tags)} +
+ + - + +
+ ); +}; diff --git a/src/ui/components/minigames/MinigameIframes.tsx b/src/ui/components/minigames/MinigameIframes.tsx index 31f1707..cfef473 100644 --- a/src/ui/components/minigames/MinigameIframes.tsx +++ b/src/ui/components/minigames/MinigameIframes.tsx @@ -12,7 +12,7 @@ export const MinigameIframes = () => { if (minigame) { const hs = new Postmate({ container: document.getElementById("minigame-frame"), - url: minigame.src, + url: minigame.runner_url, name: minigame.name, classListArray: ["flex-1"], }); @@ -44,7 +44,7 @@ export const MinigameIframes = () => { >
- + {minigame.name}