diff --git a/apps/frontend/src/app/dashboard/login/page.tsx b/apps/frontend/src/app/dashboard/login/page.tsx new file mode 100644 index 00000000..1d2fd80f --- /dev/null +++ b/apps/frontend/src/app/dashboard/login/page.tsx @@ -0,0 +1,5 @@ +import { LoginForm } from "src/components/login/LoginForm"; + +export default async function Page() { + return ; +} diff --git a/apps/frontend/src/app/page.tsx b/apps/frontend/src/app/page.tsx index ac9edc63..aa2ab86f 100644 --- a/apps/frontend/src/app/page.tsx +++ b/apps/frontend/src/app/page.tsx @@ -2,5 +2,5 @@ import { redirect } from "next/navigation"; import { toPage } from "src/utils/next/toPage"; export default async function Page() { - redirect(toPage("dashboard")); + redirect(toPage("accounts")); } diff --git a/apps/frontend/src/components/login/LoginForm.tsx b/apps/frontend/src/components/login/LoginForm.tsx index fc3b2e5b..6e8272d5 100644 --- a/apps/frontend/src/components/login/LoginForm.tsx +++ b/apps/frontend/src/components/login/LoginForm.tsx @@ -1,12 +1,25 @@ +"use client"; + import Sheet from "@mui/joy/Sheet"; import Typography from "@mui/joy/Typography"; import FormControl from "@mui/joy/FormControl"; import FormLabel from "@mui/joy/FormLabel"; import Input from "@mui/joy/Input"; import Button from "@mui/joy/Button"; -import Link from "@mui/joy/Link"; +import { useRouter } from "next/navigation"; +import { useState } from "react"; +import { toPage } from "src/utils/next/toPage"; export function LoginForm() { + const [email, setEmail] = useState("opentrader"); + const [password, setPassword] = useState(""); + const router = useRouter(); + + const handleLogin = () => { + window.localStorage.setItem("ADMIN_PASSWORD", password); + router.replace(toPage("grid-bot")); + }; + return ( - Welcome! + Welcome Trader! Sign in to continue. - Email + Username - + setEmail(e.target.value)} + placeholder="username" + type="text" + value={email} + /> Password - + setPassword(e.target.value)} + /> - - - - - - - - Sign up} - fontSize="sm" - sx={{ - alignSelf: "center", - }} - > - Don't have an account? - ); } diff --git a/apps/frontend/src/providers/TrpcProvider.tsx b/apps/frontend/src/providers/TrpcProvider.tsx index 25e85375..fb9127a3 100644 --- a/apps/frontend/src/providers/TrpcProvider.tsx +++ b/apps/frontend/src/providers/TrpcProvider.tsx @@ -14,6 +14,9 @@ import { isTRPCError } from "src/ui/errors/utils"; import { useTRPCErrorModal } from "src/ui/errors/api"; import { tClient } from "src/lib/trpc/client"; import { getBaseUrl } from "src/lib/trpc/getBaseUrl"; +import { isUnauthorizedError } from "src/ui/errors/utils/isUnauthorizedError"; +import { isLoginPage } from "src/utils/auth/isLoginPage"; +import { toPage } from "src/utils/next/toPage"; export const TrpcProvider: React.FC<{ children: React.ReactNode }> = ({ children, @@ -26,6 +29,11 @@ export const TrpcProvider: React.FC<{ children: React.ReactNode }> = ({ queryCache: new QueryCache({ onError: (error) => { if (isTRPCError(error)) { + if (isUnauthorizedError(error) && !isLoginPage()) { + window.location.href = toPage("login"); + return; + } + showErrorModal(error); } }, diff --git a/apps/frontend/src/ui/errors/utils/isUnauthorizedError.ts b/apps/frontend/src/ui/errors/utils/isUnauthorizedError.ts new file mode 100644 index 00000000..f9b3567a --- /dev/null +++ b/apps/frontend/src/ui/errors/utils/isUnauthorizedError.ts @@ -0,0 +1,10 @@ +import { TRPC_ERROR_CODES_BY_KEY } from "@trpc/server/rpc"; +import type { TRPCApiError } from "src/ui/errors/types"; + +export function isUnauthorizedError(error: TRPCApiError) { + return ( + "code" in error.shape && + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- shape is any + error.shape.code === TRPC_ERROR_CODES_BY_KEY.UNAUTHORIZED + ); +} diff --git a/apps/frontend/src/utils/auth/isLoginPage.ts b/apps/frontend/src/utils/auth/isLoginPage.ts new file mode 100644 index 00000000..6a232032 --- /dev/null +++ b/apps/frontend/src/utils/auth/isLoginPage.ts @@ -0,0 +1,5 @@ +import { toPage } from "src/utils/next/toPage"; + +export function isLoginPage() { + return window.location.pathname === toPage("login"); +} diff --git a/apps/frontend/src/utils/next/toPage.ts b/apps/frontend/src/utils/next/toPage.ts index d5c7218b..57a754b7 100644 --- a/apps/frontend/src/utils/next/toPage.ts +++ b/apps/frontend/src/utils/next/toPage.ts @@ -1,4 +1,5 @@ const routes = { + login: "/dashboard/login", dashboard: "/dashboard", accounts: "/dashboard/accounts", "bot/:id": (botId: number) => {