This commit is contained in:
2025-09-03 12:19:38 -03:00
commit 08a5e16e4b
83 changed files with 12223 additions and 0 deletions

View File

@@ -0,0 +1,67 @@
import Header from "@/components/header";
import Loader from "@/components/loader";
import { ThemeProvider } from "@/components/theme-provider";
import { Toaster } from "@/components/ui/sonner";
import type { trpc } from "@/utils/trpc";
import type { QueryClient } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import {
HeadContent,
Outlet,
createRootRouteWithContext,
useRouterState,
} from "@tanstack/react-router";
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
import "../index.css";
export interface RouterAppContext {
trpc: typeof trpc;
queryClient: QueryClient;
}
export const Route = createRootRouteWithContext<RouterAppContext>()({
component: RootComponent,
head: () => ({
meta: [
{
title: "Reflecto",
},
{
name: "description",
content: "Reflecto is a web application",
},
],
links: [
{
rel: "icon",
href: "/favicon.ico",
},
],
}),
});
function RootComponent() {
const isFetching = useRouterState({
select: (s) => s.isLoading,
});
return (
<>
<HeadContent />
<ThemeProvider
attribute="class"
defaultTheme="dark"
disableTransitionOnChange
storageKey="vite-ui-theme"
>
<div className="grid grid-rows-[auto_1fr] h-svh">
<Header />
{isFetching ? <Loader /> : <Outlet />}
</div>
<Toaster richColors />
</ThemeProvider>
<TanStackRouterDevtools position="bottom-left" />
<ReactQueryDevtools position="bottom" buttonPosition="bottom-right" />
</>
);
}

View File

@@ -0,0 +1,37 @@
import { authClient } from "@/lib/auth-client";
import { trpc } from "@/utils/trpc";
import { useQuery } from "@tanstack/react-query";
import { createFileRoute } from "@tanstack/react-router";
import { useEffect } from "react";
export const Route = createFileRoute("/dashboard")({
component: RouteComponent,
});
function RouteComponent() {
const { data: session, isPending } = authClient.useSession();
const navigate = Route.useNavigate();
const privateData = useQuery(trpc.privateData.queryOptions());
useEffect(() => {
if (!session && !isPending) {
navigate({
to: "/login",
});
}
}, [session, isPending]);
if (isPending) {
return <div>Loading...</div>;
}
return (
<div>
<h1>Dashboard</h1>
<p>Welcome {session?.user.name}</p>
<p>privateData: {privateData.data?.message}</p>
</div>
);
}

View File

@@ -0,0 +1,50 @@
import { createFileRoute } from "@tanstack/react-router";
import { trpc } from "@/utils/trpc";
import { useQuery } from "@tanstack/react-query";
export const Route = createFileRoute("/")({
component: HomeComponent,
});
const TITLE_TEXT = `
██████╗ ███████╗████████╗████████╗███████╗██████╗
██╔══██╗██╔════╝╚══██╔══╝╚══██╔══╝██╔════╝██╔══██╗
██████╔╝█████╗ ██║ ██║ █████╗ ██████╔╝
██╔══██╗██╔══╝ ██║ ██║ ██╔══╝ ██╔══██╗
██████╔╝███████╗ ██║ ██║ ███████╗██║ ██║
╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝
████████╗ ███████╗████████╗ █████╗ ██████╗██╗ ██╗
╚══██╔══╝ ██╔════╝╚══██╔══╝██╔══██╗██╔════╝██║ ██╔╝
██║ ███████╗ ██║ ███████║██║ █████╔╝
██║ ╚════██║ ██║ ██╔══██║██║ ██╔═██╗
██║ ███████║ ██║ ██║ ██║╚██████╗██║ ██╗
╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
`;
function HomeComponent() {
const healthCheck = useQuery(trpc.healthCheck.queryOptions());
return (
<div className="container mx-auto max-w-3xl px-4 py-2">
<pre className="overflow-x-auto font-mono text-sm">{TITLE_TEXT}</pre>
<div className="grid gap-6">
<section className="rounded-lg border p-4">
<h2 className="mb-2 font-medium">API Status</h2>
<div className="flex items-center gap-2">
<div
className={`h-2 w-2 rounded-full ${healthCheck.data ? "bg-green-500" : "bg-red-500"}`}
/>
<span className="text-sm text-muted-foreground">
{healthCheck.isLoading
? "Checking..."
: healthCheck.data
? "Connected"
: "Disconnected"}
</span>
</div>
</section>
</div>
</div>
);
}

View File

@@ -0,0 +1,18 @@
import SignInForm from "@/components/sign-in-form";
import SignUpForm from "@/components/sign-up-form";
import { createFileRoute } from "@tanstack/react-router";
import { useState } from "react";
export const Route = createFileRoute("/login")({
component: RouteComponent,
});
function RouteComponent() {
const [showSignIn, setShowSignIn] = useState(false);
return showSignIn ? (
<SignInForm onSwitchToSignUp={() => setShowSignIn(false)} />
) : (
<SignUpForm onSwitchToSignIn={() => setShowSignIn(true)} />
);
}