shelflife-react-hooks 1.0.18 → 1.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +23 -0
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.esm.js +23 -0
- package/dist/index.esm.js.map +1 -1
- package/package.json +36 -36
- package/src/context/AuthContext.tsx +161 -161
- package/src/context/InviteContext.tsx +74 -74
- package/src/context/ProductContext.tsx +131 -121
- package/src/context/RunningLowContext.tsx +100 -100
- package/src/context/ShoppingListContext.tsx +76 -76
- package/src/context/StorageContext.tsx +105 -105
- package/src/context/StorageItemContext.tsx +157 -157
- package/src/context/StorageMemberContext.tsx +84 -84
- package/src/context/UserContext.tsx +109 -109
- package/src/context/__tests__/contexts.test.tsx +370 -370
- package/src/context/api/authApi.ts +155 -155
- package/src/context/api/inviteApi.ts +65 -65
- package/src/context/api/productApi.ts +223 -201
- package/src/context/api/requestState.ts +24 -24
- package/src/context/api/runningLowApi.ts +141 -141
- package/src/context/api/shoppingListApi.ts +161 -159
- package/src/context/api/storageApi.ts +166 -166
- package/src/context/api/storageItemApi.ts +260 -260
- package/src/context/api/storageMemberApi.ts +84 -84
- package/src/context/api/userApi.ts +161 -161
- package/src/context/http.ts +22 -22
- package/src/index.ts +21 -21
- package/src/type/PaginatedResponse.ts +8 -8
- package/src/type/auth.ts +79 -79
- package/src/type/base.ts +21 -21
- package/src/type/item.ts +12 -12
- package/src/type/member.ts +6 -6
- package/src/type/models.ts +56 -56
- package/src/type/product.ts +11 -11
- package/src/type/requests.ts +60 -60
- package/src/type/runninglow.ts +13 -13
- package/src/type/shoppingList.ts +13 -13
- package/src/type/storage.ts +7 -7
- package/src/type/user.ts +11 -11
- package/tsconfig.json +46 -46
- package/tsup.config.ts +10 -10
- package/vitest.config.ts +8 -8
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
import type { InviteMemberError } from '../../type/member.js';
|
|
2
|
-
import type { StorageMember } from '../../type/models.js';
|
|
3
|
-
import type { InviteMemberRequest } from '../../type/requests.js';
|
|
4
|
-
import { buildAuthHeaders, normalizeBaseUrl, readJson } from '../http.js';
|
|
5
|
-
import { runWithRequestState, type RequestStateHandlers } from './requestState.js';
|
|
6
|
-
|
|
7
|
-
type StorageMemberApiConfig = RequestStateHandlers & {
|
|
8
|
-
baseUrl: string;
|
|
9
|
-
token: string | null;
|
|
10
|
-
setMembers: (value: StorageMember[] | ((items: StorageMember[]) => StorageMember[])) => void;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const fetchMembersRequest = async (
|
|
14
|
-
config: StorageMemberApiConfig,
|
|
15
|
-
storageId: number
|
|
16
|
-
): Promise<StorageMember[]> => runWithRequestState(config, async () => {
|
|
17
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
18
|
-
const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/members`, {
|
|
19
|
-
headers: buildAuthHeaders(config.token)
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
if (!response.ok) {
|
|
23
|
-
throw new Error('Failed to fetch storage members');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const payload = await readJson<StorageMember[]>(response);
|
|
27
|
-
if (payload) {
|
|
28
|
-
config.setMembers(payload);
|
|
29
|
-
return payload;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return [];
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
export const inviteMemberRequest = async (
|
|
36
|
-
config: StorageMemberApiConfig,
|
|
37
|
-
storageId: number,
|
|
38
|
-
dto: InviteMemberRequest
|
|
39
|
-
): Promise<StorageMember> => runWithRequestState(config, async () => {
|
|
40
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
41
|
-
const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/members`, {
|
|
42
|
-
method: 'POST',
|
|
43
|
-
headers: {
|
|
44
|
-
...buildAuthHeaders(config.token),
|
|
45
|
-
'Content-Type': 'application/json'
|
|
46
|
-
},
|
|
47
|
-
body: JSON.stringify(dto)
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
if (!response.ok) {
|
|
51
|
-
const err = await readJson<InviteMemberError>(response);
|
|
52
|
-
|
|
53
|
-
if(err?.email)
|
|
54
|
-
throw err;
|
|
55
|
-
|
|
56
|
-
throw new Error('Failed to invite member');
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const payload = await readJson<StorageMember>(response);
|
|
60
|
-
if (!payload) {
|
|
61
|
-
throw new Error('Invite member response missing data');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
config.setMembers((previous) => [payload, ...previous]);
|
|
65
|
-
return payload;
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
export const removeMemberRequest = async (
|
|
69
|
-
config: StorageMemberApiConfig,
|
|
70
|
-
storageId: number,
|
|
71
|
-
userId: number
|
|
72
|
-
): Promise<void> => runWithRequestState(config, async () => {
|
|
73
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
74
|
-
const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/members/${userId}`, {
|
|
75
|
-
method: 'DELETE',
|
|
76
|
-
headers: buildAuthHeaders(config.token)
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
if (!response.ok) {
|
|
80
|
-
throw new Error('Failed to remove member');
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
config.setMembers((previous) => previous.filter((member) => member.user.id !== userId));
|
|
84
|
-
});
|
|
1
|
+
import type { InviteMemberError } from '../../type/member.js';
|
|
2
|
+
import type { StorageMember } from '../../type/models.js';
|
|
3
|
+
import type { InviteMemberRequest } from '../../type/requests.js';
|
|
4
|
+
import { buildAuthHeaders, normalizeBaseUrl, readJson } from '../http.js';
|
|
5
|
+
import { runWithRequestState, type RequestStateHandlers } from './requestState.js';
|
|
6
|
+
|
|
7
|
+
type StorageMemberApiConfig = RequestStateHandlers & {
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
token: string | null;
|
|
10
|
+
setMembers: (value: StorageMember[] | ((items: StorageMember[]) => StorageMember[])) => void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const fetchMembersRequest = async (
|
|
14
|
+
config: StorageMemberApiConfig,
|
|
15
|
+
storageId: number
|
|
16
|
+
): Promise<StorageMember[]> => runWithRequestState(config, async () => {
|
|
17
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
18
|
+
const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/members`, {
|
|
19
|
+
headers: buildAuthHeaders(config.token)
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
throw new Error('Failed to fetch storage members');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const payload = await readJson<StorageMember[]>(response);
|
|
27
|
+
if (payload) {
|
|
28
|
+
config.setMembers(payload);
|
|
29
|
+
return payload;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return [];
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export const inviteMemberRequest = async (
|
|
36
|
+
config: StorageMemberApiConfig,
|
|
37
|
+
storageId: number,
|
|
38
|
+
dto: InviteMemberRequest
|
|
39
|
+
): Promise<StorageMember> => runWithRequestState(config, async () => {
|
|
40
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
41
|
+
const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/members`, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: {
|
|
44
|
+
...buildAuthHeaders(config.token),
|
|
45
|
+
'Content-Type': 'application/json'
|
|
46
|
+
},
|
|
47
|
+
body: JSON.stringify(dto)
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
if (!response.ok) {
|
|
51
|
+
const err = await readJson<InviteMemberError>(response);
|
|
52
|
+
|
|
53
|
+
if(err?.email)
|
|
54
|
+
throw err;
|
|
55
|
+
|
|
56
|
+
throw new Error('Failed to invite member');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const payload = await readJson<StorageMember>(response);
|
|
60
|
+
if (!payload) {
|
|
61
|
+
throw new Error('Invite member response missing data');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
config.setMembers((previous) => [payload, ...previous]);
|
|
65
|
+
return payload;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export const removeMemberRequest = async (
|
|
69
|
+
config: StorageMemberApiConfig,
|
|
70
|
+
storageId: number,
|
|
71
|
+
userId: number
|
|
72
|
+
): Promise<void> => runWithRequestState(config, async () => {
|
|
73
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
74
|
+
const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/members/${userId}`, {
|
|
75
|
+
method: 'DELETE',
|
|
76
|
+
headers: buildAuthHeaders(config.token)
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
throw new Error('Failed to remove member');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
config.setMembers((previous) => previous.filter((member) => member.user.id !== userId));
|
|
84
|
+
});
|
|
@@ -1,161 +1,161 @@
|
|
|
1
|
-
import type { User } from '../../type/models.js';
|
|
2
|
-
import type { ChangeUserDataRequest } from '../../type/requests.js';
|
|
3
|
-
import type { UpdateUserError } from '../../type/user.js';
|
|
4
|
-
import { buildAuthHeaders, normalizeBaseUrl, readJson } from '../http.js';
|
|
5
|
-
import { runWithRequestState, type RequestStateHandlers } from './requestState.js';
|
|
6
|
-
|
|
7
|
-
type UserApiConfig = RequestStateHandlers & {
|
|
8
|
-
baseUrl: string;
|
|
9
|
-
token: string | null;
|
|
10
|
-
setUsers: (value: User[] | ((items: User[]) => User[])) => void;
|
|
11
|
-
setUser: (value: User | null | ((prev: User | null) => User | null)) => void;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const updateById = (items: User[], updated: User): User[] => {
|
|
15
|
-
const index = items.findIndex((item) => item.id === updated.id);
|
|
16
|
-
if (index === -1) {
|
|
17
|
-
return [updated, ...items];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const next = [...items];
|
|
21
|
-
next[index] = updated;
|
|
22
|
-
return next;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export const fetchUsersRequest = async (config: UserApiConfig): Promise<User[]> => runWithRequestState(
|
|
26
|
-
config,
|
|
27
|
-
async () => {
|
|
28
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
29
|
-
const response = await fetch(`${normalizedBaseUrl}/api/users`, {
|
|
30
|
-
headers: buildAuthHeaders(config.token)
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
if (!response.ok) {
|
|
34
|
-
throw new Error('Failed to fetch users');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const payload = await readJson<User[]>(response);
|
|
38
|
-
if (payload) {
|
|
39
|
-
config.setUsers(payload);
|
|
40
|
-
return payload;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return [];
|
|
44
|
-
}
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
export const fetchUserRequest = async (
|
|
48
|
-
config: UserApiConfig,
|
|
49
|
-
id: number
|
|
50
|
-
): Promise<User | null> => runWithRequestState(config, async () => {
|
|
51
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
52
|
-
const response = await fetch(`${normalizedBaseUrl}/api/users/${id}`, {
|
|
53
|
-
headers: buildAuthHeaders(config.token)
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
if (response.status === 404) {
|
|
57
|
-
config.setUser(null);
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (!response.ok) {
|
|
62
|
-
throw new Error('Failed to fetch user');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const payload = await readJson<User>(response);
|
|
66
|
-
if (!payload) {
|
|
67
|
-
throw new Error('User response missing data');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
config.setUser(payload);
|
|
71
|
-
config.setUsers((previous) => updateById(previous, payload));
|
|
72
|
-
return payload;
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
export const updateUserRequest = async (
|
|
76
|
-
config: UserApiConfig,
|
|
77
|
-
id: number,
|
|
78
|
-
dto: ChangeUserDataRequest
|
|
79
|
-
): Promise<User> => runWithRequestState(config, async () => {
|
|
80
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
81
|
-
const response = await fetch(`${normalizedBaseUrl}/api/users/${id}`, {
|
|
82
|
-
method: 'PATCH',
|
|
83
|
-
headers: {
|
|
84
|
-
...buildAuthHeaders(config.token),
|
|
85
|
-
'Content-Type': 'application/json'
|
|
86
|
-
},
|
|
87
|
-
body: JSON.stringify(dto)
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
if (!response.ok) {
|
|
91
|
-
const update = await readJson<UpdateUserError>(response);
|
|
92
|
-
|
|
93
|
-
if (update?.email || update?.username)
|
|
94
|
-
throw update;
|
|
95
|
-
|
|
96
|
-
throw new Error('Failed to update user');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const payload = await readJson<User>(response);
|
|
100
|
-
if (!payload) {
|
|
101
|
-
throw new Error('Update user response missing data');
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
config.setUsers((previous) => updateById(previous, payload));
|
|
105
|
-
config.setUser(payload);
|
|
106
|
-
return payload;
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
export const deleteUserRequest = async (
|
|
110
|
-
config: UserApiConfig,
|
|
111
|
-
id: number
|
|
112
|
-
): Promise<void> => runWithRequestState(config, async () => {
|
|
113
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
114
|
-
const response = await fetch(`${normalizedBaseUrl}/api/users/${id}`, {
|
|
115
|
-
method: 'DELETE',
|
|
116
|
-
headers: buildAuthHeaders(config.token)
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
if (!response.ok) {
|
|
120
|
-
throw new Error('Failed to delete user');
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
config.setUsers((previous) => previous.filter((item) => item.id !== id));
|
|
124
|
-
config.setUser((current) => (current?.id === id ? null : current));
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
export const getUserPfpRequest = async (
|
|
128
|
-
config: UserApiConfig,
|
|
129
|
-
id: number
|
|
130
|
-
): Promise<Blob> => runWithRequestState(config, async () => {
|
|
131
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
132
|
-
const response = await fetch(`${normalizedBaseUrl}/api/users/${id}/pfp`, {
|
|
133
|
-
headers: buildAuthHeaders(config.token)
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
if (!response.ok) {
|
|
137
|
-
throw new Error('Failed to fetch user pfp');
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return response.blob();
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
export const uploadUserPfpRequest = async (
|
|
144
|
-
config: UserApiConfig,
|
|
145
|
-
id: number,
|
|
146
|
-
file: Blob
|
|
147
|
-
): Promise<void> => runWithRequestState(config, async () => {
|
|
148
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
149
|
-
const formData = new FormData();
|
|
150
|
-
formData.append('pfp', file);
|
|
151
|
-
|
|
152
|
-
const response = await fetch(`${normalizedBaseUrl}/api/users/${id}/pfp`, {
|
|
153
|
-
method: 'POST',
|
|
154
|
-
headers: buildAuthHeaders(config.token),
|
|
155
|
-
body: formData
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
if (!response.ok) {
|
|
159
|
-
throw new Error('Failed to upload user pfp');
|
|
160
|
-
}
|
|
161
|
-
});
|
|
1
|
+
import type { User } from '../../type/models.js';
|
|
2
|
+
import type { ChangeUserDataRequest } from '../../type/requests.js';
|
|
3
|
+
import type { UpdateUserError } from '../../type/user.js';
|
|
4
|
+
import { buildAuthHeaders, normalizeBaseUrl, readJson } from '../http.js';
|
|
5
|
+
import { runWithRequestState, type RequestStateHandlers } from './requestState.js';
|
|
6
|
+
|
|
7
|
+
type UserApiConfig = RequestStateHandlers & {
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
token: string | null;
|
|
10
|
+
setUsers: (value: User[] | ((items: User[]) => User[])) => void;
|
|
11
|
+
setUser: (value: User | null | ((prev: User | null) => User | null)) => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const updateById = (items: User[], updated: User): User[] => {
|
|
15
|
+
const index = items.findIndex((item) => item.id === updated.id);
|
|
16
|
+
if (index === -1) {
|
|
17
|
+
return [updated, ...items];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const next = [...items];
|
|
21
|
+
next[index] = updated;
|
|
22
|
+
return next;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const fetchUsersRequest = async (config: UserApiConfig): Promise<User[]> => runWithRequestState(
|
|
26
|
+
config,
|
|
27
|
+
async () => {
|
|
28
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
29
|
+
const response = await fetch(`${normalizedBaseUrl}/api/users`, {
|
|
30
|
+
headers: buildAuthHeaders(config.token)
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
throw new Error('Failed to fetch users');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const payload = await readJson<User[]>(response);
|
|
38
|
+
if (payload) {
|
|
39
|
+
config.setUsers(payload);
|
|
40
|
+
return payload;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
export const fetchUserRequest = async (
|
|
48
|
+
config: UserApiConfig,
|
|
49
|
+
id: number
|
|
50
|
+
): Promise<User | null> => runWithRequestState(config, async () => {
|
|
51
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
52
|
+
const response = await fetch(`${normalizedBaseUrl}/api/users/${id}`, {
|
|
53
|
+
headers: buildAuthHeaders(config.token)
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (response.status === 404) {
|
|
57
|
+
config.setUser(null);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
throw new Error('Failed to fetch user');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const payload = await readJson<User>(response);
|
|
66
|
+
if (!payload) {
|
|
67
|
+
throw new Error('User response missing data');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
config.setUser(payload);
|
|
71
|
+
config.setUsers((previous) => updateById(previous, payload));
|
|
72
|
+
return payload;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
export const updateUserRequest = async (
|
|
76
|
+
config: UserApiConfig,
|
|
77
|
+
id: number,
|
|
78
|
+
dto: ChangeUserDataRequest
|
|
79
|
+
): Promise<User> => runWithRequestState(config, async () => {
|
|
80
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
81
|
+
const response = await fetch(`${normalizedBaseUrl}/api/users/${id}`, {
|
|
82
|
+
method: 'PATCH',
|
|
83
|
+
headers: {
|
|
84
|
+
...buildAuthHeaders(config.token),
|
|
85
|
+
'Content-Type': 'application/json'
|
|
86
|
+
},
|
|
87
|
+
body: JSON.stringify(dto)
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (!response.ok) {
|
|
91
|
+
const update = await readJson<UpdateUserError>(response);
|
|
92
|
+
|
|
93
|
+
if (update?.email || update?.username)
|
|
94
|
+
throw update;
|
|
95
|
+
|
|
96
|
+
throw new Error('Failed to update user');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const payload = await readJson<User>(response);
|
|
100
|
+
if (!payload) {
|
|
101
|
+
throw new Error('Update user response missing data');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
config.setUsers((previous) => updateById(previous, payload));
|
|
105
|
+
config.setUser(payload);
|
|
106
|
+
return payload;
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
export const deleteUserRequest = async (
|
|
110
|
+
config: UserApiConfig,
|
|
111
|
+
id: number
|
|
112
|
+
): Promise<void> => runWithRequestState(config, async () => {
|
|
113
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
114
|
+
const response = await fetch(`${normalizedBaseUrl}/api/users/${id}`, {
|
|
115
|
+
method: 'DELETE',
|
|
116
|
+
headers: buildAuthHeaders(config.token)
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
throw new Error('Failed to delete user');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
config.setUsers((previous) => previous.filter((item) => item.id !== id));
|
|
124
|
+
config.setUser((current) => (current?.id === id ? null : current));
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
export const getUserPfpRequest = async (
|
|
128
|
+
config: UserApiConfig,
|
|
129
|
+
id: number
|
|
130
|
+
): Promise<Blob> => runWithRequestState(config, async () => {
|
|
131
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
132
|
+
const response = await fetch(`${normalizedBaseUrl}/api/users/${id}/pfp`, {
|
|
133
|
+
headers: buildAuthHeaders(config.token)
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
if (!response.ok) {
|
|
137
|
+
throw new Error('Failed to fetch user pfp');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return response.blob();
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
export const uploadUserPfpRequest = async (
|
|
144
|
+
config: UserApiConfig,
|
|
145
|
+
id: number,
|
|
146
|
+
file: Blob
|
|
147
|
+
): Promise<void> => runWithRequestState(config, async () => {
|
|
148
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
149
|
+
const formData = new FormData();
|
|
150
|
+
formData.append('pfp', file);
|
|
151
|
+
|
|
152
|
+
const response = await fetch(`${normalizedBaseUrl}/api/users/${id}/pfp`, {
|
|
153
|
+
method: 'POST',
|
|
154
|
+
headers: buildAuthHeaders(config.token),
|
|
155
|
+
body: formData
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
if (!response.ok) {
|
|
159
|
+
throw new Error('Failed to upload user pfp');
|
|
160
|
+
}
|
|
161
|
+
});
|
package/src/context/http.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
export const normalizeBaseUrl = (baseUrl: string): string => baseUrl.replace(/\/+$/, '');
|
|
2
|
-
|
|
3
|
-
export const buildAuthHeaders = (token: string | null): HeadersInit => {
|
|
4
|
-
if (!token) {
|
|
5
|
-
return {};
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return {
|
|
9
|
-
Authorization: `Bearer ${token}`
|
|
10
|
-
};
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const readJson = async <T,>(response: Response): Promise<T | null> => {
|
|
14
|
-
const contentType = response.headers.get('content-type');
|
|
15
|
-
if (!contentType || !contentType.includes('application/json')) {
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return (await response.json()) as T;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export const readArrayBuffer = async (response: Response): Promise<ArrayBuffer> => response.arrayBuffer();
|
|
1
|
+
export const normalizeBaseUrl = (baseUrl: string): string => baseUrl.replace(/\/+$/, '');
|
|
2
|
+
|
|
3
|
+
export const buildAuthHeaders = (token: string | null): HeadersInit => {
|
|
4
|
+
if (!token) {
|
|
5
|
+
return {};
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
Authorization: `Bearer ${token}`
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const readJson = async <T,>(response: Response): Promise<T | null> => {
|
|
14
|
+
const contentType = response.headers.get('content-type');
|
|
15
|
+
if (!contentType || !contentType.includes('application/json')) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return (await response.json()) as T;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const readArrayBuffer = async (response: Response): Promise<ArrayBuffer> => response.arrayBuffer();
|
package/src/index.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
export * from './type/auth.js';
|
|
2
|
-
export * from './type/base.js';
|
|
3
|
-
export * from './type/item.js';
|
|
4
|
-
export * from './type/member.js';
|
|
5
|
-
export * from './type/models.js';
|
|
6
|
-
export * from './type/PaginatedResponse.js';
|
|
7
|
-
export * from './type/product.js';
|
|
8
|
-
export * from './type/requests.js';
|
|
9
|
-
export * from './type/runninglow.js';
|
|
10
|
-
export * from './type/shoppingList.js';
|
|
11
|
-
export * from './type/storage.js';
|
|
12
|
-
export * from './type/user.js';
|
|
13
|
-
export * from './context/AuthContext.js';
|
|
14
|
-
export * from './context/http.js';
|
|
15
|
-
export * from './context/InviteContext.js';
|
|
16
|
-
export * from './context/ProductContext.js';
|
|
17
|
-
export * from './context/RunningLowContext.js';
|
|
18
|
-
export * from './context/StorageContext.js';
|
|
19
|
-
export * from './context/StorageItemContext.js';
|
|
20
|
-
export * from './context/StorageMemberContext.js';
|
|
21
|
-
export * from './context/UserContext.js';
|
|
1
|
+
export * from './type/auth.js';
|
|
2
|
+
export * from './type/base.js';
|
|
3
|
+
export * from './type/item.js';
|
|
4
|
+
export * from './type/member.js';
|
|
5
|
+
export * from './type/models.js';
|
|
6
|
+
export * from './type/PaginatedResponse.js';
|
|
7
|
+
export * from './type/product.js';
|
|
8
|
+
export * from './type/requests.js';
|
|
9
|
+
export * from './type/runninglow.js';
|
|
10
|
+
export * from './type/shoppingList.js';
|
|
11
|
+
export * from './type/storage.js';
|
|
12
|
+
export * from './type/user.js';
|
|
13
|
+
export * from './context/AuthContext.js';
|
|
14
|
+
export * from './context/http.js';
|
|
15
|
+
export * from './context/InviteContext.js';
|
|
16
|
+
export * from './context/ProductContext.js';
|
|
17
|
+
export * from './context/RunningLowContext.js';
|
|
18
|
+
export * from './context/StorageContext.js';
|
|
19
|
+
export * from './context/StorageItemContext.js';
|
|
20
|
+
export * from './context/StorageMemberContext.js';
|
|
21
|
+
export * from './context/UserContext.js';
|
|
22
22
|
export * from './context/ShoppingListContext.js';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export type PaginatedResponse<T> = {
|
|
2
|
-
data: T[];
|
|
3
|
-
currentPage: number;
|
|
4
|
-
totalPages: number;
|
|
5
|
-
totalItems: number;
|
|
6
|
-
pageSize: number;
|
|
7
|
-
hasNext: boolean;
|
|
8
|
-
hasPrevious: boolean;
|
|
1
|
+
export type PaginatedResponse<T> = {
|
|
2
|
+
data: T[];
|
|
3
|
+
currentPage: number;
|
|
4
|
+
totalPages: number;
|
|
5
|
+
totalItems: number;
|
|
6
|
+
pageSize: number;
|
|
7
|
+
hasNext: boolean;
|
|
8
|
+
hasPrevious: boolean;
|
|
9
9
|
}
|