Skip to content

Commit eb28cb9

Browse files
Merge pull request #85 from rootstrap/feat/query-factory
feat(network): add query factory library
2 parents eb3b710 + 63a686a commit eb28cb9

23 files changed

+412
-63
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
"@expo/metro-runtime": "^3.2.3",
6767
"@gorhom/bottom-sheet": "4.6.3",
6868
"@hookform/resolvers": "^3.9.0",
69+
"@lukemorales/query-key-factory": "^1.3.4",
6970
"@shopify/flash-list": "1.6.4",
7071
"@tanstack/react-query": "^5.52.1",
7172
"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: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { createMutation } from 'react-query-kit';
2+
3+
import { client } from '../common';
4+
5+
type Variables = {
6+
email?: string; // optional because API doesn't require email
7+
username: string;
8+
password: string;
9+
expiresInMins?: number;
10+
};
11+
12+
type Response = {
13+
id: number;
14+
username: string;
15+
email: string;
16+
accessToken: string;
17+
refreshToken: string;
18+
};
19+
20+
const login = async (variables: Variables) => {
21+
const { data } = await client({
22+
url: 'auth/login',
23+
method: 'POST',
24+
data: {
25+
username: variables.username,
26+
password: variables.password,
27+
},
28+
headers: {
29+
'Content-Type': 'application/json',
30+
},
31+
});
32+
return data;
33+
};
34+
35+
export const useLogin = createMutation<Response, Variables>({
36+
mutationFn: (variables) => login(variables),
37+
});

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) => [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: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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 { data } = await client.get('carts', {
19+
params: {
20+
limit,
21+
offset,
22+
},
23+
});
24+
return { data, offset: Number(offset), limit: Number(limit) };
25+
};
26+
27+
export const useCarts = (variables: Variables) =>
28+
useInfiniteQuery({
29+
...cartKeys.list(variables),
30+
queryFn: () => getCarts(variables),
31+
initialPageParam: { offset: DEFAULT_OFFSET, limit: DEFAULT_LIMIT },
32+
getNextPageParam: (lastPage) => {
33+
const { offset, limit } = lastPage;
34+
return { offset: offset + limit, limit };
35+
},
36+
});

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/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from './types';
22
export * from './use-add-post';
33
export * from './use-post';
4+
export * from './use-post-comments';
45
export * from './use-posts';

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: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,8 @@ export const useAddPost = createMutation<Response, Variables, AxiosError>({
1313
url: 'posts/add',
1414
method: 'POST',
1515
data: variables,
16+
headers: {
17+
'Content-Type': 'application/json',
18+
},
1619
}).then((response) => response.data),
1720
});

0 commit comments

Comments
 (0)