first commit
This commit is contained in:
33
apps/Frontend/src/lib/protected-route.tsx
Normal file
33
apps/Frontend/src/lib/protected-route.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import { useAuth } from "../hooks/use-auth";
|
||||
import { Loader2 } from "lucide-react";
|
||||
import { Redirect, Route } from "wouter";
|
||||
|
||||
export function ProtectedRoute({
|
||||
path,
|
||||
component: Component,
|
||||
}: {
|
||||
path: string;
|
||||
component: () => React.JSX.Element;
|
||||
}) {
|
||||
const { user, isLoading } = useAuth();
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<Route path={path}>
|
||||
<div className="flex items-center justify-center min-h-screen">
|
||||
<Loader2 className="h-8 w-8 animate-spin text-border" />
|
||||
</div>
|
||||
</Route>
|
||||
);
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
return (
|
||||
<Route path={path}>
|
||||
<Redirect to="/auth" />
|
||||
</Route>
|
||||
);
|
||||
}
|
||||
|
||||
return <Route path={path} component={Component} />;
|
||||
}
|
||||
57
apps/Frontend/src/lib/queryClient.ts
Normal file
57
apps/Frontend/src/lib/queryClient.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { QueryClient, QueryFunction } from "@tanstack/react-query";
|
||||
|
||||
async function throwIfResNotOk(res: Response) {
|
||||
if (!res.ok) {
|
||||
const text = (await res.text()) || res.statusText;
|
||||
throw new Error(`${res.status}: ${text}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function apiRequest(
|
||||
method: string,
|
||||
url: string,
|
||||
data?: unknown | undefined,
|
||||
): Promise<Response> {
|
||||
const res = await fetch(url, {
|
||||
method,
|
||||
headers: data ? { "Content-Type": "application/json" } : {},
|
||||
body: data ? JSON.stringify(data) : undefined,
|
||||
credentials: "include",
|
||||
});
|
||||
|
||||
await throwIfResNotOk(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
type UnauthorizedBehavior = "returnNull" | "throw";
|
||||
export const getQueryFn: <T>(options: {
|
||||
on401: UnauthorizedBehavior;
|
||||
}) => QueryFunction<T> =
|
||||
({ on401: unauthorizedBehavior }) =>
|
||||
async ({ queryKey }) => {
|
||||
const res = await fetch(queryKey[0] as string, {
|
||||
credentials: "include",
|
||||
});
|
||||
|
||||
if (unauthorizedBehavior === "returnNull" && res.status === 401) {
|
||||
return null;
|
||||
}
|
||||
|
||||
await throwIfResNotOk(res);
|
||||
return await res.json();
|
||||
};
|
||||
|
||||
export const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
queryFn: getQueryFn({ on401: "throw" }),
|
||||
refetchInterval: false,
|
||||
refetchOnWindowFocus: false,
|
||||
staleTime: Infinity,
|
||||
retry: false,
|
||||
},
|
||||
mutations: {
|
||||
retry: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
6
apps/Frontend/src/lib/utils.ts
Normal file
6
apps/Frontend/src/lib/utils.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
Reference in New Issue
Block a user