Skip to content

Commit 98b1e71

Browse files
committed
feat(network): add query factory library
1 parent 58c8dc1 commit 98b1e71

File tree

19 files changed

+368
-49
lines changed

19 files changed

+368
-49
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"@expo/metro-runtime": "^3.2.3",
5959
"@gorhom/bottom-sheet": "4.6.3",
6060
"@hookform/resolvers": "^3.9.0",
61+
"@lukemorales/query-key-factory": "^1.3.4",
6162
"@shopify/flash-list": "1.6.4",
6263
"@tanstack/react-query": "^5.52.1",
6364
"app-icon-badge": "^0.0.15",

pnpm-lock.yaml

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/api/auth/use-login.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { createMutation } from 'react-query-kit';
2+
3+
import { client } from '../common';
4+
5+
type Variables = {
6+
username: string;
7+
password: string;
8+
expiresInMins?: number;
9+
};
10+
11+
type Response = {
12+
id: number;
13+
username: string;
14+
email: string;
15+
accessToken: string;
16+
refreshToken: string;
17+
};
18+
19+
const login = async (variables: Variables) => {
20+
const { data } = await client({
21+
url: 'auth/login',
22+
method: 'POST',
23+
data: variables,
24+
headers: {
25+
'Content-Type': 'application/json',
26+
},
27+
});
28+
return data;
29+
};
30+
31+
export const useLogin = createMutation<Response, Variables, Error>({
32+
mutationFn: (variables) => login(variables),
33+
});

src/api/carts/query-keys.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { createQueryKeys } from '@lukemorales/query-key-factory';
2+
3+
export const cartKeys = createQueryKeys('carts', {
4+
list: (filters) => ['carts', filters],
5+
detail: (id) => [id],
6+
});

src/api/carts/types.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export type Product = {
2+
id: number;
3+
title: string;
4+
price: number;
5+
quantity: number;
6+
total: number;
7+
discountPercentage: number;
8+
discountedTotal: number;
9+
thumbnail: string;
10+
};
11+
export type Cart = {
12+
id: number;
13+
products: Product[];
14+
total: number;
15+
discountedTotal: number;
16+
userId: number;
17+
totalProducts: number;
18+
totalQuantity: number;
19+
};

src/api/carts/use-carts.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { useInfiniteQuery } from '@tanstack/react-query';
2+
3+
import { client } from '../common';
4+
import { cartKeys } from './query-keys';
5+
6+
type Variables = {
7+
limit?: number | string;
8+
offset?: number | string;
9+
};
10+
11+
const DEFAULT_LIMIT = 10;
12+
const DEFAULT_OFFSET = 0;
13+
14+
const getCarts = async ({
15+
limit = DEFAULT_LIMIT,
16+
offset = DEFAULT_OFFSET,
17+
}: Variables) => {
18+
const params = new URLSearchParams({
19+
limit: limit.toString(),
20+
offset: offset.toString(),
21+
}).toString();
22+
const { data } = await client.get(`carts?${params}`);
23+
return { data, offset: Number(offset), limit: Number(limit) };
24+
};
25+
26+
export const useCarts = (variables: Variables) =>
27+
useInfiniteQuery({
28+
...cartKeys.list(variables),
29+
queryFn: () => getCarts(variables),
30+
initialPageParam: { offset: DEFAULT_OFFSET, limit: DEFAULT_LIMIT },
31+
getNextPageParam: (lastPage) => {
32+
const { offset, limit } = lastPage;
33+
return { offset: offset + limit, limit };
34+
},
35+
});

src/api/common/interceptors.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
import type { AxiosError, InternalAxiosRequestConfig } from 'axios';
22

3+
import { useAuth } from '@/core';
4+
35
import { client } from './client';
46
import { toCamelCase, toSnakeCase } from './utils';
57

68
export default function interceptors() {
9+
const token = useAuth.getState().token;
710
client.interceptors.request.use((config: InternalAxiosRequestConfig) => {
811
if (config.data) {
912
config.data = toSnakeCase(config.data);
1013
}
14+
if (token) {
15+
config.headers.Authorization = `Bearer ${token}`;
16+
}
1117
return config;
1218
});
1319

@@ -16,6 +22,6 @@ export default function interceptors() {
1622
response.data = toCamelCase(response.data);
1723
return response;
1824
},
19-
(error: AxiosError) => Promise.reject(error)
25+
(error: AxiosError) => Promise.reject(error),
2026
);
2127
}

src/api/posts/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,15 @@ export type Post = {
44
title: string;
55
body: string;
66
};
7+
8+
export type Comment = {
9+
id: number;
10+
body: string;
11+
postId: number;
12+
likes: number;
13+
user: {
14+
id: number;
15+
username: string;
16+
fullName: string;
17+
};
18+
};

src/api/posts/use-add-post.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
import type { AxiosError } from 'axios';
2+
import axios from 'axios';
23
import { createMutation } from 'react-query-kit';
34

4-
import { client } from '../common';
5+
import { Env } from '@/core/env';
6+
57
import type { Post } from './types';
68

79
type Variables = { title: string; body: string; userId: number };
810
type Response = Post;
911

1012
export const useAddPost = createMutation<Response, Variables, AxiosError>({
1113
mutationFn: async (variables) =>
12-
client({
13-
url: 'posts/add',
14+
axios({
15+
url: `${Env.API_URL}posts/add`,
1416
method: 'POST',
1517
data: variables,
18+
headers: {
19+
'Content-Type': 'application/json',
20+
},
1621
}).then((response) => response.data),
1722
});

src/api/posts/use-post.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
1+
import { useQuery } from '@tanstack/react-query';
12
import type { AxiosError } from 'axios';
23
import { createQuery } from 'react-query-kit';
34

5+
import { queryFactory } from '@/api/query-factory';
6+
47
import { client } from '../common';
58
import type { Post } from './types';
69

710
type Variables = { id: string };
811
type Response = Post;
912

1013
export const usePost = createQuery<Response, Variables, AxiosError>({
11-
queryKey: ['posts'],
12-
fetcher: (variables) => client
13-
.get(`posts/${variables.id}`)
14-
.then((response) => response.data),
14+
// old queryKey: ['posts', 1],
15+
// ...queryFactory.posts.get(1), // this translates to ['posts', 1]
16+
...queryFactory.posts.detail(1), // this translates to ['posts', 1]
17+
fetcher: (variables) =>
18+
client.get(`posts/${variables.id}`).then((response) => response.data),
1519
});
20+
21+
export const usePostComments = (postId: number) =>
22+
useQuery({
23+
...queryFactory.posts.detail(postId)._ctx.comments,
24+
enabled: !!postId,
25+
});

0 commit comments

Comments
 (0)