Skip to content

Commit 4c59298

Browse files
committed
Add Apollo client
1 parent aa63e9c commit 4c59298

File tree

11 files changed

+311
-115
lines changed

11 files changed

+311
-115
lines changed

apps/web/package.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,22 @@
88
"build": "next build",
99
"start": "next start",
1010
"lint": "next lint --max-warnings 0",
11+
"lint:fix": "next lint --fix",
1112
"check-types": "tsc --noEmit"
1213
},
1314
"dependencies": {
15+
"@apollo/client": "^4.0.7",
16+
"@apollo/client-integration-nextjs": "^0.13.2",
1417
"@emotion/cache": "^11.14.0",
1518
"@emotion/react": "^11.14.0",
19+
"@mui/material": "^6.3.0",
1620
"@mui/material-nextjs": "^6.3.0",
1721
"@repo/ui": "*",
22+
"graphql": "^16.11.0",
1823
"next": "^15.5.4",
1924
"react": "^19.0.0",
2025
"react-dom": "^19.0.0",
21-
"@mui/material": "^6.3.0"
26+
"rxjs": "^7.8.1"
2227
},
2328
"devDependencies": {
2429
"@repo/eslint-config": "*",
@@ -28,4 +33,4 @@
2833
"@types/react-dom": "19.0.1",
2934
"typescript": "5.5.4"
3035
}
31-
}
36+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"use client";
2+
3+
import { ApolloLink, HttpLink } from "@apollo/client";
4+
import {
5+
ApolloNextAppProvider,
6+
ApolloClient,
7+
InMemoryCache,
8+
SSRMultipartLink,
9+
} from "@apollo/client-integration-nextjs";
10+
import type { ReactNode } from "react";
11+
12+
function makeClient() {
13+
const httpLink = new HttpLink({
14+
uri: "https://graphql.pokeapi.co/v1beta2",
15+
fetchOptions: { cache: "no-store" }, // avoid stale HTML if you stream/SSR
16+
headers: { accept: "*/*" },
17+
});
18+
19+
// In SSR we prepend the special multipart link to support streaming with Suspense
20+
const link =
21+
typeof window === "undefined"
22+
? ApolloLink.from([new SSRMultipartLink({ stripDefer: true }), httpLink])
23+
: httpLink;
24+
25+
return new ApolloClient({
26+
cache: new InMemoryCache(),
27+
link,
28+
});
29+
}
30+
31+
export default function ApolloProvider({ children }: { children: ReactNode }) {
32+
return (
33+
<ApolloNextAppProvider makeClient={makeClient}>
34+
{children}
35+
</ApolloNextAppProvider>
36+
);
37+
}

apps/web/src/app/layout.tsx

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
11
import type { Metadata } from "next";
22
import "./globals.css";
3-
import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';
3+
import { AppRouterCacheProvider } from "@mui/material-nextjs/v15-appRouter";
4+
import ApolloProvider from "./apollo-provider";
45

5-
import { Roboto } from 'next/font/google';
6-
import { ThemeProvider } from '@mui/material/styles';
7-
import theme from '@repo/ui/theme';
8-
9-
const roboto = Roboto({
10-
weight: ['300', '400', '500', '700'],
11-
subsets: ['latin'],
12-
display: 'swap',
13-
variable: '--font-roboto',
14-
});
6+
import { ThemeProvider } from "@mui/material/styles";
7+
import theme from "@repo/ui/theme";
158

169
export const metadata: Metadata = {
17-
title: "Create Next App",
10+
title: "Pokemon Team Builder",
1811
description: "Generated by create next app",
1912
};
2013

