diff --git a/.vscode/settings.json b/.vscode/settings.json index f9fa73f..a880bab 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -37,7 +37,8 @@ "timestamper", "tseslint", "vitest", - "xdist" + "xdist", + "Zustand's" ], "python.analysis.extraPaths": ["./backend/"], "editor.formatOnSave": true, diff --git a/frontend/src/components/auth/UserAuthForm.tsx b/frontend/src/components/auth/UserAuthForm.tsx deleted file mode 100644 index e2969bf..0000000 --- a/frontend/src/components/auth/UserAuthForm.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { Icons } from "@/components/icons"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { cn } from "@/lib/utils"; -import { HTMLAttributes, useState } from "react"; - -interface UserAuthFormProps extends HTMLAttributes {} - -export function UserAuthForm({ className, ...props }: UserAuthFormProps) { - const [isLoading, setIsLoading] = useState(false); - - async function onSubmit(event: React.SyntheticEvent) { - event.preventDefault(); - setIsLoading(true); - - setTimeout(() => { - setIsLoading(false); - }, 3000); - } - - return ( -
-
-
-
- - -
- -
-
-
-
- -
-
- - Or continue with - -
-
- -
- ); -} diff --git a/frontend/src/components/auth/form.tsx b/frontend/src/components/auth/form.tsx new file mode 100644 index 0000000..fb09104 --- /dev/null +++ b/frontend/src/components/auth/form.tsx @@ -0,0 +1,108 @@ +import { Icons } from "@/components/icons"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { cn } from "@/lib/utils"; +import { Link } from "@tanstack/react-router"; +import { HTMLAttributes, useState } from "react"; + +interface UserAuthFormProps extends HTMLAttributes {} + +export function RegisterForm({ className, ...props }: UserAuthFormProps) { + const [isLoading, setIsLoading] = useState(false); + + async function onSubmit(event: React.SyntheticEvent) { + event.preventDefault(); + setIsLoading(true); + + setTimeout(() => { + setIsLoading(false); + }, 3000); + } + + return ( +
+
+
+
+ + +
+ +
+
+
+ ); +} + +export function LoginForm({ className, ...props }: UserAuthFormProps) { + const [isLoading, setIsLoading] = useState(false); + + async function onSubmit(event: React.SyntheticEvent) { + event.preventDefault(); + setIsLoading(true); + + setTimeout(() => { + setIsLoading(false); + }, 3000); + } + + return ( +
+
+
+
+ + +
+ +
+
+

+ + Register + {" "} + or{" "} + + Forgot Password + +

+
+ ); +} diff --git a/frontend/src/components/pages/authentication.tsx b/frontend/src/components/pages/authentication.tsx new file mode 100644 index 0000000..dea7caf --- /dev/null +++ b/frontend/src/components/pages/authentication.tsx @@ -0,0 +1,67 @@ +import { Icons } from "@/components/icons"; +import { buttonVariants } from "@/components/ui/button"; +import { cn } from "@/lib/utils"; +import { Link } from "@tanstack/react-router"; +import { ReactNode } from "react"; + +export function AgreementText() { + return ( +

+ By clicking continue, you agree to our{" "} + + Terms of Service + {" "} + and{" "} + + Privacy Policy + + . +

+ ); +} + +export default function AuthenticationPage({ + children, +}: { + children: ReactNode; +}) { + return ( +
+ + Linkpulse + +
+
+
+ + Linkpulse +
+
+ {/*
+

+ “This library has saved me countless hours of work and + helped me deliver stunning designs to my clients faster than + ever before.” +

+
Sofia Davis
+
*/} + {/*

+
*/} +
+
+
{children}
+
+ ); +} diff --git a/frontend/src/routeTree.gen.ts b/frontend/src/routeTree.gen.ts index d5d7791..36868a8 100644 --- a/frontend/src/routeTree.gen.ts +++ b/frontend/src/routeTree.gen.ts @@ -13,6 +13,7 @@ import { createFileRoute } from '@tanstack/react-router' // Import Routes import { Route as rootRoute } from './routes/__root' +import { Route as RegisterImport } from './routes/register' import { Route as LoginImport } from './routes/login' import { Route as DashboardImport } from './routes/dashboard' @@ -22,6 +23,12 @@ const IndexLazyImport = createFileRoute('/')() // Create/Update Routes +const RegisterRoute = RegisterImport.update({ + id: '/register', + path: '/register', + getParentRoute: () => rootRoute, +} as any) + const LoginRoute = LoginImport.update({ id: '/login', path: '/login', @@ -65,6 +72,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof LoginImport parentRoute: typeof rootRoute } + '/register': { + id: '/register' + path: '/register' + fullPath: '/register' + preLoaderRoute: typeof RegisterImport + parentRoute: typeof rootRoute + } } } @@ -74,12 +88,14 @@ export interface FileRoutesByFullPath { '/': typeof IndexLazyRoute '/dashboard': typeof DashboardRoute '/login': typeof LoginRoute + '/register': typeof RegisterRoute } export interface FileRoutesByTo { '/': typeof IndexLazyRoute '/dashboard': typeof DashboardRoute '/login': typeof LoginRoute + '/register': typeof RegisterRoute } export interface FileRoutesById { @@ -87,14 +103,15 @@ export interface FileRoutesById { '/': typeof IndexLazyRoute '/dashboard': typeof DashboardRoute '/login': typeof LoginRoute + '/register': typeof RegisterRoute } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath - fullPaths: '/' | '/dashboard' | '/login' + fullPaths: '/' | '/dashboard' | '/login' | '/register' fileRoutesByTo: FileRoutesByTo - to: '/' | '/dashboard' | '/login' - id: '__root__' | '/' | '/dashboard' | '/login' + to: '/' | '/dashboard' | '/login' | '/register' + id: '__root__' | '/' | '/dashboard' | '/login' | '/register' fileRoutesById: FileRoutesById } @@ -102,12 +119,14 @@ export interface RootRouteChildren { IndexLazyRoute: typeof IndexLazyRoute DashboardRoute: typeof DashboardRoute LoginRoute: typeof LoginRoute + RegisterRoute: typeof RegisterRoute } const rootRouteChildren: RootRouteChildren = { IndexLazyRoute: IndexLazyRoute, DashboardRoute: DashboardRoute, LoginRoute: LoginRoute, + RegisterRoute: RegisterRoute, } export const routeTree = rootRoute @@ -122,7 +141,8 @@ export const routeTree = rootRoute "children": [ "/", "/dashboard", - "/login" + "/login", + "/register" ] }, "/": { @@ -133,6 +153,9 @@ export const routeTree = rootRoute }, "/login": { "filePath": "login.tsx" + }, + "/register": { + "filePath": "register.tsx" } } } diff --git a/frontend/src/routes/login.tsx b/frontend/src/routes/login.tsx index 146803e..96eb277 100644 --- a/frontend/src/routes/login.tsx +++ b/frontend/src/routes/login.tsx @@ -1,10 +1,8 @@ -import { createFileRoute, redirect } from "@tanstack/react-router"; import { useUserStore } from "@/lib/state"; +import { createFileRoute, redirect } from "@tanstack/react-router"; -import { buttonVariants } from "@/components/ui/button"; -import { cn } from "@/lib/utils"; -import { UserAuthForm } from "@/components/auth/UserAuthForm"; -import { Icons } from "@/components/icons"; +import { LoginForm } from "@/components/auth/form"; +import AuthenticationPage from "@/components/pages/authentication"; export const Route = createFileRoute("/login")({ beforeLoad: async ({ location }) => { @@ -22,67 +20,16 @@ export const Route = createFileRoute("/login")({ function Login() { return ( - <> -
- - Linkpulse - -
-
-
- - Linkpulse -
-
- {/*
-

- “This library has saved me countless hours of work and - helped me deliver stunning designs to my clients faster than - ever before.” -

-
Sofia Davis
-
*/} - {/*

-
*/} -
-
-
-
-
-

- Create an account -

-

- Enter your email below to create your account -

-
- -

- By clicking continue, you agree to our{" "} - - Terms of Service - {" "} - and{" "} - - Privacy Policy - - . -

-
+ +
+
+

Login

+

+ Enter your email below to login +

+
- +
); } diff --git a/frontend/src/routes/register.tsx b/frontend/src/routes/register.tsx new file mode 100644 index 0000000..60e90dd --- /dev/null +++ b/frontend/src/routes/register.tsx @@ -0,0 +1,40 @@ +import { useUserStore } from "@/lib/state"; +import { createFileRoute, redirect } from "@tanstack/react-router"; + +import { RegisterForm } from "@/components/auth/form"; +import AuthenticationPage, { + AgreementText, +} from "@/components/pages/authentication"; + +export const Route = createFileRoute("/register")({ + beforeLoad: async ({ location }) => { + const isLoggedIn = useUserStore.getState().user !== null; + + if (isLoggedIn) { + return redirect({ + to: "/dashboard", + search: { redirect: location.href }, + }); + } + }, + component: Register, +}); + +function Register() { + return ( + +
+
+

+ Create an account +

+

+ Enter your email below to create your account +

+
+ + +
+
+ ); +}