diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index fda6f7c..72b9238 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,5 +1,12 @@ import { Navigate } from "react-router"; +import { useUserContext } from "./context/user-context"; export const App = () => { + const { isLoggedIn } = useUserContext(); + + if (isLoggedIn) { + return ; + } + return ; }; diff --git a/frontend/src/components/ui/code.tsx b/frontend/src/components/ui/code.tsx deleted file mode 100644 index a4bc8cb..0000000 --- a/frontend/src/components/ui/code.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { twMerge } from "tailwind-merge"; - -interface CodeProps extends React.ComponentPropsWithoutRef<"code"> { - children?: React.ReactNode; - className?: string; -} - -function Code({ children, className, ...props }: CodeProps) { - return ( - - {children} - - ); -} - -export { Code }; diff --git a/frontend/src/context/app-context.tsx b/frontend/src/context/app-context.tsx index 347a06a..b8044f6 100644 --- a/frontend/src/context/app-context.tsx +++ b/frontend/src/context/app-context.tsx @@ -1,6 +1,6 @@ import { AppContextSchema } from "@/schemas/app-context-schema"; import { createContext, useContext } from "react"; -import { useQuery } from "@tanstack/react-query"; +import { useSuspenseQuery } from "@tanstack/react-query"; import axios from "axios"; const AppContext = createContext(null); @@ -10,16 +10,12 @@ export const AppContextProvider = ({ }: { children: React.ReactNode; }) => { - const { isPending, isError, data, error } = useQuery({ - queryKey: ["status"], + const { isFetching, data, error } = useSuspenseQuery({ + queryKey: ["app"], queryFn: () => axios.get("/api/app").then((res) => res.data), }); - if (isPending) { - return; - } - - if (isError) { + if (error && !isFetching) { throw error; } diff --git a/frontend/src/context/user-context.tsx b/frontend/src/context/user-context.tsx new file mode 100644 index 0000000..84130d6 --- /dev/null +++ b/frontend/src/context/user-context.tsx @@ -0,0 +1,35 @@ +import { UserContextSchema } from "@/schemas/user-context-schema"; +import { createContext, useContext } from "react"; +import { useSuspenseQuery } from "@tanstack/react-query"; +import axios from "axios"; + +const UserContext = createContext(null); + +export const UserContextProvider = ({ + children, +}: { + children: React.ReactNode; +}) => { + const { isFetching, data, error } = useSuspenseQuery({ + queryKey: ["user"], + queryFn: () => axios.get("/api/user").then((res) => res.data), + }); + + if (error && !isFetching) { + throw error; + } + + return {children}; +}; + +export const useUserContext = () => { + const context = useContext(UserContext); + + if (!context) { + throw new Error( + "useUserContext must be used within an UserContextProvider", + ); + } + + return context; +}; diff --git a/frontend/src/index.css b/frontend/src/index.css index f4c1e9b..c80b837 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -118,3 +118,59 @@ @apply bg-background text-foreground; } } + +h1 { + @apply scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl; +} + +h2 { + @apply scroll-m-20 border-b pb-2 text-3xl font-semibold tracking-tight first:mt-0; +} + +h3 { + @apply scroll-m-20 text-2xl font-semibold tracking-tight; +} + +h4 { + @apply scroll-m-20 text-xl font-semibold tracking-tight; +} + +p { + @apply leading-7 [&:not(:first-child)]:mt-6; +} + +blockquote { + @apply mt-6 border-l-2 pl-6 italic; +} + +tr { + @apply m-0 border-t p-0 even:bg-muted; +} + +th { + @apply border px-4 py-2 text-left font-bold [&[align=center]]:text-center [&[align=right]]:text-right; +} + +ul { + @apply my-6 ml-6 list-disc [&>li]:mt-2; +} + +code { + @apply relative rounded bg-muted px-[0.2rem] py-[0.1rem] font-mono text-sm font-semibold; +} + +.lead { + @apply text-xl text-muted-foreground; +} + +.large { + @apply text-lg font-semibold; +} + +small { + @apply text-sm font-medium leading-none; +} + +.muted { + @apply text-sm text-muted-foreground; +} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index edf6c55..3d114db 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -14,6 +14,7 @@ import { LogoutPage } from "./pages/logout-page.tsx"; import { UnauthorizedPage } from "./pages/unauthorized-page.tsx"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { AppContextProvider } from "./context/app-context.tsx"; +import { UserContextProvider } from "./context/user-context.tsx"; const router = createBrowserRouter([ { @@ -64,9 +65,11 @@ createRoot(document.getElementById("root")!).render( - - - + + + + + , diff --git a/frontend/src/pages/continue-page.tsx b/frontend/src/pages/continue-page.tsx index 323bd5f..2baf89b 100644 --- a/frontend/src/pages/continue-page.tsx +++ b/frontend/src/pages/continue-page.tsx @@ -6,8 +6,8 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; -import { Code } from "@/components/ui/code"; import { useAppContext } from "@/context/app-context"; +import { useUserContext } from "@/context/user-context"; import { isValidUrl } from "@/lib/utils"; import { Trans, useTranslation } from "react-i18next"; import { Navigate, useNavigate } from "react-router"; @@ -16,11 +16,16 @@ export const ContinuePage = () => { const params = new URLSearchParams(window.location.search); const redirectURI = params.get("redirect_uri"); + const { isLoggedIn } = useUserContext(); const { domain, disableContinue } = useAppContext(); const { t } = useTranslation(); const navigate = useNavigate(); + if (!isLoggedIn) { + return ; + } + if (!redirectURI) { return ; } @@ -37,7 +42,7 @@ export const ContinuePage = () => { if (!url.hostname.includes(domain)) { return ( - + {t("untrustedRedirectTitle")} @@ -47,7 +52,7 @@ export const ContinuePage = () => { i18nKey="untrustedRedirectSubtitle" t={t} components={{ - code: , + code: , }} values={{ domain }} /> @@ -70,7 +75,7 @@ export const ContinuePage = () => { if (url.protocol === "http:" && window.location.protocol === "https:") { return ( - + {t("continueInsecureRedirectTitle")} @@ -80,7 +85,7 @@ export const ContinuePage = () => { i18nKey="continueInsecureRedirectSubtitle" t={t} components={{ - code: , + code: , }} /> diff --git a/frontend/src/pages/login-page.tsx b/frontend/src/pages/login-page.tsx index 1278226..cb1b6c2 100644 --- a/frontend/src/pages/login-page.tsx +++ b/frontend/src/pages/login-page.tsx @@ -16,6 +16,8 @@ import { useTranslation } from "react-i18next"; export const LoginPage = () => { const { configuredProviders, title } = useAppContext(); + + console.log("Configured providers:", configuredProviders); const { t } = useTranslation(); const oauthConfigured = diff --git a/frontend/src/pages/logout-page.tsx b/frontend/src/pages/logout-page.tsx index 2e65e54..26229a1 100644 --- a/frontend/src/pages/logout-page.tsx +++ b/frontend/src/pages/logout-page.tsx @@ -6,18 +6,20 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; -import { Code } from "@/components/ui/code"; import { useAppContext } from "@/context/app-context"; +import { useUserContext } from "@/context/user-context"; import { capitalize } from "@/lib/utils"; import { Trans, useTranslation } from "react-i18next"; +import { Navigate } from "react-router"; export const LogoutPage = () => { + const { provider, username, email, isLoggedIn } = useUserContext(); const { genericName } = useAppContext(); const { t } = useTranslation(); - const provider = "google"; - const username = "username"; - const email = "smbd@example.com"; + if (!isLoggedIn) { + return ; + } return ( @@ -29,7 +31,7 @@ export const LogoutPage = () => { i18nKey="logoutOauthSubtitle" t={t} components={{ - code: , + code: , }} values={{ username: email, @@ -42,7 +44,7 @@ export const LogoutPage = () => { i18nKey="logoutUsernameSubtitle" t={t} components={{ - code: , + code: , }} values={{ username: username, diff --git a/frontend/src/pages/unauthorized-page.tsx b/frontend/src/pages/unauthorized-page.tsx index fc4c484..22b4f32 100644 --- a/frontend/src/pages/unauthorized-page.tsx +++ b/frontend/src/pages/unauthorized-page.tsx @@ -6,7 +6,6 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; -import { Code } from "@/components/ui/code"; import { Trans, useTranslation } from "react-i18next"; import { Navigate, useNavigate } from "react-router"; @@ -42,7 +41,7 @@ export const UnauthorizedPage = () => { i18nKey={i18nKey} t={t} components={{ - code: , + code: , }} values={{ username: username,