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,141 +1,141 @@
|
|
|
1
|
-
import type { RunningLowSetting } from '../../type/models.js';
|
|
2
|
-
import type { CreateSettingRequest, EditSettingRequest } from '../../type/requests.js';
|
|
3
|
-
import type { CreateRunningLowSettingError, EditRunningLowSettingError } from '../../type/runninglow.js';
|
|
4
|
-
import { buildAuthHeaders, normalizeBaseUrl, readJson } from '../http.js';
|
|
5
|
-
import { runWithRequestState, type RequestStateHandlers } from './requestState.js';
|
|
6
|
-
|
|
7
|
-
type RunningLowApiConfig = RequestStateHandlers & {
|
|
8
|
-
baseUrl: string;
|
|
9
|
-
token: string | null;
|
|
10
|
-
setSettings: (value: RunningLowSetting[] | ((items: RunningLowSetting[]) => RunningLowSetting[])) => void;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
const updateById = (items: RunningLowSetting[], updated: RunningLowSetting): RunningLowSetting[] => {
|
|
14
|
-
const index = items.findIndex((item) => item.id === updated.id);
|
|
15
|
-
if (index === -1) {
|
|
16
|
-
return [updated, ...items];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const next = [...items];
|
|
20
|
-
next[index] = updated;
|
|
21
|
-
return next;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export const fetchSettingsRequest = async (
|
|
25
|
-
config: RunningLowApiConfig,
|
|
26
|
-
storageId: number
|
|
27
|
-
): Promise<RunningLowSetting[]> => runWithRequestState(config, async () => {
|
|
28
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
29
|
-
const response = await fetch(
|
|
30
|
-
`${normalizedBaseUrl}/api/storages/${storageId}/runninglowsettings`,
|
|
31
|
-
{
|
|
32
|
-
headers: buildAuthHeaders(config.token)
|
|
33
|
-
}
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
if (!response.ok) {
|
|
37
|
-
throw new Error('Failed to fetch running low settings');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const payload = await readJson<RunningLowSetting[]>(response);
|
|
41
|
-
if (payload) {
|
|
42
|
-
config.setSettings(payload);
|
|
43
|
-
return payload;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return [];
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
export const createSettingRequest = async (
|
|
50
|
-
config: RunningLowApiConfig,
|
|
51
|
-
storageId: number,
|
|
52
|
-
dto: CreateSettingRequest
|
|
53
|
-
): Promise<RunningLowSetting> => runWithRequestState(config, async () => {
|
|
54
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
55
|
-
const response = await fetch(
|
|
56
|
-
`${normalizedBaseUrl}/api/storages/${storageId}/runninglowsettings`,
|
|
57
|
-
{
|
|
58
|
-
method: 'POST',
|
|
59
|
-
headers: {
|
|
60
|
-
...buildAuthHeaders(config.token),
|
|
61
|
-
'Content-Type': 'application/json'
|
|
62
|
-
},
|
|
63
|
-
body: JSON.stringify(dto)
|
|
64
|
-
}
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
if (!response.ok) {
|
|
68
|
-
const err = await readJson<CreateRunningLowSettingError>(response);
|
|
69
|
-
|
|
70
|
-
if (err?.productId || err?.runningLow)
|
|
71
|
-
throw err;
|
|
72
|
-
|
|
73
|
-
throw new Error('Failed to create running low setting');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const payload = await readJson<RunningLowSetting>(response);
|
|
77
|
-
if (!payload) {
|
|
78
|
-
throw new Error('Create running low response missing data');
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
config.setSettings((previous) => [payload, ...previous]);
|
|
82
|
-
return payload;
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
export const editSettingRequest = async (
|
|
86
|
-
config: RunningLowApiConfig,
|
|
87
|
-
storageId: number,
|
|
88
|
-
id: number,
|
|
89
|
-
dto: EditSettingRequest
|
|
90
|
-
): Promise<RunningLowSetting> => runWithRequestState(config, async () => {
|
|
91
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
92
|
-
const response = await fetch(
|
|
93
|
-
`${normalizedBaseUrl}/api/storages/${storageId}/runninglowsettings/${id}`,
|
|
94
|
-
{
|
|
95
|
-
method: 'PUT',
|
|
96
|
-
headers: {
|
|
97
|
-
...buildAuthHeaders(config.token),
|
|
98
|
-
'Content-Type': 'application/json'
|
|
99
|
-
},
|
|
100
|
-
body: JSON.stringify(dto)
|
|
101
|
-
}
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
if (!response.ok) {
|
|
105
|
-
const err = await readJson<EditRunningLowSettingError>(response);
|
|
106
|
-
|
|
107
|
-
if (err?.runningLow)
|
|
108
|
-
throw err;
|
|
109
|
-
|
|
110
|
-
throw new Error('Failed to edit running low setting');
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const payload = await readJson<RunningLowSetting>(response);
|
|
114
|
-
if (!payload) {
|
|
115
|
-
throw new Error('Edit running low response missing data');
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
config.setSettings((previous) => updateById(previous, payload));
|
|
119
|
-
return payload;
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
export const deleteSettingRequest = async (
|
|
123
|
-
config: RunningLowApiConfig,
|
|
124
|
-
storageId: number,
|
|
125
|
-
id: number
|
|
126
|
-
): Promise<void> => runWithRequestState(config, async () => {
|
|
127
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
128
|
-
const response = await fetch(
|
|
129
|
-
`${normalizedBaseUrl}/api/storages/${storageId}/runninglowsettings/${id}`,
|
|
130
|
-
{
|
|
131
|
-
method: 'DELETE',
|
|
132
|
-
headers: buildAuthHeaders(config.token)
|
|
133
|
-
}
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
if (!response.ok) {
|
|
137
|
-
throw new Error('Failed to delete running low setting');
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
config.setSettings((previous) => previous.filter((item) => item.id !== id));
|
|
141
|
-
});
|
|
1
|
+
import type { RunningLowSetting } from '../../type/models.js';
|
|
2
|
+
import type { CreateSettingRequest, EditSettingRequest } from '../../type/requests.js';
|
|
3
|
+
import type { CreateRunningLowSettingError, EditRunningLowSettingError } from '../../type/runninglow.js';
|
|
4
|
+
import { buildAuthHeaders, normalizeBaseUrl, readJson } from '../http.js';
|
|
5
|
+
import { runWithRequestState, type RequestStateHandlers } from './requestState.js';
|
|
6
|
+
|
|
7
|
+
type RunningLowApiConfig = RequestStateHandlers & {
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
token: string | null;
|
|
10
|
+
setSettings: (value: RunningLowSetting[] | ((items: RunningLowSetting[]) => RunningLowSetting[])) => void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const updateById = (items: RunningLowSetting[], updated: RunningLowSetting): RunningLowSetting[] => {
|
|
14
|
+
const index = items.findIndex((item) => item.id === updated.id);
|
|
15
|
+
if (index === -1) {
|
|
16
|
+
return [updated, ...items];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const next = [...items];
|
|
20
|
+
next[index] = updated;
|
|
21
|
+
return next;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const fetchSettingsRequest = async (
|
|
25
|
+
config: RunningLowApiConfig,
|
|
26
|
+
storageId: number
|
|
27
|
+
): Promise<RunningLowSetting[]> => runWithRequestState(config, async () => {
|
|
28
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
29
|
+
const response = await fetch(
|
|
30
|
+
`${normalizedBaseUrl}/api/storages/${storageId}/runninglowsettings`,
|
|
31
|
+
{
|
|
32
|
+
headers: buildAuthHeaders(config.token)
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
throw new Error('Failed to fetch running low settings');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const payload = await readJson<RunningLowSetting[]>(response);
|
|
41
|
+
if (payload) {
|
|
42
|
+
config.setSettings(payload);
|
|
43
|
+
return payload;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return [];
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export const createSettingRequest = async (
|
|
50
|
+
config: RunningLowApiConfig,
|
|
51
|
+
storageId: number,
|
|
52
|
+
dto: CreateSettingRequest
|
|
53
|
+
): Promise<RunningLowSetting> => runWithRequestState(config, async () => {
|
|
54
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
55
|
+
const response = await fetch(
|
|
56
|
+
`${normalizedBaseUrl}/api/storages/${storageId}/runninglowsettings`,
|
|
57
|
+
{
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: {
|
|
60
|
+
...buildAuthHeaders(config.token),
|
|
61
|
+
'Content-Type': 'application/json'
|
|
62
|
+
},
|
|
63
|
+
body: JSON.stringify(dto)
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
if (!response.ok) {
|
|
68
|
+
const err = await readJson<CreateRunningLowSettingError>(response);
|
|
69
|
+
|
|
70
|
+
if (err?.productId || err?.runningLow)
|
|
71
|
+
throw err;
|
|
72
|
+
|
|
73
|
+
throw new Error('Failed to create running low setting');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const payload = await readJson<RunningLowSetting>(response);
|
|
77
|
+
if (!payload) {
|
|
78
|
+
throw new Error('Create running low response missing data');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
config.setSettings((previous) => [payload, ...previous]);
|
|
82
|
+
return payload;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export const editSettingRequest = async (
|
|
86
|
+
config: RunningLowApiConfig,
|
|
87
|
+
storageId: number,
|
|
88
|
+
id: number,
|
|
89
|
+
dto: EditSettingRequest
|
|
90
|
+
): Promise<RunningLowSetting> => runWithRequestState(config, async () => {
|
|
91
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
92
|
+
const response = await fetch(
|
|
93
|
+
`${normalizedBaseUrl}/api/storages/${storageId}/runninglowsettings/${id}`,
|
|
94
|
+
{
|
|
95
|
+
method: 'PUT',
|
|
96
|
+
headers: {
|
|
97
|
+
...buildAuthHeaders(config.token),
|
|
98
|
+
'Content-Type': 'application/json'
|
|
99
|
+
},
|
|
100
|
+
body: JSON.stringify(dto)
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
if (!response.ok) {
|
|
105
|
+
const err = await readJson<EditRunningLowSettingError>(response);
|
|
106
|
+
|
|
107
|
+
if (err?.runningLow)
|
|
108
|
+
throw err;
|
|
109
|
+
|
|
110
|
+
throw new Error('Failed to edit running low setting');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const payload = await readJson<RunningLowSetting>(response);
|
|
114
|
+
if (!payload) {
|
|
115
|
+
throw new Error('Edit running low response missing data');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
config.setSettings((previous) => updateById(previous, payload));
|
|
119
|
+
return payload;
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
export const deleteSettingRequest = async (
|
|
123
|
+
config: RunningLowApiConfig,
|
|
124
|
+
storageId: number,
|
|
125
|
+
id: number
|
|
126
|
+
): Promise<void> => runWithRequestState(config, async () => {
|
|
127
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
128
|
+
const response = await fetch(
|
|
129
|
+
`${normalizedBaseUrl}/api/storages/${storageId}/runninglowsettings/${id}`,
|
|
130
|
+
{
|
|
131
|
+
method: 'DELETE',
|
|
132
|
+
headers: buildAuthHeaders(config.token)
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
if (!response.ok) {
|
|
137
|
+
throw new Error('Failed to delete running low setting');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
config.setSettings((previous) => previous.filter((item) => item.id !== id));
|
|
141
|
+
});
|
|
@@ -1,159 +1,161 @@
|
|
|
1
|
-
import type { ShoppingListItem } from '../../type/models.js';
|
|
2
|
-
import type { CreateShoppingItemRequest, EditShoppingItemRequest } from '../../type/requests.js';
|
|
3
|
-
import type { CreateShoppingItemError, EditShoppingItemError } from '../../type/shoppingList.js';
|
|
4
|
-
import { buildAuthHeaders, normalizeBaseUrl, readJson } from '../http.js';
|
|
5
|
-
import { runWithRequestState, type RequestStateHandlers } from './requestState.js';
|
|
6
|
-
|
|
7
|
-
type ShoppingListApiConfig = RequestStateHandlers & {
|
|
8
|
-
baseUrl: string;
|
|
9
|
-
token: string | null;
|
|
10
|
-
setItems: (value: ShoppingListItem[] | ((items: ShoppingListItem[]) => ShoppingListItem[])) => void;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
const updateById = (items: ShoppingListItem[], updated: ShoppingListItem): ShoppingListItem[] => {
|
|
14
|
-
const index = items.findIndex((i) => i.id === updated.id);
|
|
15
|
-
if (index === -1) return [updated, ...items];
|
|
16
|
-
const next = [...items];
|
|
17
|
-
next[index] = updated;
|
|
18
|
-
return next;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const fetchShoppingListRequest = async (
|
|
22
|
-
config: ShoppingListApiConfig,
|
|
23
|
-
storageId: number
|
|
24
|
-
): Promise<ShoppingListItem[]> => runWithRequestState(config, async () => {
|
|
25
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
26
|
-
const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/shoppinglist`, {
|
|
27
|
-
headers: buildAuthHeaders(config.token)
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
if (!response.ok) {
|
|
31
|
-
throw new Error('Failed to fetch shopping list items');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const payload = await readJson<ShoppingListItem[]>(response);
|
|
35
|
-
if (payload) {
|
|
36
|
-
config.setItems(payload);
|
|
37
|
-
return payload;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return [];
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
export const fetchAggregatedShoppingListRequest = async (
|
|
44
|
-
config: ShoppingListApiConfig
|
|
45
|
-
): Promise<ShoppingListItem[]> => runWithRequestState(config, async () => {
|
|
46
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
47
|
-
const response = await fetch(`${normalizedBaseUrl}/api/shoppinglist`, {
|
|
48
|
-
headers: buildAuthHeaders(config.token)
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
if (!response.ok) {
|
|
52
|
-
throw new Error('Failed to fetch aggregated shopping list');
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const payload = await readJson<ShoppingListItem[]>(response);
|
|
56
|
-
if (payload) {
|
|
57
|
-
config.setItems(payload);
|
|
58
|
-
return payload;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return [];
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
export const createStorageItemsWithShoppingListItemRequest = async (
|
|
65
|
-
config: ShoppingListApiConfig,
|
|
66
|
-
storageId: number,
|
|
67
|
-
itemId: number
|
|
68
|
-
) => runWithRequestState(config, async () => {
|
|
69
|
-
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
70
|
-
const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/shoppinglist/${itemId}`, {
|
|
71
|
-
method: 'POST',
|
|
72
|
-
headers: buildAuthHeaders(config.token)
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
if (!response.ok) {
|
|
76
|
-
throw new Error('Failed to add items');
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
1
|
+
import type { ShoppingListItem } from '../../type/models.js';
|
|
2
|
+
import type { CreateShoppingItemRequest, EditShoppingItemRequest } from '../../type/requests.js';
|
|
3
|
+
import type { CreateShoppingItemError, EditShoppingItemError } from '../../type/shoppingList.js';
|
|
4
|
+
import { buildAuthHeaders, normalizeBaseUrl, readJson } from '../http.js';
|
|
5
|
+
import { runWithRequestState, type RequestStateHandlers } from './requestState.js';
|
|
6
|
+
|
|
7
|
+
type ShoppingListApiConfig = RequestStateHandlers & {
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
token: string | null;
|
|
10
|
+
setItems: (value: ShoppingListItem[] | ((items: ShoppingListItem[]) => ShoppingListItem[])) => void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const updateById = (items: ShoppingListItem[], updated: ShoppingListItem): ShoppingListItem[] => {
|
|
14
|
+
const index = items.findIndex((i) => i.id === updated.id);
|
|
15
|
+
if (index === -1) return [updated, ...items];
|
|
16
|
+
const next = [...items];
|
|
17
|
+
next[index] = updated;
|
|
18
|
+
return next;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const fetchShoppingListRequest = async (
|
|
22
|
+
config: ShoppingListApiConfig,
|
|
23
|
+
storageId: number
|
|
24
|
+
): Promise<ShoppingListItem[]> => runWithRequestState(config, async () => {
|
|
25
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
26
|
+
const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/shoppinglist`, {
|
|
27
|
+
headers: buildAuthHeaders(config.token)
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
throw new Error('Failed to fetch shopping list items');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const payload = await readJson<ShoppingListItem[]>(response);
|
|
35
|
+
if (payload) {
|
|
36
|
+
config.setItems(payload);
|
|
37
|
+
return payload;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return [];
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export const fetchAggregatedShoppingListRequest = async (
|
|
44
|
+
config: ShoppingListApiConfig
|
|
45
|
+
): Promise<ShoppingListItem[]> => runWithRequestState(config, async () => {
|
|
46
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
47
|
+
const response = await fetch(`${normalizedBaseUrl}/api/shoppinglist`, {
|
|
48
|
+
headers: buildAuthHeaders(config.token)
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
throw new Error('Failed to fetch aggregated shopping list');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const payload = await readJson<ShoppingListItem[]>(response);
|
|
56
|
+
if (payload) {
|
|
57
|
+
config.setItems(payload);
|
|
58
|
+
return payload;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return [];
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export const createStorageItemsWithShoppingListItemRequest = async (
|
|
65
|
+
config: ShoppingListApiConfig,
|
|
66
|
+
storageId: number,
|
|
67
|
+
itemId: number
|
|
68
|
+
) => runWithRequestState(config, async () => {
|
|
69
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
70
|
+
const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/shoppinglist/${itemId}`, {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
headers: buildAuthHeaders(config.token)
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
if (!response.ok) {
|
|
76
|
+
throw new Error('Failed to add items');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
config.setItems((previous) => previous.filter((i) => i.id !== itemId));
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
export const createShoppingItemRequest = async (
|
|
83
|
+
config: ShoppingListApiConfig,
|
|
84
|
+
storageId: number,
|
|
85
|
+
dto: CreateShoppingItemRequest
|
|
86
|
+
): Promise<ShoppingListItem> => runWithRequestState(config, async () => {
|
|
87
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
88
|
+
const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/shoppinglist`, {
|
|
89
|
+
method: 'POST',
|
|
90
|
+
headers: {
|
|
91
|
+
...buildAuthHeaders(config.token),
|
|
92
|
+
'Content-Type': 'application/json'
|
|
93
|
+
},
|
|
94
|
+
body: JSON.stringify(dto)
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
const err = await readJson<CreateShoppingItemError>(response);
|
|
99
|
+
|
|
100
|
+
if (err?.productId || err?.amountToBuy)
|
|
101
|
+
throw err;
|
|
102
|
+
|
|
103
|
+
throw new Error('Failed to create shopping list item');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const payload = await readJson<ShoppingListItem>(response);
|
|
107
|
+
if (!payload) throw new Error('Create shopping item response missing data');
|
|
108
|
+
|
|
109
|
+
config.setItems((previous) => [payload, ...previous]);
|
|
110
|
+
return payload;
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
export const editShoppingItemRequest = async (
|
|
114
|
+
config: ShoppingListApiConfig,
|
|
115
|
+
storageId: number,
|
|
116
|
+
itemId: number,
|
|
117
|
+
dto: EditShoppingItemRequest
|
|
118
|
+
): Promise<ShoppingListItem> => runWithRequestState(config, async () => {
|
|
119
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
120
|
+
const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/shoppinglist/${itemId}`, {
|
|
121
|
+
method: 'PUT',
|
|
122
|
+
headers: {
|
|
123
|
+
...buildAuthHeaders(config.token),
|
|
124
|
+
'Content-Type': 'application/json'
|
|
125
|
+
},
|
|
126
|
+
body: JSON.stringify(dto)
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
if (!response.ok) {
|
|
130
|
+
const err = await readJson<EditShoppingItemError>(response);
|
|
131
|
+
|
|
132
|
+
if (err?.productId || err?.amountToBuy)
|
|
133
|
+
throw err;
|
|
134
|
+
|
|
135
|
+
throw new Error('Failed to edit shopping list item');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const payload = await readJson<ShoppingListItem>(response);
|
|
139
|
+
if (!payload) throw new Error('Edit shopping item response missing data');
|
|
140
|
+
|
|
141
|
+
config.setItems((previous) => updateById(previous, payload));
|
|
142
|
+
return payload;
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
export const deleteShoppingItemRequest = async (
|
|
146
|
+
config: ShoppingListApiConfig,
|
|
147
|
+
storageId: number,
|
|
148
|
+
itemId: number
|
|
149
|
+
): Promise<void> => runWithRequestState(config, async () => {
|
|
150
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
151
|
+
const response = await fetch(`${normalizedBaseUrl}/api/storages/${storageId}/shoppinglist/${itemId}`, {
|
|
152
|
+
method: 'DELETE',
|
|
153
|
+
headers: buildAuthHeaders(config.token)
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
if (!response.ok) {
|
|
157
|
+
throw new Error('Failed to delete shopping list item');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
config.setItems((previous) => previous.filter((i) => i.id !== itemId));
|
|
161
|
+
});
|