shelflife-react-hooks 1.0.0

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.
Files changed (38) hide show
  1. package/dist/index.cjs.js +1374 -0
  2. package/dist/index.cjs.js.map +1 -0
  3. package/dist/index.d.cts +339 -0
  4. package/dist/index.d.ts +339 -0
  5. package/dist/index.esm.js +1376 -0
  6. package/dist/index.esm.js.map +1 -0
  7. package/package.json +33 -0
  8. package/src/context/AuthContext.tsx +109 -0
  9. package/src/context/InviteContext.tsx +74 -0
  10. package/src/context/ProductContext.tsx +126 -0
  11. package/src/context/RunningLowContext.tsx +100 -0
  12. package/src/context/StorageContext.tsx +104 -0
  13. package/src/context/StorageItemContext.tsx +136 -0
  14. package/src/context/StorageMemberContext.tsx +84 -0
  15. package/src/context/UserContext.tsx +109 -0
  16. package/src/context/__tests__/contexts.test.tsx +354 -0
  17. package/src/context/api/authApi.ts +141 -0
  18. package/src/context/api/inviteApi.ts +65 -0
  19. package/src/context/api/productApi.ts +204 -0
  20. package/src/context/api/requestState.ts +25 -0
  21. package/src/context/api/runningLowApi.ts +130 -0
  22. package/src/context/api/storageApi.ts +147 -0
  23. package/src/context/api/storageItemApi.ts +187 -0
  24. package/src/context/api/storageMemberApi.ts +78 -0
  25. package/src/context/api/userApi.ts +155 -0
  26. package/src/context/http.ts +22 -0
  27. package/src/index.ts +17 -0
  28. package/src/type/auth.ts +62 -0
  29. package/src/type/base.ts +22 -0
  30. package/src/type/models.ts +48 -0
  31. package/src/type/product.ts +29 -0
  32. package/src/type/requests.ts +49 -0
  33. package/src/type/runninglow.ts +23 -0
  34. package/src/type/storage.ts +70 -0
  35. package/src/type/user.ts +23 -0
  36. package/tsconfig.json +46 -0
  37. package/tsup.config.ts +11 -0
  38. package/vitest.config.ts +8 -0
