This commit is contained in:
2025-11-22 18:19:55 +01:00
parent d3c76bc303
commit 014f489857
7 changed files with 124 additions and 141 deletions
+45
View File
@@ -0,0 +1,45 @@
import React, { createContext, useContext, useEffect, useMemo } from 'react';
import type { PropsWithChildren } from 'react';
import { httpClient, setAuthToken, clearAuthToken } from '../lib/apiClient';
type HttpClient = typeof httpClient;
interface ApiContextValue {
client: HttpClient;
setAuthToken: (token?: string | null) => void;
clearAuthToken: () => void;
}
const ApiContext = createContext<ApiContextValue | null>(null);
export const ApiProvider: React.FC<PropsWithChildren<{ initialToken?: string | null }>> = ({
initialToken = null,
children,
}) => {
useEffect(() => {
if (initialToken) {
setAuthToken(initialToken);
}
}, [initialToken]);
const value = useMemo<ApiContextValue>(
() => ({
client: httpClient,
setAuthToken,
clearAuthToken,
}),
[],
);
return <ApiContext.Provider value={value}>{children}</ApiContext.Provider>;
};
export const useApi = (): ApiContextValue => {
const ctx = useContext(ApiContext);
if (!ctx) {
throw new Error('useApi must be used within an ApiProvider');
}
return ctx;
};
export const getHttpClient = (): HttpClient => httpClient;
+13 -10
View File
@@ -1,5 +1,6 @@
import React, { useContext, useEffect, useMemo, useReducer } from 'react';
import api from '../lib/api';
import { clearAuthToken, setAuthToken } from '../lib/apiClient';
import { ApiProvider } from './ApiContext';
import { listTenants } from '../lib/apiClient';
type Tenant = Record<string, unknown> | null;
@@ -61,7 +62,7 @@ if (storage) {
}
if (STORED_TOKEN) {
api.defaults.headers.common.Authorization = `Bearer ${STORED_TOKEN}`;
setAuthToken(STORED_TOKEN);
}
const initialAppState: AppState = {
@@ -188,10 +189,10 @@ const AppStateProvider: React.FC<{ children?: React.ReactNode }> = ({ children }
useEffect(() => {
const token = state.token ?? '';
if (token) {
api.defaults.headers.common.Authorization = `Bearer ${token}`;
setAuthToken(token);
storage?.setItem('papercrate_token', token);
} else {
delete api.defaults.headers.common.Authorization;
clearAuthToken();
storage?.removeItem('papercrate_token');
}
}, [state.token]);
@@ -242,11 +243,13 @@ const AppStateProvider: React.FC<{ children?: React.ReactNode }> = ({ children }
const stateValue = useMemo(() => state, [state]);
return (
<AppStateContext.Provider value={stateValue}>
<AppDispatchContext.Provider value={dispatch}>
{children}
</AppDispatchContext.Provider>
</AppStateContext.Provider>
<ApiProvider initialToken={state.token}>
<AppStateContext.Provider value={stateValue}>
<AppDispatchContext.Provider value={dispatch}>
{children}
</AppDispatchContext.Provider>
</AppStateContext.Provider>
</ApiProvider>
);
};
@@ -266,4 +269,4 @@ const useAppDispatch = (): React.Dispatch<AppAction> => {
return context;
};
export { api, AppStateProvider, useAppState, useAppDispatch };
export { AppStateProvider, useAppState, useAppDispatch };