74 lines
1.9 KiB
TypeScript
74 lines
1.9 KiB
TypeScript
import { createContext, PropsWithChildren, useCallback, useContext, useMemo } from "react";
|
|
import { MantineColor, MantineColorScheme } from "@mantine/core";
|
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
import { fetchMe } from "@/features/players/server";
|
|
|
|
const queryKey = ['auth'];
|
|
export const authQueryConfig = {
|
|
queryKey,
|
|
queryFn: fetchMe
|
|
}
|
|
|
|
interface AuthData {
|
|
user: any;
|
|
metadata: { accentColor: MantineColor; colorScheme: MantineColorScheme };
|
|
roles: string[];
|
|
}
|
|
|
|
export const defaultAuthData: AuthData = {
|
|
user: undefined,
|
|
metadata: { accentColor: 'blue', colorScheme: 'auto' },
|
|
roles: [],
|
|
}
|
|
|
|
export interface AuthContextType extends AuthData {
|
|
set: ({ user, metadata, roles }: Partial<AuthContextType>) => void;
|
|
}
|
|
|
|
const AuthContext = createContext<AuthContextType>({
|
|
...defaultAuthData,
|
|
set: () => {},
|
|
});
|
|
|
|
export const AuthProvider: React.FC<PropsWithChildren> = ({ children }) => {
|
|
const queryClient = useQueryClient();
|
|
const { data, isLoading } = useQuery<AuthData>(authQueryConfig);
|
|
|
|
const set = useCallback((updates: Partial<AuthData>) => {
|
|
queryClient.setQueryData(queryKey, (oldData: AuthData | undefined) => {
|
|
const currentData = oldData || defaultAuthData;
|
|
return {
|
|
...currentData,
|
|
...updates,
|
|
metadata: updates.metadata
|
|
? { ...currentData.metadata, ...updates.metadata }
|
|
: currentData.metadata
|
|
};
|
|
});
|
|
}, [queryClient]);
|
|
|
|
if (isLoading) {
|
|
return <p>Loading...</p>
|
|
}
|
|
|
|
return (
|
|
<AuthContext
|
|
value={{
|
|
user: data?.user || defaultAuthData.user,
|
|
metadata: data?.metadata || defaultAuthData.metadata,
|
|
roles: data?.roles || defaultAuthData.roles,
|
|
set
|
|
}}>
|
|
{children}
|
|
</AuthContext>
|
|
)
|
|
};
|
|
|
|
export const useAuth = () => {
|
|
const context = useContext(AuthContext);
|
|
if (!context) {
|
|
throw new Error('useAuth must be used within an AuthProvider');
|
|
}
|
|
return context;
|
|
};
|