@@ -25,10 +18,10 @@ export default function RootLayout({
2518
}>) {
2619
return (
2720
<html lang="en">
28-
<body className={roboto.variable}>
21+
<body>
2922
<AppRouterCacheProvider>
3023
<ThemeProvider theme={theme}>
31-
{children}
24+
<ApolloProvider>{children}</ApolloProvider>
3225
</ThemeProvider>
3326
</AppRouterCacheProvider>
3427
</body>

apps/web/src/app/page.tsx

Lines changed: 14 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,20 @@
1-
import Image, { type ImageProps } from "next/image";
2-
import { Button } from "@repo/ui";
3-
import styles from "./page.module.css";
4-
5-
type Props = Omit<ImageProps, "src"> & {
6-
srcLight: string;
7-
srcDark: string;
8-
};
1+
"use client";
92

10-
const ThemeImage = (props: Props) => {
11-
const { srcLight, srcDark, ...rest } = props;
3+
import { GET_POKEMON_SPRITES } from "@/lib/graphql/queries";
4+
import styles from "./page.module.css";
125

13-
return (
14-
<>
15-
<Image {...rest} src={srcLight} className="imgLight" />
16-
<Image {...rest} src={srcDark} className="imgDark" />
17-
</>
18-
);
19-
};
6+
import { useQuery } from "@apollo/client/react";
7+
import { useEffect } from "react";
8+
import type { PokemonSpritesResponse } from "@/lib/graphql/types";
209

2110
export default function Home() {
22-
return (
23-
<div className={styles.page}>
24-
<main className={styles.main}>
25-
<ThemeImage
26-
className={styles.logo}
27-
srcLight="turborepo-dark.svg"
28-
srcDark="turborepo-light.svg"
29-
alt="Turborepo logo"
30-
width={180}
31-
height={38}
32-
priority
33-
/>
34-
<ol>
35-
<li>
36-
Get started by editing <code>apps/web/app/page.tsx</code>
37-
</li>
38-
<li>Save and see your changes instantly.</li>
39-
</ol>
11+
const { data } = useQuery<PokemonSpritesResponse>(GET_POKEMON_SPRITES);
12+
13+
useEffect(() => {
14+
if (data) {
15+
console.log(data);
16+
}
17+
}, [data]);
4018

41-
<div className={styles.ctas}>
42-
<a
43-
className={styles.primary}
44-
href="https://vercel.com/new/clone?demo-description=Learn+to+implement+a+monorepo+with+a+two+Next.js+sites+that+has+installed+three+local+packages.&demo-image=%2F%2Fimages.ctfassets.net%2Fe5382hct74si%2F4K8ZISWAzJ8X1504ca0zmC%2F0b21a1c6246add355e55816278ef54bc%2FBasic.png&demo-title=Monorepo+with+Turborepo&demo-url=https%3A%2F%2Fexamples-basic-web.vercel.sh%2F&from=templates&project-name=Monorepo+with+Turborepo&repository-name=monorepo-turborepo&repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fturborepo%2Ftree%2Fmain%2Fexamples%2Fbasic&root-directory=apps%2Fdocs&skippable-integrations=1&teamSlug=vercel&utm_source=create-turbo"
45-
target="_blank"
46-
rel="noopener noreferrer"
47-
>
48-
<Image
49-
className={styles.logo}
50-
src="/vercel.svg"
51-
alt="Vercel logomark"
52-
width={20}
53-
height={20}
54-
/>
55-
Deploy now
56-
</a>
57-
<a
58-
href="https://turbo.build/repo/docs?utm_source"
59-
target="_blank"
60-
rel="noopener noreferrer"
61-
className={styles.secondary}
62-
>
63-
Read our docs
64-
</a>
65-
</div>
66-
<Button appName="web" className={styles.secondary}>
67-
Open alert
68-
</Button>
69-
</main>
70-
<footer className={styles.footer}>
71-
<a
72-
href="https://vercel.com/templates?search=turborepo&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
73-
target="_blank"
74-
rel="noopener noreferrer"
75-
>
76-
<Image
77-
aria-hidden
78-
src="/window.svg"
79-
alt="Window icon"
80-
width={16}
81-
height={16}
82-
/>
83-
Examples
84-
</a>
85-
<a
86-
href="https://turbo.build?utm_source=create-turbo"
87-
target="_blank"
88-
rel="noopener noreferrer"
89-
>
90-
<Image
91-
aria-hidden
92-
src="/globe.svg"
93-
alt="Globe icon"
94-
width={16}
95-
height={16}
96-
/>
97-
Go to turbo.build →
98-
</a>
99-
</footer>
100-
</div>
101-
);
19+
return <div className={styles.page}></div>;
10220
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { gql } from "@apollo/client";
2+
3+
export const GET_POKEMON_SPRITES = gql`
4+
query MyQuery {
5+
pokemonsprites {
6+
pokemon {
7+
name
8+
order
9+
id
10+
}
11+
sprites
12+
}
13+
}
14+
`;

apps/web/src/lib/graphql/types.ts

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
export interface PokemonSpritesResponse {
2+
pokemonsprites: PokemonSpriteEntry[];
3+
}
4+
5+
export interface PokemonSpriteEntry {
6+
__typename: "pokemonsprites";
7+
pokemon: {
8+
__typename: "pokemon";
9+
id: number;
10+
name: string;
11+
order: number;
12+
};
13+
sprites: PokemonSprites;
14+
}
15+
16+
export interface PokemonSprites {
17+
back_default: string | null;
18+
back_female: string | null;
19+
back_shiny: string | null;
20+
back_shiny_female: string | null;
21+
front_default: string | null;
22+
front_female: string | null;
23+
front_shiny: string | null;
24+
front_shiny_female: string | null;
25+
other: {
26+
home: SpriteVariants;
27+
showdown: SpriteVariants;
28+
dream_world: Partial<
29+
Record<"front_default" | "front_female", string | null>
30+
>;
31+
"official-artwork": Partial<
32+
Record<"front_default" | "front_shiny", string | null>
33+
>;
34+
};
35+
versions: {
36+
"generation-i": {
37+
yellow: GenerationISprites;
38+
"red-blue": GenerationISprites;
39+
};
40+
"generation-ii": {
41+
gold: GenerationIISprites;
42+
silver: GenerationIISprites;
43+
crystal: GenerationIICrystalSprites;
44+
};
45+
"generation-iii": {
46+
emerald: SimpleFrontSprites;
47+
"ruby-sapphire": SimpleBackFrontSprites;
48+
"firered-leafgreen": SimpleBackFrontSprites;
49+
};
50+
"generation-iv": {
51+
platinum: GenderedSprites;
52+
"diamond-pearl": GenderedSprites;
53+
"heartgold-soulsilver": GenderedSprites;
54+
};
55+
"generation-v": {
56+
"black-white": GenerationVBlackWhiteSprites;
57+
};
58+
"generation-vi": {
59+
"x-y": SimpleFrontSpritesWithGender;
60+
"omegaruby-alphasapphire": SimpleFrontSpritesWithGender;
61+
};
62+
"generation-vii": {
63+
icons: SimpleFrontSpritesWithGender;
64+
"ultra-sun-ultra-moon": SimpleFrontSpritesWithGender;
65+
};
66+
"generation-viii": {
67+
icons: SimpleFrontSpritesWithGender;
68+
};
69+
};
70+
}
71+
72+
export interface SpriteVariants {
73+
front_default: string | null;
74+
front_shiny: string | null;
75+
front_female: string | null;
76+
front_shiny_female: string | null;
77+
back_default?: string | null;
78+
back_female?: string | null;
79+
back_shiny?: string | null;
80+
back_shiny_female?: string | null;
81+
}
82+
83+
export interface GenerationISprites {
84+
back_gray: string | null;
85+
front_gray: string | null;
86+
back_default: string | null;
87+
front_default: string | null;
88+
back_transparent: string | null;
89+
front_transparent: string | null;
90+
}
91+
92+
export interface GenerationIISprites {
93+
back_shiny: string | null;
94+
front_shiny: string | null;
95+
back_default: string | null;
96+
front_default: string | null;
97+
front_transparent?: string | null;
98+
}
99+
100+
export interface GenerationIICrystalSprites extends GenerationIISprites {
101+
back_transparent: string | null;
102+
front_transparent: string | null;
103+
back_shiny_transparent: string | null;
104+
front_shiny_transparent: string | null;
105+
}
106+
107+
export interface SimpleFrontSprites {
108+
front_default: string | null;
109+
front_shiny: string | null;
110+
}
111+
112+
export interface SimpleBackFrontSprites extends SimpleFrontSprites {
113+
back_default: string | null;
114+
back_shiny: string | null;
115+
}
116+
117+
export interface SimpleFrontSpritesWithGender extends SimpleFrontSprites {
118+
front_female: string | null;
119+
front_shiny_female: string | null;
120+
}
121+
122+
export interface GenderedSprites extends SimpleBackFrontSprites {
123+
back_female: string | null;
124+
back_shiny_female: string | null;
125+
front_female: string | null;
126+
front_shiny_female: string | null;
127+
}
128+
129+
export interface GenerationVBlackWhiteSprites extends GenderedSprites {
130+
animated: GenderedSprites;
131+
}

apps/web/turbo.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"extends": ["//"],
23
"$schema": "https://turbo.build/schema.json",
34
"tasks": {
45
"dev": {

packages/eslint-config/base.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export const config = [
1919
},
2020
rules: {
2121
"turbo/no-undeclared-env-vars": "warn",
22+
"@typescript-eslint/consistent-type-imports": "error",
2223
},
2324
},
2425
{

packages/ui/src/button/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import { ReactNode } from "react";
3+
import type { ReactNode } from "react";
44

55
interface ButtonProps {
66
children: ReactNode;

0 commit comments

Comments
 (0)