feat: implement authentication and health check providers with hooks for user management
This commit is contained in:
56
apps/frontend/app/providers/ApiHealthProvider.tsx
Normal file
56
apps/frontend/app/providers/ApiHealthProvider.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import { useNavigate } from 'react-router';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { createContext, use, type PropsWithChildren } from 'react';
|
||||
import { useApi } from './ApiProvider';
|
||||
import { useResponseErrorHandler } from '../hooks/ResponseHelper';
|
||||
import type { Schemas } from '../generated/api-client/api-client';
|
||||
|
||||
export type HealthStatus = Schemas.HealthInfo;
|
||||
|
||||
export type ApiHealthProviderProps = PropsWithChildren<object>;
|
||||
export type ApiHealthContextType = {
|
||||
healthStatus: HealthStatus | undefined;
|
||||
};
|
||||
|
||||
const ApiHealthContext = createContext<ApiHealthContextType | null>(null);
|
||||
|
||||
export const ApiHealthProvider: React.FC<ApiHealthProviderProps> = ({ children }) => {
|
||||
const navigate = useNavigate();
|
||||
const { tanstackApiClient } = useApi();
|
||||
const { defaultResponseErrorHandler } = useResponseErrorHandler();
|
||||
|
||||
const { queryOptions: healthInfoQuery } = tanstackApiClient.get('/api/health/info');
|
||||
const { data } = useQuery({
|
||||
...healthInfoQuery,
|
||||
queryFn: async (...args) => {
|
||||
try {
|
||||
const data = await healthInfoQuery.queryFn!(...args);
|
||||
if (!data.is_initialized) {
|
||||
navigate('/init');
|
||||
}
|
||||
return data;
|
||||
} catch (error) {
|
||||
if (defaultResponseErrorHandler(error)) return {} as never;
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<ApiHealthContext
|
||||
value={{
|
||||
healthStatus: data,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</ApiHealthContext>
|
||||
);
|
||||
};
|
||||
|
||||
export const useApiHealth = (): ApiHealthContextType => {
|
||||
const context = use(ApiHealthContext);
|
||||
if (!context) {
|
||||
throw new Error('useApiHealth must be used within an ApiHealthProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
@@ -2,7 +2,6 @@ import { createContext, use, type PropsWithChildren } from 'react';
|
||||
import { createTanstackApi, createApi } from '../lib/api';
|
||||
import axios from 'axios';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
type ApiProviderProps = PropsWithChildren<object>;
|
||||
type ApiContextType = {
|
||||
|
||||
47
apps/frontend/app/providers/AuthProvider.tsx
Normal file
47
apps/frontend/app/providers/AuthProvider.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { createContext, use, useCallback, useState, type PropsWithChildren } from 'react';
|
||||
|
||||
export type User = {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type AuthProviderProps = PropsWithChildren<object>;
|
||||
export type AuthContextType = {
|
||||
setUser: (user: User) => void;
|
||||
logOut: () => void;
|
||||
user: User | null;
|
||||
};
|
||||
|
||||
const AuthContext = createContext<AuthContextType | null>(null);
|
||||
|
||||
export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
|
||||
const [user, setUserState] = useState<User | null>(null);
|
||||
|
||||
const setUser = useCallback((user: User) => {
|
||||
setUserState(user);
|
||||
}, []);
|
||||
|
||||
const logout = useCallback(() => {
|
||||
setUserState(null);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AuthContext
|
||||
value={{
|
||||
user: user,
|
||||
logOut: logout,
|
||||
setUser: setUser,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</AuthContext>
|
||||
);
|
||||
};
|
||||
|
||||
export function useAuth() {
|
||||
const context = use(AuthContext);
|
||||
if (!context) {
|
||||
throw new Error('useAuth must be used within a AuthProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
Reference in New Issue
Block a user