- {games.map((game) => (
-
-
-
-
-
-
-
-
{game.ratingAverage} out of 5 stars
-
- {[0, 1, 2, 3, 4].map((rating) => (
-
rating
- ? "text-yellow-400"
- : "text-gray-100",
- "h-5 w-5 flex-shrink-0"
- )}
- aria-hidden="true"
- />
- ))}
+ {games.map(
+ (game) =>
+ game && (
+
+
+
+
+
+
+
+
+ {game.ratingAverage} out of 5 stars
+
+
+
+ {game.reviewsCount || 0} reviews
+
+
+ {game.clipsCount || 0} reviews
+
+
-
- {game.reviewsCount || 0} reviews
-
-
- {game.clipsCount || 0} reviews
-
-
-
- ))}
+ )
+ )}
);
}
+
+function RatingStars({ ratingAverage }: { ratingAverage: number }) {
+ return (
+
+ {[0, 1, 2, 3, 4].map((rating) => (
+ rating ? "text-yellow-400" : "text-gray-100",
+ "h-5 w-5 flex-shrink-0"
+ )}
+ aria-hidden="true"
+ />
+ ))}
+
+ );
+}
diff --git a/frontend/graphql/generated/gql.ts b/frontend/graphql/generated/gql.ts
index 440e446..ea62d3b 100644
--- a/frontend/graphql/generated/gql.ts
+++ b/frontend/graphql/generated/gql.ts
@@ -15,6 +15,8 @@ import { TypedDocumentNode as DocumentNode } from "@graphql-typed-document-node/
const documents = {
"\n query game($gameId: ID!) {\n game(id: $gameId) {\n id\n title\n imageUrl\n reviewsCount\n clipsCount\n publishedAt\n ratingAverage\n reviews {\n body\n rating\n createdAt\n }\n }\n }\n":
types.GameDocument,
+ "\n query games($first: Int, $last: Int, $before: String, $after: String) {\n games(first: $first, last: $last, before: $before, after: $after) {\n nodes {\n id\n title\n imageUrl\n reviewsCount\n clipsCount\n publishedAt\n ratingAverage\n }\n }\n }\n":
+ types.GamesDocument,
"\n query me {\n me {\n id\n displayName\n photoUrl\n }\n }\n":
types.MeDocument,
};
@@ -39,6 +41,12 @@ export function graphql(source: string): unknown;
export function graphql(
source: "\n query game($gameId: ID!) {\n game(id: $gameId) {\n id\n title\n imageUrl\n reviewsCount\n clipsCount\n publishedAt\n ratingAverage\n reviews {\n body\n rating\n createdAt\n }\n }\n }\n"
): (typeof documents)["\n query game($gameId: ID!) {\n game(id: $gameId) {\n id\n title\n imageUrl\n reviewsCount\n clipsCount\n publishedAt\n ratingAverage\n reviews {\n body\n rating\n createdAt\n }\n }\n }\n"];
+/**
+ * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
+ */
+export function graphql(
+ source: "\n query games($first: Int, $last: Int, $before: String, $after: String) {\n games(first: $first, last: $last, before: $before, after: $after) {\n nodes {\n id\n title\n imageUrl\n reviewsCount\n clipsCount\n publishedAt\n ratingAverage\n }\n }\n }\n"
+): (typeof documents)["\n query games($first: Int, $last: Int, $before: String, $after: String) {\n games(first: $first, last: $last, before: $before, after: $after) {\n nodes {\n id\n title\n imageUrl\n reviewsCount\n clipsCount\n publishedAt\n ratingAverage\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
diff --git a/frontend/graphql/generated/graphql.ts b/frontend/graphql/generated/graphql.ts
index 3ae7686..5477341 100644
--- a/frontend/graphql/generated/graphql.ts
+++ b/frontend/graphql/generated/graphql.ts
@@ -269,6 +269,30 @@ export type GameQuery = {
};
};
+export type GamesQueryVariables = Exact<{
+ first?: InputMaybe
;
+ last?: InputMaybe;
+ before?: InputMaybe;
+ after?: InputMaybe;
+}>;
+
+export type GamesQuery = {
+ __typename?: "Query";
+ games: {
+ __typename?: "GameConnection";
+ nodes?: Array<{
+ __typename?: "Game";
+ id: string;
+ title: string;
+ imageUrl?: string | null;
+ reviewsCount: number;
+ clipsCount: number;
+ publishedAt?: string | null;
+ ratingAverage: number;
+ } | null> | null;
+ };
+};
+
export type MeQueryVariables = Exact<{ [key: string]: never }>;
export type MeQuery = {
@@ -359,6 +383,126 @@ export const GameDocument = {
},
],
} as unknown as DocumentNode;
+export const GamesDocument = {
+ kind: "Document",
+ definitions: [
+ {
+ kind: "OperationDefinition",
+ operation: "query",
+ name: { kind: "Name", value: "games" },
+ variableDefinitions: [
+ {
+ kind: "VariableDefinition",
+ variable: {
+ kind: "Variable",
+ name: { kind: "Name", value: "first" },
+ },
+ type: { kind: "NamedType", name: { kind: "Name", value: "Int" } },
+ },
+ {
+ kind: "VariableDefinition",
+ variable: { kind: "Variable", name: { kind: "Name", value: "last" } },
+ type: { kind: "NamedType", name: { kind: "Name", value: "Int" } },
+ },
+ {
+ kind: "VariableDefinition",
+ variable: {
+ kind: "Variable",
+ name: { kind: "Name", value: "before" },
+ },
+ type: { kind: "NamedType", name: { kind: "Name", value: "String" } },
+ },
+ {
+ kind: "VariableDefinition",
+ variable: {
+ kind: "Variable",
+ name: { kind: "Name", value: "after" },
+ },
+ type: { kind: "NamedType", name: { kind: "Name", value: "String" } },
+ },
+ ],
+ selectionSet: {
+ kind: "SelectionSet",
+ selections: [
+ {
+ kind: "Field",
+ name: { kind: "Name", value: "games" },
+ arguments: [
+ {
+ kind: "Argument",
+ name: { kind: "Name", value: "first" },
+ value: {
+ kind: "Variable",
+ name: { kind: "Name", value: "first" },
+ },
+ },
+ {
+ kind: "Argument",
+ name: { kind: "Name", value: "last" },
+ value: {
+ kind: "Variable",
+ name: { kind: "Name", value: "last" },
+ },
+ },
+ {
+ kind: "Argument",
+ name: { kind: "Name", value: "before" },
+ value: {
+ kind: "Variable",
+ name: { kind: "Name", value: "before" },
+ },
+ },
+ {
+ kind: "Argument",
+ name: { kind: "Name", value: "after" },
+ value: {
+ kind: "Variable",
+ name: { kind: "Name", value: "after" },
+ },
+ },
+ ],
+ selectionSet: {
+ kind: "SelectionSet",
+ selections: [
+ {
+ kind: "Field",
+ name: { kind: "Name", value: "nodes" },
+ selectionSet: {
+ kind: "SelectionSet",
+ selections: [
+ { kind: "Field", name: { kind: "Name", value: "id" } },
+ { kind: "Field", name: { kind: "Name", value: "title" } },
+ {
+ kind: "Field",
+ name: { kind: "Name", value: "imageUrl" },
+ },
+ {
+ kind: "Field",
+ name: { kind: "Name", value: "reviewsCount" },
+ },
+ {
+ kind: "Field",
+ name: { kind: "Name", value: "clipsCount" },
+ },
+ {
+ kind: "Field",
+ name: { kind: "Name", value: "publishedAt" },
+ },
+ {
+ kind: "Field",
+ name: { kind: "Name", value: "ratingAverage" },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ ],
+} as unknown as DocumentNode;
export const MeDocument = {
kind: "Document",
definitions: [
diff --git a/frontend/graphql/queries/games.ts b/frontend/graphql/queries/games.ts
new file mode 100644
index 0000000..c4d27e0
--- /dev/null
+++ b/frontend/graphql/queries/games.ts
@@ -0,0 +1,16 @@
+import { gql } from "@apollo/client";
+export default gql`
+ query games($first: Int, $last: Int, $before: String, $after: String) {
+ games(first: $first, last: $last, before: $before, after: $after) {
+ nodes {
+ id
+ title
+ imageUrl
+ reviewsCount
+ clipsCount
+ publishedAt
+ ratingAverage
+ }
+ }
+ }
+`;
diff --git a/frontend/pages/index.tsx b/frontend/pages/index.tsx
index 507bfc8..d020deb 100644
--- a/frontend/pages/index.tsx
+++ b/frontend/pages/index.tsx
@@ -1,13 +1,13 @@
import GameList from "@/components/GameList";
-import { ApolloClient, InMemoryCache } from "@apollo/client";
+import { createApolloClient } from "@/graphql/client";
import { NextPage } from "next";
import { withUserTokenSSR } from "next-firebase-auth";
import Head from "next/head";
-import { GameDocument, GameQuery } from "../graphql/generated/graphql";
+import { GamesDocument, GamesQuery } from "../graphql/generated/graphql";
-type Game = GameQuery["game"];
+type Games = GamesQuery["games"]["nodes"];
-const Home: NextPage<{ games: Game[] }> = ({ games }) => {
+const Home: NextPage<{ games: Games }> = ({ games }) => {
return (
@@ -24,33 +24,21 @@ const Home: NextPage<{ games: Game[] }> = ({ games }) => {
};
export const getServerSideProps = withUserTokenSSR()(async ({ user }) => {
- const GAME_IDS: string[] = [
- "Z2lkOi8vYXBwbGljYXRpb24vR2FtZS8wQkR2OUZ3eFNCRkJ1akFUcHZkdw",
- "Z2lkOi8vYXBwbGljYXRpb24vR2FtZS8wTllsbmV0ejEzRkJPeWI1MDdyTw",
- "Z2lkOi8vYXBwbGljYXRpb24vR2FtZS8waGh2dGkycm40dE92OG14UVFxcQ",
- ];
-
- let token: string | null;
- if (user) token = await user.getIdToken(true);
-
- const client = new ApolloClient({
- uri: process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT_URL,
- cache: new InMemoryCache(),
+ const token = (await user?.getIdToken(true)) ?? null;
+
+ const client = createApolloClient(token);
+ const {
+ data: { games },
+ } = await client.query({
+ query: GamesDocument,
+ variables: {
+ first: 5,
+ },
});
- const games: Game[] = await Promise.all(
- GAME_IDS.map(async (gameId) => {
- const { data } = await client.query({
- query: GameDocument,
- variables: { gameId },
- });
- return data.game;
- })
- );
-
return {
props: {
- games,
+ games: games.nodes,
},
};
});