shelflife-react-hooks 1.0.19 → 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 +22 -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 +22 -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 -161
- 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
package/package.json
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "shelflife-react-hooks",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "",
|
|
5
|
-
"license": "ISC",
|
|
6
|
-
"author": "Preisler25",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"main": "dist/index.cjs.js",
|
|
9
|
-
"module": "dist/index.esm.js",
|
|
10
|
-
"types": "dist/index.d.ts",
|
|
11
|
-
"scripts": {
|
|
12
|
-
"build": "tsup",
|
|
13
|
-
"test": "vitest run"
|
|
14
|
-
},
|
|
15
|
-
"exports": {
|
|
16
|
-
".": {
|
|
17
|
-
"types": "./dist/index.d.ts",
|
|
18
|
-
"import": "./dist/index.esm.js",
|
|
19
|
-
"require": "./dist/index.cjs.js"
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
"devDependencies": {
|
|
23
|
-
"@testing-library/dom": "^10.4.1",
|
|
24
|
-
"@testing-library/react": "^16.3.2",
|
|
25
|
-
"@types/node": "^25.2.3",
|
|
26
|
-
"@types/react": "^19.0.0",
|
|
27
|
-
"jsdom": "^28.1.0",
|
|
28
|
-
"ts-node": "^10.9.2",
|
|
29
|
-
"tsup": "^8.5.1",
|
|
30
|
-
"typescript": "^5.9.3",
|
|
31
|
-
"vitest": "^2.1.9"
|
|
32
|
-
},
|
|
33
|
-
"peerDependencies": {
|
|
34
|
-
"react": "^19.0.0"
|
|
35
|
-
}
|
|
36
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "shelflife-react-hooks",
|
|
3
|
+
"version": "1.0.20",
|
|
4
|
+
"description": "",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"author": "Preisler25",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/index.cjs.js",
|
|
9
|
+
"module": "dist/index.esm.js",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsup",
|
|
13
|
+
"test": "vitest run"
|
|
14
|
+
},
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.esm.js",
|
|
19
|
+
"require": "./dist/index.cjs.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@testing-library/dom": "^10.4.1",
|
|
24
|
+
"@testing-library/react": "^16.3.2",
|
|
25
|
+
"@types/node": "^25.2.3",
|
|
26
|
+
"@types/react": "^19.0.0",
|
|
27
|
+
"jsdom": "^28.1.0",
|
|
28
|
+
"ts-node": "^10.9.2",
|
|
29
|
+
"tsup": "^8.5.1",
|
|
30
|
+
"typescript": "^5.9.3",
|
|
31
|
+
"vitest": "^2.1.9"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"react": "^19.0.0"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -1,161 +1,161 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
createContext,
|
|
3
|
-
useCallback,
|
|
4
|
-
useContext,
|
|
5
|
-
useEffect,
|
|
6
|
-
useMemo,
|
|
7
|
-
useState
|
|
8
|
-
} from 'react';
|
|
9
|
-
|
|
10
|
-
import type {
|
|
11
|
-
ChangePasswordRequest,
|
|
12
|
-
LoginRequest,
|
|
13
|
-
SignupRequest,
|
|
14
|
-
TokenStorage,
|
|
15
|
-
User
|
|
16
|
-
} from '../type/auth.js';
|
|
17
|
-
import {
|
|
18
|
-
changePasswordRequest,
|
|
19
|
-
getMeRequest,
|
|
20
|
-
loginRequest,
|
|
21
|
-
logoutRequest,
|
|
22
|
-
signupRequest
|
|
23
|
-
} from './api/authApi.js';
|
|
24
|
-
import type { ChangeUserDataRequest } from '../type/requests.js';
|
|
25
|
-
import { updateUserRequest } from './api/userApi.js';
|
|
26
|
-
|
|
27
|
-
export type AuthContextValue = {
|
|
28
|
-
token: string | null;
|
|
29
|
-
user: User | null;
|
|
30
|
-
isLoading: boolean;
|
|
31
|
-
isError: boolean;
|
|
32
|
-
error: Error | null;
|
|
33
|
-
login: (dto: LoginRequest) => Promise<void>;
|
|
34
|
-
signup: (dto: SignupRequest) => Promise<User>;
|
|
35
|
-
changeMe: (dto: ChangeUserDataRequest) => Promise<User>;
|
|
36
|
-
changePassword: (dto: ChangePasswordRequest) => Promise<void>;
|
|
37
|
-
getMe: () => Promise<User | null>;
|
|
38
|
-
logout: () => Promise<void>;
|
|
39
|
-
getToken: () => string | null;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
type AuthProviderProps = {
|
|
43
|
-
baseUrl: string;
|
|
44
|
-
children: React.ReactNode;
|
|
45
|
-
initialToken?: string | null;
|
|
46
|
-
tokenStorage?: TokenStorage;
|
|
47
|
-
storageKey?: string;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const AuthContext = createContext<AuthContextValue | undefined>(undefined);
|
|
51
|
-
|
|
52
|
-
export const AuthProvider = ({
|
|
53
|
-
baseUrl,
|
|
54
|
-
children,
|
|
55
|
-
initialToken = null,
|
|
56
|
-
tokenStorage,
|
|
57
|
-
storageKey = 'auth_token'
|
|
58
|
-
}: AuthProviderProps) => {
|
|
59
|
-
const [token, setTokenState] = useState<string | null>(initialToken);
|
|
60
|
-
const [user, setUser] = useState<User | null>(null);
|
|
61
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
62
|
-
const [isError, setIsError] = useState(false);
|
|
63
|
-
const [error, setError] = useState<Error | null>(null);
|
|
64
|
-
|
|
65
|
-
// Load token from storage on mount
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
if (tokenStorage && !initialToken) {
|
|
68
|
-
const loadToken = async () => {
|
|
69
|
-
try {
|
|
70
|
-
const storedToken = await tokenStorage.getItem(storageKey);
|
|
71
|
-
if (storedToken) {
|
|
72
|
-
setTokenState(storedToken);
|
|
73
|
-
}
|
|
74
|
-
} catch (err) {
|
|
75
|
-
console.error('Failed to load token from storage:', err);
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
loadToken();
|
|
79
|
-
}
|
|
80
|
-
}, [tokenStorage, storageKey, initialToken]);
|
|
81
|
-
|
|
82
|
-
// Wrap setToken to persist to storage
|
|
83
|
-
const setToken = useCallback(async (newToken: string | null) => {
|
|
84
|
-
setTokenState(newToken);
|
|
85
|
-
if (tokenStorage) {
|
|
86
|
-
try {
|
|
87
|
-
if (newToken) {
|
|
88
|
-
await tokenStorage.setItem(storageKey, newToken);
|
|
89
|
-
} else {
|
|
90
|
-
await tokenStorage.removeItem(storageKey);
|
|
91
|
-
}
|
|
92
|
-
} catch (err) {
|
|
93
|
-
console.error('Failed to persist token to storage:', err);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}, [tokenStorage, storageKey]);
|
|
97
|
-
|
|
98
|
-
const getToken = useCallback(() => token, [token]);
|
|
99
|
-
|
|
100
|
-
const apiConfig = useMemo(() => ({
|
|
101
|
-
baseUrl,
|
|
102
|
-
token,
|
|
103
|
-
setToken,
|
|
104
|
-
setUser,
|
|
105
|
-
setIsLoading,
|
|
106
|
-
setIsError,
|
|
107
|
-
setError
|
|
108
|
-
}), [baseUrl, token]);
|
|
109
|
-
|
|
110
|
-
const login = useCallback((dto: LoginRequest) => loginRequest(apiConfig, dto), [apiConfig]);
|
|
111
|
-
const signup = useCallback((dto: SignupRequest) => signupRequest(apiConfig, dto), [apiConfig]);
|
|
112
|
-
const changeMe = useCallback(
|
|
113
|
-
(dto: ChangeUserDataRequest) => updateUserRequest({ ...apiConfig, setUsers: () => { }, setUser }, user!.id, dto),
|
|
114
|
-
[apiConfig, user]
|
|
115
|
-
)
|
|
116
|
-
const changePassword = useCallback(
|
|
117
|
-
(dto: ChangePasswordRequest) => changePasswordRequest(apiConfig, dto),
|
|
118
|
-
[apiConfig]
|
|
119
|
-
);
|
|
120
|
-
const getMe = useCallback(() => getMeRequest(apiConfig), [apiConfig]);
|
|
121
|
-
const logout = useCallback(() => logoutRequest(apiConfig), [apiConfig]);
|
|
122
|
-
|
|
123
|
-
const value = useMemo<AuthContextValue>(() => ({
|
|
124
|
-
token,
|
|
125
|
-
user,
|
|
126
|
-
isLoading,
|
|
127
|
-
isError,
|
|
128
|
-
error,
|
|
129
|
-
login,
|
|
130
|
-
signup,
|
|
131
|
-
changeMe,
|
|
132
|
-
changePassword,
|
|
133
|
-
getMe,
|
|
134
|
-
logout,
|
|
135
|
-
getToken
|
|
136
|
-
}), [
|
|
137
|
-
changeMe,
|
|
138
|
-
changePassword,
|
|
139
|
-
error,
|
|
140
|
-
getMe,
|
|
141
|
-
getToken,
|
|
142
|
-
isError,
|
|
143
|
-
isLoading,
|
|
144
|
-
login,
|
|
145
|
-
logout,
|
|
146
|
-
signup,
|
|
147
|
-
token,
|
|
148
|
-
user
|
|
149
|
-
]);
|
|
150
|
-
|
|
151
|
-
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
export const useAuth = (): AuthContextValue => {
|
|
155
|
-
const context = useContext(AuthContext);
|
|
156
|
-
if (!context) {
|
|
157
|
-
throw new Error('useAuth must be used within an AuthProvider');
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return context;
|
|
161
|
-
};
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
useCallback,
|
|
4
|
+
useContext,
|
|
5
|
+
useEffect,
|
|
6
|
+
useMemo,
|
|
7
|
+
useState
|
|
8
|
+
} from 'react';
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
ChangePasswordRequest,
|
|
12
|
+
LoginRequest,
|
|
13
|
+
SignupRequest,
|
|
14
|
+
TokenStorage,
|
|
15
|
+
User
|
|
16
|
+
} from '../type/auth.js';
|
|
17
|
+
import {
|
|
18
|
+
changePasswordRequest,
|
|
19
|
+
getMeRequest,
|
|
20
|
+
loginRequest,
|
|
21
|
+
logoutRequest,
|
|
22
|
+
signupRequest
|
|
23
|
+
} from './api/authApi.js';
|
|
24
|
+
import type { ChangeUserDataRequest } from '../type/requests.js';
|
|
25
|
+
import { updateUserRequest } from './api/userApi.js';
|
|
26
|
+
|
|
27
|
+
export type AuthContextValue = {
|
|
28
|
+
token: string | null;
|
|
29
|
+
user: User | null;
|
|
30
|
+
isLoading: boolean;
|
|
31
|
+
isError: boolean;
|
|
32
|
+
error: Error | null;
|
|
33
|
+
login: (dto: LoginRequest) => Promise<void>;
|
|
34
|
+
signup: (dto: SignupRequest) => Promise<User>;
|
|
35
|
+
changeMe: (dto: ChangeUserDataRequest) => Promise<User>;
|
|
36
|
+
changePassword: (dto: ChangePasswordRequest) => Promise<void>;
|
|
37
|
+
getMe: () => Promise<User | null>;
|
|
38
|
+
logout: () => Promise<void>;
|
|
39
|
+
getToken: () => string | null;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
type AuthProviderProps = {
|
|
43
|
+
baseUrl: string;
|
|
44
|
+
children: React.ReactNode;
|
|
45
|
+
initialToken?: string | null;
|
|
46
|
+
tokenStorage?: TokenStorage;
|
|
47
|
+
storageKey?: string;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const AuthContext = createContext<AuthContextValue | undefined>(undefined);
|
|
51
|
+
|
|
52
|
+
export const AuthProvider = ({
|
|
53
|
+
baseUrl,
|
|
54
|
+
children,
|
|
55
|
+
initialToken = null,
|
|
56
|
+
tokenStorage,
|
|
57
|
+
storageKey = 'auth_token'
|
|
58
|
+
}: AuthProviderProps) => {
|
|
59
|
+
const [token, setTokenState] = useState<string | null>(initialToken);
|
|
60
|
+
const [user, setUser] = useState<User | null>(null);
|
|
61
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
62
|
+
const [isError, setIsError] = useState(false);
|
|
63
|
+
const [error, setError] = useState<Error | null>(null);
|
|
64
|
+
|
|
65
|
+
// Load token from storage on mount
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (tokenStorage && !initialToken) {
|
|
68
|
+
const loadToken = async () => {
|
|
69
|
+
try {
|
|
70
|
+
const storedToken = await tokenStorage.getItem(storageKey);
|
|
71
|
+
if (storedToken) {
|
|
72
|
+
setTokenState(storedToken);
|
|
73
|
+
}
|
|
74
|
+
} catch (err) {
|
|
75
|
+
console.error('Failed to load token from storage:', err);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
loadToken();
|
|
79
|
+
}
|
|
80
|
+
}, [tokenStorage, storageKey, initialToken]);
|
|
81
|
+
|
|
82
|
+
// Wrap setToken to persist to storage
|
|
83
|
+
const setToken = useCallback(async (newToken: string | null) => {
|
|
84
|
+
setTokenState(newToken);
|
|
85
|
+
if (tokenStorage) {
|
|
86
|
+
try {
|
|
87
|
+
if (newToken) {
|
|
88
|
+
await tokenStorage.setItem(storageKey, newToken);
|
|
89
|
+
} else {
|
|
90
|
+
await tokenStorage.removeItem(storageKey);
|
|
91
|
+
}
|
|
92
|
+
} catch (err) {
|
|
93
|
+
console.error('Failed to persist token to storage:', err);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}, [tokenStorage, storageKey]);
|
|
97
|
+
|
|
98
|
+
const getToken = useCallback(() => token, [token]);
|
|
99
|
+
|
|
100
|
+
const apiConfig = useMemo(() => ({
|
|
101
|
+
baseUrl,
|
|
102
|
+
token,
|
|
103
|
+
setToken,
|
|
104
|
+
setUser,
|
|
105
|
+
setIsLoading,
|
|
106
|
+
setIsError,
|
|
107
|
+
setError
|
|
108
|
+
}), [baseUrl, token]);
|
|
109
|
+
|
|
110
|
+
const login = useCallback((dto: LoginRequest) => loginRequest(apiConfig, dto), [apiConfig]);
|
|
111
|
+
const signup = useCallback((dto: SignupRequest) => signupRequest(apiConfig, dto), [apiConfig]);
|
|
112
|
+
const changeMe = useCallback(
|
|
113
|
+
(dto: ChangeUserDataRequest) => updateUserRequest({ ...apiConfig, setUsers: () => { }, setUser }, user!.id, dto),
|
|
114
|
+
[apiConfig, user]
|
|
115
|
+
)
|
|
116
|
+
const changePassword = useCallback(
|
|
117
|
+
(dto: ChangePasswordRequest) => changePasswordRequest(apiConfig, dto),
|
|
118
|
+
[apiConfig]
|
|
119
|
+
);
|
|
120
|
+
const getMe = useCallback(() => getMeRequest(apiConfig), [apiConfig]);
|
|
121
|
+
const logout = useCallback(() => logoutRequest(apiConfig), [apiConfig]);
|
|
122
|
+
|
|
123
|
+
const value = useMemo<AuthContextValue>(() => ({
|
|
124
|
+
token,
|
|
125
|
+
user,
|
|
126
|
+
isLoading,
|
|
127
|
+
isError,
|
|
128
|
+
error,
|
|
129
|
+
login,
|
|
130
|
+
signup,
|
|
131
|
+
changeMe,
|
|
132
|
+
changePassword,
|
|
133
|
+
getMe,
|
|
134
|
+
logout,
|
|
135
|
+
getToken
|
|
136
|
+
}), [
|
|
137
|
+
changeMe,
|
|
138
|
+
changePassword,
|
|
139
|
+
error,
|
|
140
|
+
getMe,
|
|
141
|
+
getToken,
|
|
142
|
+
isError,
|
|
143
|
+
isLoading,
|
|
144
|
+
login,
|
|
145
|
+
logout,
|
|
146
|
+
signup,
|
|
147
|
+
token,
|
|
148
|
+
user
|
|
149
|
+
]);
|
|
150
|
+
|
|
151
|
+
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export const useAuth = (): AuthContextValue => {
|
|
155
|
+
const context = useContext(AuthContext);
|
|
156
|
+
if (!context) {
|
|
157
|
+
throw new Error('useAuth must be used within an AuthProvider');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return context;
|
|
161
|
+
};
|
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
createContext,
|
|
3
|
-
useCallback,
|
|
4
|
-
useContext,
|
|
5
|
-
useMemo,
|
|
6
|
-
useState
|
|
7
|
-
} from 'react';
|
|
8
|
-
|
|
9
|
-
import type { StorageMember } from '../type/models.js';
|
|
10
|
-
import { useAuth } from './AuthContext.js';
|
|
11
|
-
import {
|
|
12
|
-
acceptInviteRequest,
|
|
13
|
-
declineInviteRequest,
|
|
14
|
-
fetchInvitesRequest
|
|
15
|
-
} from './api/inviteApi.js';
|
|
16
|
-
|
|
17
|
-
type InviteContextValue = {
|
|
18
|
-
invites: StorageMember[];
|
|
19
|
-
isLoading: boolean;
|
|
20
|
-
isError: boolean;
|
|
21
|
-
error: Error | null;
|
|
22
|
-
fetchInvites: () => Promise<StorageMember[]>;
|
|
23
|
-
acceptInvite: (id: number) => Promise<void>;
|
|
24
|
-
declineInvite: (id: number) => Promise<void>;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
type InviteProviderProps = {
|
|
28
|
-
baseUrl: string;
|
|
29
|
-
children: React.ReactNode;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const InviteContext = createContext<InviteContextValue | undefined>(undefined);
|
|
33
|
-
|
|
34
|
-
export const InviteProvider = ({ baseUrl, children }: InviteProviderProps) => {
|
|
35
|
-
const { token } = useAuth();
|
|
36
|
-
const [invites, setInvites] = useState<StorageMember[]>([]);
|
|
37
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
38
|
-
const [isError, setIsError] = useState(false);
|
|
39
|
-
const [error, setError] = useState<Error | null>(null);
|
|
40
|
-
|
|
41
|
-
const apiConfig = useMemo(() => ({
|
|
42
|
-
baseUrl,
|
|
43
|
-
token,
|
|
44
|
-
setInvites,
|
|
45
|
-
setIsLoading,
|
|
46
|
-
setIsError,
|
|
47
|
-
setError
|
|
48
|
-
}), [baseUrl, token]);
|
|
49
|
-
|
|
50
|
-
const fetchInvites = useCallback(() => fetchInvitesRequest(apiConfig), [apiConfig]);
|
|
51
|
-
const acceptInvite = useCallback((id: number) => acceptInviteRequest(apiConfig, id), [apiConfig]);
|
|
52
|
-
const declineInvite = useCallback((id: number) => declineInviteRequest(apiConfig, id), [apiConfig]);
|
|
53
|
-
|
|
54
|
-
const value = useMemo<InviteContextValue>(() => ({
|
|
55
|
-
invites,
|
|
56
|
-
isLoading,
|
|
57
|
-
isError,
|
|
58
|
-
error,
|
|
59
|
-
fetchInvites,
|
|
60
|
-
acceptInvite,
|
|
61
|
-
declineInvite
|
|
62
|
-
}), [acceptInvite, declineInvite, error, fetchInvites, isError, isLoading, invites]);
|
|
63
|
-
|
|
64
|
-
return <InviteContext.Provider value={value}>{children}</InviteContext.Provider>;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
export const useInvites = (): InviteContextValue => {
|
|
68
|
-
const context = useContext(InviteContext);
|
|
69
|
-
if (!context) {
|
|
70
|
-
throw new Error('useInvites must be used within an InviteProvider');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return context;
|
|
74
|
-
};
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
useCallback,
|
|
4
|
+
useContext,
|
|
5
|
+
useMemo,
|
|
6
|
+
useState
|
|
7
|
+
} from 'react';
|
|
8
|
+
|
|
9
|
+
import type { StorageMember } from '../type/models.js';
|
|
10
|
+
import { useAuth } from './AuthContext.js';
|
|
11
|
+
import {
|
|
12
|
+
acceptInviteRequest,
|
|
13
|
+
declineInviteRequest,
|
|
14
|
+
fetchInvitesRequest
|
|
15
|
+
} from './api/inviteApi.js';
|
|
16
|
+
|
|
17
|
+
type InviteContextValue = {
|
|
18
|
+
invites: StorageMember[];
|
|
19
|
+
isLoading: boolean;
|
|
20
|
+
isError: boolean;
|
|
21
|
+
error: Error | null;
|
|
22
|
+
fetchInvites: () => Promise<StorageMember[]>;
|
|
23
|
+
acceptInvite: (id: number) => Promise<void>;
|
|
24
|
+
declineInvite: (id: number) => Promise<void>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
type InviteProviderProps = {
|
|
28
|
+
baseUrl: string;
|
|
29
|
+
children: React.ReactNode;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const InviteContext = createContext<InviteContextValue | undefined>(undefined);
|
|
33
|
+
|
|
34
|
+
export const InviteProvider = ({ baseUrl, children }: InviteProviderProps) => {
|
|
35
|
+
const { token } = useAuth();
|
|
36
|
+
const [invites, setInvites] = useState<StorageMember[]>([]);
|
|
37
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
38
|
+
const [isError, setIsError] = useState(false);
|
|
39
|
+
const [error, setError] = useState<Error | null>(null);
|
|
40
|
+
|
|
41
|
+
const apiConfig = useMemo(() => ({
|
|
42
|
+
baseUrl,
|
|
43
|
+
token,
|
|
44
|
+
setInvites,
|
|
45
|
+
setIsLoading,
|
|
46
|
+
setIsError,
|
|
47
|
+
setError
|
|
48
|
+
}), [baseUrl, token]);
|
|
49
|
+
|
|
50
|
+
const fetchInvites = useCallback(() => fetchInvitesRequest(apiConfig), [apiConfig]);
|
|
51
|
+
const acceptInvite = useCallback((id: number) => acceptInviteRequest(apiConfig, id), [apiConfig]);
|
|
52
|
+
const declineInvite = useCallback((id: number) => declineInviteRequest(apiConfig, id), [apiConfig]);
|
|
53
|
+
|
|
54
|
+
const value = useMemo<InviteContextValue>(() => ({
|
|
55
|
+
invites,
|
|
56
|
+
isLoading,
|
|
57
|
+
isError,
|
|
58
|
+
error,
|
|
59
|
+
fetchInvites,
|
|
60
|
+
acceptInvite,
|
|
61
|
+
declineInvite
|
|
62
|
+
}), [acceptInvite, declineInvite, error, fetchInvites, isError, isLoading, invites]);
|
|
63
|
+
|
|
64
|
+
return <InviteContext.Provider value={value}>{children}</InviteContext.Provider>;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const useInvites = (): InviteContextValue => {
|
|
68
|
+
const context = useContext(InviteContext);
|
|
69
|
+
if (!context) {
|
|
70
|
+
throw new Error('useInvites must be used within an InviteProvider');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return context;
|
|
74
|
+
};
|