@@ -0,0 +1,1374 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AuthProvider: () => AuthProvider,
24
+ InviteProvider: () => InviteProvider,
25
+ ProductProvider: () => ProductProvider,
26
+ RunningLowProvider: () => RunningLowProvider,
27
+ StorageItemProvider: () => StorageItemProvider,
28
+ StorageMemberProvider: () => StorageMemberProvider,
29
+ StorageProvider: () => StorageProvider,
30
+ UserProvider: () => UserProvider,
31
+ buildAuthHeaders: () => buildAuthHeaders,
32
+ normalizeBaseUrl: () => normalizeBaseUrl,
33
+ readArrayBuffer: () => readArrayBuffer,
34
+ readJson: () => readJson,
35
+ useAuth: () => useAuth,
36
+ useInvites: () => useInvites,
37
+ useProducts: () => useProducts,
38
+ useRunningLow: () => useRunningLow,
39
+ useStorageItems: () => useStorageItems,
40
+ useStorageMembers: () => useStorageMembers,
41
+ useStorages: () => useStorages,
42
+ useUsers: () => useUsers
43
+ });
44
+ module.exports = __toCommonJS(index_exports);
45
+
46
+ // src/context/AuthContext.tsx
47
+ var import_react = require("react");
48
+
49
+ // src/context/http.ts
50
+ var normalizeBaseUrl = (baseUrl) => baseUrl.replace(/\/+$/, "");
51
+ var buildAuthHeaders = (token) => {
52
+ if (!token) {
53
+ return {};
54
+ }
55
+ return {
56
+ Authorization: `Bearer ${token}`
57
+ };
58
+ };
59
+ var readJson = async (response) => {
60
+ const contentType = response.headers.get("content-type");
61
+ if (!contentType || !contentType.includes("application/json")) {
62
+ return null;
63
+ }
64
+ return await response.json();
65
+ };
66
+ var readArrayBuffer = async (response) => response.arrayBuffer();
67
+
68
+ // src/context/api/requestState.ts
69
+ var runWithRequestState = async (handlers, request) => {
70
+ handlers.setIsLoading(true);
71
+ handlers.setIsError(false);
72
+ handlers.setError(null);
73
+ try {
74
+ return await request();
75
+ } catch (err) {
76
+ const error = err instanceof Error ? err : new Error("Unknown error");
77
+ handlers.setIsError(true);
78
+ handlers.setError(error);
79
+ throw error;
80
+ } finally {
81
+ handlers.setIsLoading(false);
82
+ }
83
+ };
84
+
85
+ // src/context/api/authApi.ts
86
+ var loginRequest = async (config, dto) => runWithRequestState(config, async () => {
87
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
88
+ const response = await fetch(`${normalizedBaseUrl}/api/auth/login`, {
89
+ method: "POST",
90
+ headers: {
91
+ "Content-Type": "application/json"
92
+ },
93
+ body: JSON.stringify(dto)
94
+ });
95
+ if (!response.ok) {
96
+ const error = await readJson(response);
97
+ throw new Error(error?.error ?? "Login failed");
98
+ }
99
+ const payload = await readJson(response);
100
+ if (!payload || !("token" in payload)) {
101
+ throw new Error("Login response missing token");
102
+ }
103
+ config.setToken(payload.token);
104
+ const meResponse = await fetch(`${normalizedBaseUrl}/api/auth/me`, {
105
+ headers: buildAuthHeaders(payload.token)
106
+ });
107
+ if (meResponse.ok) {
108
+ const mePayload = await readJson(meResponse);
109
+ if (mePayload) {
110
+ config.setUser(mePayload);
111
+ }
112
+ }
113
+ });
114
+ var signupRequest = async (config, dto) => runWithRequestState(config, async () => {
115
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
116
+ const response = await fetch(`${normalizedBaseUrl}/api/auth/signup`, {
117
+ method: "POST",
118
+ headers: {
119
+ "Content-Type": "application/json"
120
+ },
121
+ body: JSON.stringify(dto)
122
+ });
123
+ if (!response.ok) {
124
+ const error = await readJson(response);
125
+ throw new Error(error?.error ?? "Signup failed");
126
+ }
127
+ const payload = await readJson(response);
128
+ if (!payload) {
129
+ throw new Error("Signup response missing user");
130
+ }
131
+ config.setUser(payload);
132
+ return payload;
133
+ });
134
+ var changePasswordRequest = async (config, dto) => runWithRequestState(config, async () => {
135
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
136
+ const response = await fetch(`${normalizedBaseUrl}/api/auth/password/change`, {
137
+ method: "POST",
138
+ headers: {
139
+ ...buildAuthHeaders(config.token),
140
+ "Content-Type": "application/json"
141
+ },
142
+ body: JSON.stringify(dto)
143
+ });
144
+ if (!response.ok) {
145
+ const error = await readJson(response);
146
+ throw new Error(error?.error ?? "Change password failed");
147
+ }
148
+ });
149
+ var getMeRequest = async (config) => runWithRequestState(
150
+ config,
151
+ async () => {
152
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
153
+ const response = await fetch(`${normalizedBaseUrl}/api/auth/me`, {
154
+ headers: buildAuthHeaders(config.token)
155
+ });
156
+ if (!response.ok) {
157
+ config.setUser(null);
158
+ return null;
159
+ }
160
+ const payload = await readJson(response);
161
+ if (!payload) {
162
+ config.setUser(null);
163
+ return null;
164
+ }
165
+ config.setUser(payload);
166
+ return payload;
167
+ }
168
+ );
169
+ var logoutRequest = async (config) => runWithRequestState(
170
+ config,
171
+ async () => {
172
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
173
+ if (config.token) {
174
+ await fetch(`${normalizedBaseUrl}/api/auth/logout`, {
175
+ method: "POST",
176
+ headers: buildAuthHeaders(config.token)
177
+ });
178
+ }
179
+ config.setToken(null);
180
+ config.setUser(null);
181
+ }
182
+ );
183
+
184
+ // src/context/AuthContext.tsx
185
+ var import_jsx_runtime = require("react/jsx-runtime");
186
+ var AuthContext = (0, import_react.createContext)(void 0);
187
+ var AuthProvider = ({ baseUrl, children, initialToken = null }) => {
188
+ const [token, setToken] = (0, import_react.useState)(initialToken);
189
+ const [user, setUser] = (0, import_react.useState)(null);
190
+ const [isLoading, setIsLoading] = (0, import_react.useState)(false);
191
+ const [isError, setIsError] = (0, import_react.useState)(false);
192
+ const [error, setError] = (0, import_react.useState)(null);
193
+ const getToken = (0, import_react.useCallback)(() => token, [token]);
194
+ const apiConfig = (0, import_react.useMemo)(() => ({
195
+ baseUrl,
196
+ token,
197
+ setToken,
198
+ setUser,
199
+ setIsLoading,
200
+ setIsError,
201
+ setError
202
+ }), [baseUrl, token]);
203
+ const login = (0, import_react.useCallback)((dto) => loginRequest(apiConfig, dto), [apiConfig]);
204
+ const signup = (0, import_react.useCallback)((dto) => signupRequest(apiConfig, dto), [apiConfig]);
205
+ const changePassword = (0, import_react.useCallback)(
206
+ (dto) => changePasswordRequest(apiConfig, dto),
207
+ [apiConfig]
208
+ );
209
+ const getMe = (0, import_react.useCallback)(() => getMeRequest(apiConfig), [apiConfig]);
210
+ const logout = (0, import_react.useCallback)(() => logoutRequest(apiConfig), [apiConfig]);
211
+ const value = (0, import_react.useMemo)(() => ({
212
+ token,
213
+ user,
214
+ isLoading,
215
+ isError,
216
+ error,
217
+ login,
218
+ signup,
219
+ changePassword,
220
+ getMe,
221
+ logout,
222
+ getToken
223
+ }), [
224
+ changePassword,
225
+ error,
226
+ getMe,
227
+ getToken,
228
+ isError,
229
+ isLoading,
230
+ login,
231
+ logout,
232
+ signup,
233
+ token,
234
+ user
235
+ ]);
236
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AuthContext.Provider, { value, children });
237
+ };
238
+ var useAuth = () => {
239
+ const context = (0, import_react.useContext)(AuthContext);
240
+ if (!context) {
241
+ throw new Error("useAuth must be used within an AuthProvider");
242
+ }
243
+ return context;
244
+ };
245
+
246
+ // src/context/InviteContext.tsx
247
+ var import_react2 = require("react");
248
+
249
+ // src/context/api/inviteApi.ts
250
+ var fetchInvitesRequest = async (config) => runWithRequestState(
251
+ config,
252
+ async () => {
253
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
254
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/invites`, {
255
+ headers: buildAuthHeaders(config.token)
256
+ });
257
+ if (!response.ok) {
258
+ throw new Error("Failed to fetch invites");
259
+ }
260
+ const payload = await readJson(response);
261
+ if (payload) {
262
+ config.setInvites(payload);
263
+ return payload;
264
+ }
265
+ return [];
266
+ }
267
+ );
268
+ var acceptInviteRequest = async (config, id) => runWithRequestState(config, async () => {
269
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
270
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/invites/${id}`, {
271
+ method: "POST",
272
+ headers: buildAuthHeaders(config.token)
273
+ });
274
+ if (!response.ok) {
275
+ throw new Error("Failed to accept invite");
276
+ }
277
+ config.setInvites((previous) => previous.filter((invite) => invite.id !== id));
278
+ });
279
+ var declineInviteRequest = async (config, id) => runWithRequestState(config, async () => {
280
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
281
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/invites/${id}`, {
282
+ method: "DELETE",
283
+ headers: buildAuthHeaders(config.token)
284
+ });
285
+ if (!response.ok) {
286
+ throw new Error("Failed to decline invite");
287
+ }
288
+ config.setInvites((previous) => previous.filter((invite) => invite.id !== id));
289
+ });
290
+
291
+ // src/context/InviteContext.tsx
292
+ var import_jsx_runtime2 = require("react/jsx-runtime");
293
+ var InviteContext = (0, import_react2.createContext)(void 0);
294
+ var InviteProvider = ({ baseUrl, children }) => {
295
+ const { token } = useAuth();
296
+ const [invites, setInvites] = (0, import_react2.useState)([]);
297
+ const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
298
+ const [isError, setIsError] = (0, import_react2.useState)(false);
299
+ const [error, setError] = (0, import_react2.useState)(null);
300
+ const apiConfig = (0, import_react2.useMemo)(() => ({
301
+ baseUrl,
302
+ token,
303
+ setInvites,
304
+ setIsLoading,
305
+ setIsError,
306
+ setError
307
+ }), [baseUrl, token]);
308
+ const fetchInvites = (0, import_react2.useCallback)(() => fetchInvitesRequest(apiConfig), [apiConfig]);
309
+ const acceptInvite = (0, import_react2.useCallback)((id) => acceptInviteRequest(apiConfig, id), [apiConfig]);
310
+ const declineInvite = (0, import_react2.useCallback)((id) => declineInviteRequest(apiConfig, id), [apiConfig]);
311
+ const value = (0, import_react2.useMemo)(() => ({
312
+ invites,
313
+ isLoading,
314
+ isError,
315
+ error,
316
+ fetchInvites,
317
+ acceptInvite,
318
+ declineInvite
319
+ }), [acceptInvite, declineInvite, error, fetchInvites, isError, isLoading, invites]);
320
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(InviteContext.Provider, { value, children });
321
+ };
322
+ var useInvites = () => {
323
+ const context = (0, import_react2.useContext)(InviteContext);
324
+ if (!context) {
325
+ throw new Error("useInvites must be used within an InviteProvider");
326
+ }
327
+ return context;
328
+ };
329
+
330
+ // src/context/ProductContext.tsx
331
+ var import_react3 = require("react");
332
+
333
+ // src/context/api/productApi.ts
334
+ var updateById = (items, updated) => {
335
+ const index = items.findIndex((item) => item.id === updated.id);
336
+ if (index === -1) {
337
+ return [updated, ...items];
338
+ }
339
+ const next = [...items];
340
+ next[index] = updated;
341
+ return next;
342
+ };
343
+ var fetchProductsRequest = async (config, query) => runWithRequestState(config, async () => {
344
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
345
+ const params = new URLSearchParams();
346
+ if (query?.barcode) {
347
+ params.set("barcode", query.barcode);
348
+ }
349
+ if (query?.name) {
350
+ params.set("name", query.name);
351
+ }
352
+ if (query?.category) {
353
+ params.set("category", query.category);
354
+ }
355
+ const url = params.toString() ? `${normalizedBaseUrl}/api/products?${params.toString()}` : `${normalizedBaseUrl}/api/products`;
356
+ const response = await fetch(url, {
357
+ headers: buildAuthHeaders(config.token)
358
+ });
359
+ if (!response.ok) {
360
+ throw new Error("Failed to fetch products");
361
+ }
362
+ const payload = await readJson(response);
363
+ if (payload) {
364
+ config.setProducts(payload);
365
+ return payload;
366
+ }
367
+ return [];
368
+ });
369
+ var fetchProductRequest = async (config, id) => runWithRequestState(config, async () => {
370
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
371
+ const response = await fetch(`${normalizedBaseUrl}/api/products/${id}`, {
372
+ headers: buildAuthHeaders(config.token)
373
+ });
374
+ if (response.status === 404) {
375
+ config.setProduct(null);
376
+ return null;
377
+ }
378
+ if (!response.ok) {
379
+ throw new Error("Failed to fetch product");
380
+ }
381
+ const payload = await readJson(response);
382
+ if (!payload) {
383
+ throw new Error("Product response missing data");
384
+ }
385
+ config.setProduct(payload);
386
+ config.setProducts((previous) => updateById(previous, payload));
387
+ return payload;
388
+ });
389
+ var createProductRequest = async (config, dto) => runWithRequestState(config, async () => {
390
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
391
+ const response = await fetch(`${normalizedBaseUrl}/api/products`, {
392
+ method: "POST",
393
+ headers: {
394
+ ...buildAuthHeaders(config.token),
395
+ "Content-Type": "application/json"
396
+ },
397
+ body: JSON.stringify(dto)
398
+ });
399
+ if (!response.ok) {
400
+ throw new Error("Failed to create product");
401
+ }
402
+ const payload = await readJson(response);
403
+ if (!payload) {
404
+ throw new Error("Create product response missing data");
405
+ }
406
+ config.setProducts((previous) => [payload, ...previous]);
407
+ config.setProduct(payload);
408
+ return payload;
409
+ });
410
+ var updateProductRequest = async (config, id, dto) => runWithRequestState(config, async () => {
411
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
412
+ const response = await fetch(`${normalizedBaseUrl}/api/products/${id}`, {
413
+ method: "PATCH",
414
+ headers: {
415
+ ...buildAuthHeaders(config.token),
416
+ "Content-Type": "application/json"
417
+ },
418
+ body: JSON.stringify(dto)
419
+ });
420
+ if (!response.ok) {
421
+ throw new Error("Failed to update product");
422
+ }
423
+ const payload = await readJson(response);
424
+ if (!payload) {
425
+ throw new Error("Update product response missing data");
426
+ }
427
+ config.setProducts((previous) => updateById(previous, payload));
428
+ config.setProduct(payload);
429
+ return payload;
430
+ });
431
+ var deleteProductRequest = async (config, id) => runWithRequestState(config, async () => {
432
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
433
+ const response = await fetch(`${normalizedBaseUrl}/api/products/${id}`, {
434
+ method: "DELETE",
435
+ headers: buildAuthHeaders(config.token)
436
+ });
437
+ if (!response.ok) {
438
+ throw new Error("Failed to delete product");
439
+ }
440
+ config.setProducts((previous) => previous.filter((item) => item.id !== id));
441
+ config.setProduct((current) => current?.id === id ? null : current);
442
+ });
443
+ var getProductIconRequest = async (config, id) => runWithRequestState(config, async () => {
444
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
445
+ const response = await fetch(`${normalizedBaseUrl}/api/products/${id}/icon`, {
446
+ headers: buildAuthHeaders(config.token)
447
+ });
448
+ if (!response.ok) {
449
+ throw new Error("Failed to fetch product icon");
450
+ }
451
+ return readArrayBuffer(response);
452
+ });
453
+ var uploadProductIconRequest = async (config, id, file) => runWithRequestState(config, async () => {
454
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
455
+ const formData = new FormData();
456
+ formData.append("pfp", file);
457
+ const response = await fetch(`${normalizedBaseUrl}/api/products/${id}/icon`, {
458
+ method: "POST",
459
+ headers: buildAuthHeaders(config.token),
460
+ body: formData
461
+ });
462
+ if (!response.ok) {
463
+ throw new Error("Failed to upload product icon");
464
+ }
465
+ });
466
+
467
+ // src/context/ProductContext.tsx
468
+ var import_jsx_runtime3 = require("react/jsx-runtime");
469
+ var ProductContext = (0, import_react3.createContext)(void 0);
470
+ var ProductProvider = ({ baseUrl, children }) => {
471
+ const { token } = useAuth();
472
+ const [products, setProducts] = (0, import_react3.useState)([]);
473
+ const [product, setProduct] = (0, import_react3.useState)(null);
474
+ const [isLoading, setIsLoading] = (0, import_react3.useState)(false);
475
+ const [isError, setIsError] = (0, import_react3.useState)(false);
476
+ const [error, setError] = (0, import_react3.useState)(null);
477
+ const apiConfig = (0, import_react3.useMemo)(() => ({
478
+ baseUrl,
479
+ token,
480
+ setProducts,
481
+ setProduct,
482
+ setIsLoading,
483
+ setIsError,
484
+ setError
485
+ }), [baseUrl, token]);
486
+ const fetchProducts = (0, import_react3.useCallback)(
487
+ (query) => fetchProductsRequest(apiConfig, query),
488
+ [apiConfig]
489
+ );
490
+ const fetchProduct = (0, import_react3.useCallback)((id) => fetchProductRequest(apiConfig, id), [apiConfig]);
491
+ const createProduct = (0, import_react3.useCallback)(
492
+ (dto) => createProductRequest(apiConfig, dto),
493
+ [apiConfig]
494
+ );
495
+ const updateProduct = (0, import_react3.useCallback)(
496
+ (id, dto) => updateProductRequest(apiConfig, id, dto),
497
+ [apiConfig]
498
+ );
499
+ const deleteProduct = (0, import_react3.useCallback)((id) => deleteProductRequest(apiConfig, id), [apiConfig]);
500
+ const getProductIcon = (0, import_react3.useCallback)((id) => getProductIconRequest(apiConfig, id), [apiConfig]);
501
+ const uploadProductIcon = (0, import_react3.useCallback)(
502
+ (id, file) => uploadProductIconRequest(apiConfig, id, file),
503
+ [apiConfig]
504
+ );
505
+ const value = (0, import_react3.useMemo)(() => ({
506
+ products,
507
+ product,
508
+ isLoading,
509
+ isError,
510
+ error,
511
+ fetchProducts,
512
+ fetchProduct,
513
+ createProduct,
514
+ updateProduct,
515
+ deleteProduct,
516
+ getProductIcon,
517
+ uploadProductIcon
518
+ }), [
519
+ createProduct,
520
+ deleteProduct,
521
+ error,
522
+ fetchProduct,
523
+ fetchProducts,
524
+ getProductIcon,
525
+ isError,
526
+ isLoading,
527
+ product,
528
+ products,
529
+ updateProduct,
530
+ uploadProductIcon
531
+ ]);
532
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ProductContext.Provider, { value, children });
533
+ };
534
+ var useProducts = () => {
535
+ const context = (0, import_react3.useContext)(ProductContext);
536
+ if (!context) {
537
+ throw new Error("useProducts must be used within a ProductProvider");
538
+ }
539
+ return context;
540
+ };
541
+
542
+ // src/context/RunningLowContext.tsx
543
+ var import_react4 = require("react");
544
+
545
+ // src/context/api/runningLowApi.ts
546
+ var updateById2 = (items, updated) => {
547
+ const index = items.findIndex((item) => item.id === updated.id);
548
+ if (index === -1) {
549
+ return [updated, ...items];
550
+ }
551
+ const next = [...items];
552
+ next[index] = updated;
553
+ return next;
554
+ };
555
+ var fetchSettingsRequest = async (config, storageId) => runWithRequestState(config, async () => {
556
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
557
+ const response = await fetch(
558
+ `${normalizedBaseUrl}/api/storages/${storageId}/runninglowsettings`,
559
+ {
560
+ headers: buildAuthHeaders(config.token)
561
+ }
562
+ );
563
+ if (!response.ok) {
564
+ throw new Error("Failed to fetch running low settings");
565
+ }
566
+ const payload = await readJson(response);
567
+ if (payload) {
568
+ config.setSettings(payload);
569
+ return payload;
570
+ }
571
+ return [];
572
+ });
573
+ var createSettingRequest = async (config, storageId, dto) => runWithRequestState(config, async () => {
574
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
575
+ const response = await fetch(
576
+ `${normalizedBaseUrl}/api/storages/${storageId}/runninglowsettings`,
577
+ {
578
+ method: "POST",
579
+ headers: {
580
+ ...buildAuthHeaders(config.token),
581
+ "Content-Type": "application/json"
582
+ },
583
+ body: JSON.stringify(dto)
584
+ }
585
+ );
586
+ if (!response.ok) {
587
+ throw new Error("Failed to create running low setting");
588
+ }
589
+ const payload = await readJson(response);
590
+ if (!payload) {
591
+ throw new Error("Create running low response missing data");
592
+ }
593
+ config.setSettings((previous) => [payload, ...previous]);
594
+ return payload;
595
+ });
596
+ var editSettingRequest = async (config, storageId, id, dto) => runWithRequestState(config, async () => {
597
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
598
+ const response = await fetch(
599
+ `${normalizedBaseUrl}/api/storages/${storageId}/runninglowsettings/${id}`,
600
+ {
601
+ method: "PUT",
602
+ headers: {
603
+ ...buildAuthHeaders(config.token),
604
+ "Content-Type": "application/json"
605
+ },
606
+ body: JSON.stringify(dto)
607
+ }
608
+ );
609
+ if (!response.ok) {
610
+ throw new Error("Failed to edit running low setting");
611
+ }
612
+ const payload = await readJson(response);
613
+ if (!payload) {
614
+ throw new Error("Edit running low response missing data");
615
+ }
616
+ config.setSettings((previous) => updateById2(previous, payload));
617
+ return payload;
618
+ });
619
+ var deleteSettingRequest = async (config, storageId, id) => runWithRequestState(config, async () => {
620
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
621
+ const response = await fetch(
622
+ `${normalizedBaseUrl}/api/storages/${storageId}/runninglowsettings/${id}`,
623
+ {
624
+ method: "DELETE",
625
+ headers: buildAuthHeaders(config.token)
626
+ }
627
+ );
628
+ if (!response.ok) {
629
+ throw new Error("Failed to delete running low setting");
630
+ }
631
+ config.setSettings((previous) => previous.filter((item) => item.id !== id));
632
+ });
633
+
634
+ // src/context/RunningLowContext.tsx
635
+ var import_jsx_runtime4 = require("react/jsx-runtime");
636
+ var RunningLowContext = (0, import_react4.createContext)(void 0);
637
+ var RunningLowProvider = ({ baseUrl, children }) => {
638
+ const { token } = useAuth();
639
+ const [settings, setSettings] = (0, import_react4.useState)([]);
640
+ const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
641
+ const [isError, setIsError] = (0, import_react4.useState)(false);
642
+ const [error, setError] = (0, import_react4.useState)(null);
643
+ const apiConfig = (0, import_react4.useMemo)(() => ({
644
+ baseUrl,
645
+ token,
646
+ setSettings,
647
+ setIsLoading,
648
+ setIsError,
649
+ setError
650
+ }), [baseUrl, token]);
651
+ const fetchSettings = (0, import_react4.useCallback)(
652
+ (storageId) => fetchSettingsRequest(apiConfig, storageId),
653
+ [apiConfig]
654
+ );
655
+ const createSetting = (0, import_react4.useCallback)(
656
+ (storageId, dto) => createSettingRequest(apiConfig, storageId, dto),
657
+ [apiConfig]
658
+ );
659
+ const editSetting = (0, import_react4.useCallback)(
660
+ (storageId, id, dto) => editSettingRequest(apiConfig, storageId, id, dto),
661
+ [apiConfig]
662
+ );
663
+ const deleteSetting = (0, import_react4.useCallback)(
664
+ (storageId, id) => deleteSettingRequest(apiConfig, storageId, id),
665
+ [apiConfig]
666
+ );
667
+ const value = (0, import_react4.useMemo)(() => ({
668
+ settings,
669
+ isLoading,
670
+ isError,
671
+ error,
672
+ fetchSettings,
673
+ createSetting,
674
+ editSetting,
675
+ deleteSetting
676
+ }), [
677
+ createSetting,
678
+ deleteSetting,
679
+ editSetting,
680
+ error,
681
+ fetchSettings,
682
+ isError,
683
+ isLoading,
684
+ settings
685
+ ]);
686
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RunningLowContext.Provider, { value, children });
687
+ };
688
+ var useRunningLow = () => {
689
+ const context = (0, import_react4.useContext)(RunningLowContext);
690
+ if (!context) {
691
+ throw new Error("useRunningLow must be used within a RunningLowProvider");
692
+ }
693
+ return context;
694
+ };
695
+
696
+ // src/context/StorageContext.tsx
697
+ var import_react5 = require("react");
698
+
699
+ // src/context/api/storageApi.ts
700
+ var updateById3 = (items, updated) => {
701
+ const index = items.findIndex((item) => item.id === updated.id);
702
+ if (index === -1) {
703
+ return [updated, ...items];
704
+ }
705
+ const next = [...items];
706
+ next[index] = updated;
707
+ return next;
708
+ };
709
+ var fetchStoragesRequest = async (config) => runWithRequestState(
710
+ config,
711
+ async () => {
712
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
713
+ const response = await fetch(`${normalizedBaseUrl}/api/storages`, {
714
+ headers: buildAuthHeaders(config.token)
715
+ });
716
+ if (!response.ok) {
717
+ throw new Error("Failed to fetch storages");
718
+ }
719
+ const payload = await readJson(response);
720
+ if (payload) {
721
+ config.setStorages(payload);
722
+ return payload;
723
+ }
724
+ return [];
725
+ }
726
+ );
727
+ var fetchStorageRequest = async (config, id) => runWithRequestState(config, async () => {
728
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
729
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/${id}`, {
730
+ headers: buildAuthHeaders(config.token)
731
+ });
732
+ if (response.status === 404) {
733
+ config.setStorage(null);
734
+ return null;
735
+ }
736
+ if (!response.ok) {
737
+ throw new Error("Failed to fetch storage");
738
+ }
739
+ const payload = await readJson(response);
740
+ if (!payload) {
741
+ throw new Error("Storage response missing data");
742
+ }
743
+ config.setStorage(payload);
744
+ config.setStorages((previous) => updateById3(previous, payload));
745
+ return payload;
746
+ });
747
+ var createStorageRequest = async (config, dto) => runWithRequestState(config, async () => {
748
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
749
+ const response = await fetch(`${normalizedBaseUrl}/api/storages`, {
750
+ method: "POST",
751
+ headers: {
752
+ ...buildAuthHeaders(config.token),
753
+ "Content-Type": "application/json"
754
+ },
755
+ body: JSON.stringify(dto)
756
+ });
757
+ if (!response.ok) {
758
+ throw new Error("Failed to create storage");
759
+ }
760
+ const payload = await readJson(response);
761
+ if (!payload) {
762
+ throw new Error("Create storage response missing data");
763
+ }
764
+ config.setStorages((previous) => [payload, ...previous]);
765
+ config.setStorage(payload);
766
+ return payload;
767
+ });
768
+ var changeStorageNameRequest = async (config, id, dto) => runWithRequestState(config, async () => {
769
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
770
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/${id}`, {
771
+ method: "PATCH",
772
+ headers: {
773
+ ...buildAuthHeaders(config.token),
774
+ "Content-Type": "application/json"
775
+ },
776
+ body: JSON.stringify(dto)
777
+ });
778
+ if (!response.ok) {
779
+ throw new Error("Failed to update storage");
780
+ }
781
+ const payload = await readJson(response);
782
+ if (!payload) {
783
+ throw new Error("Update storage response missing data");
784
+ }
785
+ config.setStorages((previous) => updateById3(previous, payload));
786
+ config.setStorage(payload);
787
+ return payload;
788
+ });
789
+ var deleteStorageRequest = async (config, id) => runWithRequestState(config, async () => {
790
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
791
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/${id}`, {
792
+ method: "DELETE",
793
+ headers: buildAuthHeaders(config.token)
794
+ });
795
+ if (!response.ok) {
796
+ throw new Error("Failed to delete storage");
797
+ }
798
+ config.setStorages((previous) => previous.filter((item) => item.id !== id));
799
+ config.setStorage((current) => current?.id === id ? null : current);
800
+ });
801
+
802
+ // src/context/StorageContext.tsx
803
+ var import_jsx_runtime5 = require("react/jsx-runtime");
804
+ var StorageContext = (0, import_react5.createContext)(void 0);
805
+ var StorageProvider = ({ baseUrl, children }) => {
806
+ const { token } = useAuth();
807
+ const [storages, setStorages] = (0, import_react5.useState)([]);
808
+ const [storage, setStorage] = (0, import_react5.useState)(null);
809
+ const [isLoading, setIsLoading] = (0, import_react5.useState)(false);
810
+ const [isError, setIsError] = (0, import_react5.useState)(false);
811
+ const [error, setError] = (0, import_react5.useState)(null);
812
+ const apiConfig = (0, import_react5.useMemo)(() => ({
813
+ baseUrl,
814
+ token,
815
+ setStorages,
816
+ setStorage,
817
+ setIsLoading,
818
+ setIsError,
819
+ setError
820
+ }), [baseUrl, token]);
821
+ const fetchStorages = (0, import_react5.useCallback)(() => fetchStoragesRequest(apiConfig), [apiConfig]);
822
+ const fetchStorage = (0, import_react5.useCallback)((id) => fetchStorageRequest(apiConfig, id), [apiConfig]);
823
+ const createStorage = (0, import_react5.useCallback)(
824
+ (dto) => createStorageRequest(apiConfig, dto),
825
+ [apiConfig]
826
+ );
827
+ const changeStorageName = (0, import_react5.useCallback)(
828
+ (id, dto) => changeStorageNameRequest(apiConfig, id, dto),
829
+ [apiConfig]
830
+ );
831
+ const deleteStorage = (0, import_react5.useCallback)((id) => deleteStorageRequest(apiConfig, id), [apiConfig]);
832
+ const value = (0, import_react5.useMemo)(() => ({
833
+ storages,
834
+ storage,
835
+ isLoading,
836
+ isError,
837
+ error,
838
+ fetchStorages,
839
+ fetchStorage,
840
+ createStorage,
841
+ changeStorageName,
842
+ deleteStorage
843
+ }), [
844
+ changeStorageName,
845
+ createStorage,
846
+ deleteStorage,
847
+ error,
848
+ fetchStorage,
849
+ fetchStorages,
850
+ isError,
851
+ isLoading,
852
+ storage,
853
+ storages
854
+ ]);
855
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StorageContext.Provider, { value, children });
856
+ };
857
+ var useStorages = () => {
858
+ const context = (0, import_react5.useContext)(StorageContext);
859
+ if (!context) {
860
+ throw new Error("useStorages must be used within a StorageProvider");
861
+ }
862
+ return context;
863
+ };
864
+
865
+ // src/context/StorageItemContext.tsx
866
+ var import_react6 = require("react");
867
+
868
+ // src/context/api/storageItemApi.ts
869
+ var updateById4 = (items, updated) => {
870
+ const index = items.findIndex((item) => item.id === updated.id);
871
+ if (index === -1) {
872
+ return [updated, ...items];
873
+ }
874
+ const next = [...items];
875
+ next[index] = updated;
876
+ return next;
877
+ };
878
+ var fetchItemsRequest = async (config, storageId) => runWithRequestState(config, async () => {
879
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
880
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/items`, {
881
+ headers: buildAuthHeaders(config.token)
882
+ });
883
+ if (!response.ok) {
884
+ throw new Error("Failed to fetch storage items");
885
+ }
886
+ const payload = await readJson(response);
887
+ if (payload) {
888
+ config.setItems(payload);
889
+ return payload;
890
+ }
891
+ return [];
892
+ });
893
+ var addItemRequest = async (config, storageId, dto) => runWithRequestState(config, async () => {
894
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
895
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/items`, {
896
+ method: "POST",
897
+ headers: {
898
+ ...buildAuthHeaders(config.token),
899
+ "Content-Type": "application/json"
900
+ },
901
+ body: JSON.stringify(dto)
902
+ });
903
+ if (!response.ok) {
904
+ throw new Error("Failed to add storage item");
905
+ }
906
+ const payload = await readJson(response);
907
+ if (!payload) {
908
+ throw new Error("Add item response missing data");
909
+ }
910
+ config.setItems((previous) => [payload, ...previous]);
911
+ return payload;
912
+ });
913
+ var editItemRequest = async (config, storageId, itemId, dto) => runWithRequestState(config, async () => {
914
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
915
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/items/${itemId}`, {
916
+ method: "PATCH",
917
+ headers: {
918
+ ...buildAuthHeaders(config.token),
919
+ "Content-Type": "application/json"
920
+ },
921
+ body: JSON.stringify(dto)
922
+ });
923
+ if (!response.ok) {
924
+ throw new Error("Failed to edit storage item");
925
+ }
926
+ const payload = await readJson(response);
927
+ if (!payload) {
928
+ throw new Error("Edit item response missing data");
929
+ }
930
+ config.setItems((previous) => updateById4(previous, payload));
931
+ return payload;
932
+ });
933
+ var deleteItemRequest = async (config, storageId, itemId) => runWithRequestState(config, async () => {
934
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
935
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/items/${itemId}`, {
936
+ method: "DELETE",
937
+ headers: buildAuthHeaders(config.token)
938
+ });
939
+ if (!response.ok) {
940
+ throw new Error("Failed to delete storage item");
941
+ }
942
+ config.setItems((previous) => previous.filter((item) => item.id !== itemId));
943
+ });
944
+ var fetchExpiredRequest = async (config, storageId) => runWithRequestState(config, async () => {
945
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
946
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/expired`, {
947
+ headers: buildAuthHeaders(config.token)
948
+ });
949
+ if (!response.ok) {
950
+ throw new Error("Failed to fetch expired items");
951
+ }
952
+ const payload = await readJson(response);
953
+ if (payload) {
954
+ config.setExpiredItems(payload);
955
+ return payload;
956
+ }
957
+ return [];
958
+ });
959
+ var fetchAboutToExpireRequest = async (config, storageId) => runWithRequestState(config, async () => {
960
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
961
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/abouttoexpire`, {
962
+ headers: buildAuthHeaders(config.token)
963
+ });
964
+ if (!response.ok) {
965
+ throw new Error("Failed to fetch items about to expire");
966
+ }
967
+ const payload = await readJson(response);
968
+ if (payload) {
969
+ config.setAboutToExpireItems(payload);
970
+ return payload;
971
+ }
972
+ return [];
973
+ });
974
+ var fetchRunningLowRequest = async (config, storageId) => runWithRequestState(config, async () => {
975
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
976
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/runninglow`, {
977
+ headers: buildAuthHeaders(config.token)
978
+ });
979
+ if (!response.ok) {
980
+ throw new Error("Failed to fetch running low items");
981
+ }
982
+ const payload = await readJson(response);
983
+ if (payload) {
984
+ config.setRunningLow(payload);
985
+ return payload;
986
+ }
987
+ return [];
988
+ });
989
+
990
+ // src/context/StorageItemContext.tsx
991
+ var import_jsx_runtime6 = require("react/jsx-runtime");
992
+ var StorageItemContext = (0, import_react6.createContext)(void 0);
993
+ var StorageItemProvider = ({ baseUrl, children }) => {
994
+ const { token } = useAuth();
995
+ const [items, setItems] = (0, import_react6.useState)([]);
996
+ const [expiredItems, setExpiredItems] = (0, import_react6.useState)([]);
997
+ const [aboutToExpireItems, setAboutToExpireItems] = (0, import_react6.useState)([]);
998
+ const [runningLow, setRunningLow] = (0, import_react6.useState)([]);
999
+ const [isLoading, setIsLoading] = (0, import_react6.useState)(false);
1000
+ const [isError, setIsError] = (0, import_react6.useState)(false);
1001
+ const [error, setError] = (0, import_react6.useState)(null);
1002
+ const apiConfig = (0, import_react6.useMemo)(() => ({
1003
+ baseUrl,
1004
+ token,
1005
+ setItems,
1006
+ setExpiredItems,
1007
+ setAboutToExpireItems,
1008
+ setRunningLow,
1009
+ setIsLoading,
1010
+ setIsError,
1011
+ setError
1012
+ }), [baseUrl, token]);
1013
+ const fetchItems = (0, import_react6.useCallback)((storageId) => fetchItemsRequest(apiConfig, storageId), [apiConfig]);
1014
+ const addItem = (0, import_react6.useCallback)(
1015
+ (storageId, dto) => addItemRequest(apiConfig, storageId, dto),
1016
+ [apiConfig]
1017
+ );
1018
+ const editItem = (0, import_react6.useCallback)(
1019
+ (storageId, itemId, dto) => editItemRequest(apiConfig, storageId, itemId, dto),
1020
+ [apiConfig]
1021
+ );
1022
+ const deleteItem = (0, import_react6.useCallback)(
1023
+ (storageId, itemId) => deleteItemRequest(apiConfig, storageId, itemId),
1024
+ [apiConfig]
1025
+ );
1026
+ const fetchExpired = (0, import_react6.useCallback)(
1027
+ (storageId) => fetchExpiredRequest(apiConfig, storageId),
1028
+ [apiConfig]
1029
+ );
1030
+ const fetchAboutToExpire = (0, import_react6.useCallback)(
1031
+ (storageId) => fetchAboutToExpireRequest(apiConfig, storageId),
1032
+ [apiConfig]
1033
+ );
1034
+ const fetchRunningLow = (0, import_react6.useCallback)(
1035
+ (storageId) => fetchRunningLowRequest(apiConfig, storageId),
1036
+ [apiConfig]
1037
+ );
1038
+ const value = (0, import_react6.useMemo)(() => ({
1039
+ items,
1040
+ expiredItems,
1041
+ aboutToExpireItems,
1042
+ runningLow,
1043
+ isLoading,
1044
+ isError,
1045
+ error,
1046
+ fetchItems,
1047
+ addItem,
1048
+ editItem,
1049
+ deleteItem,
1050
+ fetchExpired,
1051
+ fetchAboutToExpire,
1052
+ fetchRunningLow
1053
+ }), [
1054
+ aboutToExpireItems,
1055
+ addItem,
1056
+ deleteItem,
1057
+ editItem,
1058
+ error,
1059
+ expiredItems,
1060
+ fetchAboutToExpire,
1061
+ fetchExpired,
1062
+ fetchItems,
1063
+ fetchRunningLow,
1064
+ isError,
1065
+ isLoading,
1066
+ items,
1067
+ runningLow
1068
+ ]);
1069
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StorageItemContext.Provider, { value, children });
1070
+ };
1071
+ var useStorageItems = () => {
1072
+ const context = (0, import_react6.useContext)(StorageItemContext);
1073
+ if (!context) {
1074
+ throw new Error("useStorageItems must be used within a StorageItemProvider");
1075
+ }
1076
+ return context;
1077
+ };
1078
+
1079
+ // src/context/StorageMemberContext.tsx
1080
+ var import_react7 = require("react");
1081
+
1082
+ // src/context/api/storageMemberApi.ts
1083
+ var fetchMembersRequest = async (config, storageId) => runWithRequestState(config, async () => {
1084
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
1085
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/members`, {
1086
+ headers: buildAuthHeaders(config.token)
1087
+ });
1088
+ if (!response.ok) {
1089
+ throw new Error("Failed to fetch storage members");
1090
+ }
1091
+ const payload = await readJson(response);
1092
+ if (payload) {
1093
+ config.setMembers(payload);
1094
+ return payload;
1095
+ }
1096
+ return [];
1097
+ });
1098
+ var inviteMemberRequest = async (config, storageId, dto) => runWithRequestState(config, async () => {
1099
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
1100
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/members`, {
1101
+ method: "POST",
1102
+ headers: {
1103
+ ...buildAuthHeaders(config.token),
1104
+ "Content-Type": "application/json"
1105
+ },
1106
+ body: JSON.stringify(dto)
1107
+ });
1108
+ if (!response.ok) {
1109
+ throw new Error("Failed to invite member");
1110
+ }
1111
+ const payload = await readJson(response);
1112
+ if (!payload) {
1113
+ throw new Error("Invite member response missing data");
1114
+ }
1115
+ config.setMembers((previous) => [payload, ...previous]);
1116
+ return payload;
1117
+ });
1118
+ var removeMemberRequest = async (config, storageId, userId) => runWithRequestState(config, async () => {
1119
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
1120
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/members/${userId}`, {
1121
+ method: "DELETE",
1122
+ headers: buildAuthHeaders(config.token)
1123
+ });
1124
+ if (!response.ok) {
1125
+ throw new Error("Failed to remove member");
1126
+ }
1127
+ config.setMembers((previous) => previous.filter((member) => member.user.id !== userId));
1128
+ });
1129
+
1130
+ // src/context/StorageMemberContext.tsx
1131
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1132
+ var StorageMemberContext = (0, import_react7.createContext)(void 0);
1133
+ var StorageMemberProvider = ({ baseUrl, children }) => {
1134
+ const { token } = useAuth();
1135
+ const [members, setMembers] = (0, import_react7.useState)([]);
1136
+ const [isLoading, setIsLoading] = (0, import_react7.useState)(false);
1137
+ const [isError, setIsError] = (0, import_react7.useState)(false);
1138
+ const [error, setError] = (0, import_react7.useState)(null);
1139
+ const apiConfig = (0, import_react7.useMemo)(() => ({
1140
+ baseUrl,
1141
+ token,
1142
+ setMembers,
1143
+ setIsLoading,
1144
+ setIsError,
1145
+ setError
1146
+ }), [baseUrl, token]);
1147
+ const fetchMembers = (0, import_react7.useCallback)(
1148
+ (storageId) => fetchMembersRequest(apiConfig, storageId),
1149
+ [apiConfig]
1150
+ );
1151
+ const inviteMember = (0, import_react7.useCallback)(
1152
+ (storageId, dto) => inviteMemberRequest(apiConfig, storageId, dto),
1153
+ [apiConfig]
1154
+ );
1155
+ const removeMember = (0, import_react7.useCallback)(
1156
+ (storageId, userId) => removeMemberRequest(apiConfig, storageId, userId),
1157
+ [apiConfig]
1158
+ );
1159
+ const value = (0, import_react7.useMemo)(() => ({
1160
+ members,
1161
+ isLoading,
1162
+ isError,
1163
+ error,
1164
+ fetchMembers,
1165
+ inviteMember,
1166
+ removeMember
1167
+ }), [error, fetchMembers, inviteMember, isError, isLoading, members, removeMember]);
1168
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StorageMemberContext.Provider, { value, children });
1169
+ };
1170
+ var useStorageMembers = () => {
1171
+ const context = (0, import_react7.useContext)(StorageMemberContext);
1172
+ if (!context) {
1173
+ throw new Error("useStorageMembers must be used within a StorageMemberProvider");
1174
+ }
1175
+ return context;
1176
+ };
1177
+
1178
+ // src/context/UserContext.tsx
1179
+ var import_react8 = require("react");
1180
+
1181
+ // src/context/api/userApi.ts
1182
+ var updateById5 = (items, updated) => {
1183
+ const index = items.findIndex((item) => item.id === updated.id);
1184
+ if (index === -1) {
1185
+ return [updated, ...items];
1186
+ }
1187
+ const next = [...items];
1188
+ next[index] = updated;
1189
+ return next;
1190
+ };
1191
+ var fetchUsersRequest = async (config) => runWithRequestState(
1192
+ config,
1193
+ async () => {
1194
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
1195
+ const response = await fetch(`${normalizedBaseUrl}/api/users`, {
1196
+ headers: buildAuthHeaders(config.token)
1197
+ });
1198
+ if (!response.ok) {
1199
+ throw new Error("Failed to fetch users");
1200
+ }
1201
+ const payload = await readJson(response);
1202
+ if (payload) {
1203
+ config.setUsers(payload);
1204
+ return payload;
1205
+ }
1206
+ return [];
1207
+ }
1208
+ );
1209
+ var fetchUserRequest = async (config, id) => runWithRequestState(config, async () => {
1210
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
1211
+ const response = await fetch(`${normalizedBaseUrl}/api/users/${id}`, {
1212
+ headers: buildAuthHeaders(config.token)
1213
+ });
1214
+ if (response.status === 404) {
1215
+ config.setUser(null);
1216
+ return null;
1217
+ }
1218
+ if (!response.ok) {
1219
+ throw new Error("Failed to fetch user");
1220
+ }
1221
+ const payload = await readJson(response);
1222
+ if (!payload) {
1223
+ throw new Error("User response missing data");
1224
+ }
1225
+ config.setUser(payload);
1226
+ config.setUsers((previous) => updateById5(previous, payload));
1227
+ return payload;
1228
+ });
1229
+ var updateUserRequest = async (config, id, dto) => runWithRequestState(config, async () => {
1230
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
1231
+ const response = await fetch(`${normalizedBaseUrl}/api/users/${id}`, {
1232
+ method: "PATCH",
1233
+ headers: {
1234
+ ...buildAuthHeaders(config.token),
1235
+ "Content-Type": "application/json"
1236
+ },
1237
+ body: JSON.stringify(dto)
1238
+ });
1239
+ if (!response.ok) {
1240
+ throw new Error("Failed to update user");
1241
+ }
1242
+ const payload = await readJson(response);
1243
+ if (!payload) {
1244
+ throw new Error("Update user response missing data");
1245
+ }
1246
+ config.setUsers((previous) => updateById5(previous, payload));
1247
+ config.setUser(payload);
1248
+ return payload;
1249
+ });
1250
+ var deleteUserRequest = async (config, id) => runWithRequestState(config, async () => {
1251
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
1252
+ const response = await fetch(`${normalizedBaseUrl}/api/users/${id}`, {
1253
+ method: "DELETE",
1254
+ headers: buildAuthHeaders(config.token)
1255
+ });
1256
+ if (!response.ok) {
1257
+ throw new Error("Failed to delete user");
1258
+ }
1259
+ config.setUsers((previous) => previous.filter((item) => item.id !== id));
1260
+ config.setUser((current) => current?.id === id ? null : current);
1261
+ });
1262
+ var getUserPfpRequest = async (config, id) => runWithRequestState(config, async () => {
1263
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
1264
+ const response = await fetch(`${normalizedBaseUrl}/api/users/${id}/pfp`, {
1265
+ headers: buildAuthHeaders(config.token)
1266
+ });
1267
+ if (!response.ok) {
1268
+ throw new Error("Failed to fetch user pfp");
1269
+ }
1270
+ return readArrayBuffer(response);
1271
+ });
1272
+ var uploadUserPfpRequest = async (config, id, file) => runWithRequestState(config, async () => {
1273
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
1274
+ const formData = new FormData();
1275
+ formData.append("pfp", file);
1276
+ const response = await fetch(`${normalizedBaseUrl}/api/users/${id}/pfp`, {
1277
+ method: "POST",
1278
+ headers: buildAuthHeaders(config.token),
1279
+ body: formData
1280
+ });
1281
+ if (!response.ok) {
1282
+ throw new Error("Failed to upload user pfp");
1283
+ }
1284
+ });
1285
+
1286
+ // src/context/UserContext.tsx
1287
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1288
+ var UserContext = (0, import_react8.createContext)(void 0);
1289
+ var UserProvider = ({ baseUrl, children }) => {
1290
+ const { token } = useAuth();
1291
+ const [users, setUsers] = (0, import_react8.useState)([]);
1292
+ const [user, setUser] = (0, import_react8.useState)(null);
1293
+ const [isLoading, setIsLoading] = (0, import_react8.useState)(false);
1294
+ const [isError, setIsError] = (0, import_react8.useState)(false);
1295
+ const [error, setError] = (0, import_react8.useState)(null);
1296
+ const apiConfig = (0, import_react8.useMemo)(() => ({
1297
+ baseUrl,
1298
+ token,
1299
+ setUsers,
1300
+ setUser,
1301
+ setIsLoading,
1302
+ setIsError,
1303
+ setError
1304
+ }), [baseUrl, token]);
1305
+ const fetchUsers = (0, import_react8.useCallback)(() => fetchUsersRequest(apiConfig), [apiConfig]);
1306
+ const fetchUser = (0, import_react8.useCallback)((id) => fetchUserRequest(apiConfig, id), [apiConfig]);
1307
+ const updateUser = (0, import_react8.useCallback)(
1308
+ (id, dto) => updateUserRequest(apiConfig, id, dto),
1309
+ [apiConfig]
1310
+ );
1311
+ const deleteUser = (0, import_react8.useCallback)((id) => deleteUserRequest(apiConfig, id), [apiConfig]);
1312
+ const getUserPfp = (0, import_react8.useCallback)((id) => getUserPfpRequest(apiConfig, id), [apiConfig]);
1313
+ const uploadUserPfp = (0, import_react8.useCallback)(
1314
+ (id, file) => uploadUserPfpRequest(apiConfig, id, file),
1315
+ [apiConfig]
1316
+ );
1317
+ const value = (0, import_react8.useMemo)(() => ({
1318
+ users,
1319
+ user,
1320
+ isLoading,
1321
+ isError,
1322
+ error,
1323
+ fetchUsers,
1324
+ fetchUser,
1325
+ updateUser,
1326
+ deleteUser,
1327
+ getUserPfp,
1328
+ uploadUserPfp
1329
+ }), [
1330
+ deleteUser,
1331
+ error,
1332
+ fetchUser,
1333
+ fetchUsers,
1334
+ getUserPfp,
1335
+ isError,
1336
+ isLoading,
1337
+ updateUser,
1338
+ uploadUserPfp,
1339
+ user,
1340
+ users
1341
+ ]);
1342
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(UserContext.Provider, { value, children });
1343
+ };
1344
+ var useUsers = () => {
1345
+ const context = (0, import_react8.useContext)(UserContext);
1346
+ if (!context) {
1347
+ throw new Error("useUsers must be used within a UserProvider");
1348
+ }
1349
+ return context;
1350
+ };
1351
+ // Annotate the CommonJS export names for ESM import in node:
1352
+ 0 && (module.exports = {
1353
+ AuthProvider,
1354
+ InviteProvider,
1355
+ ProductProvider,
1356
+ RunningLowProvider,
1357
+ StorageItemProvider,
1358
+ StorageMemberProvider,
1359
+ StorageProvider,
1360
+ UserProvider,
1361
+ buildAuthHeaders,
1362
+ normalizeBaseUrl,
1363
+ readArrayBuffer,
1364
+ readJson,
1365
+ useAuth,
1366
+ useInvites,
1367
+ useProducts,
1368
+ useRunningLow,
1369
+ useStorageItems,
1370
+ useStorageMembers,
1371
+ useStorages,
1372
+ useUsers
1373
+ });
1374
+ //# sourceMappingURL=index.cjs.js.map