diff --git a/apps/web/app/routes/auth/login.tsx b/apps/web/app/routes/auth/login.tsx index 9c7afd1de..c11a67cf6 100644 --- a/apps/web/app/routes/auth/login.tsx +++ b/apps/web/app/routes/auth/login.tsx @@ -1,5 +1,9 @@ "use client"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; + import { authClient } from "~/api/auth-client"; import { Button } from "~/components/ui/button"; import { @@ -9,14 +13,104 @@ import { CardHeader, CardTitle, } from "~/components/ui/card"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "~/components/ui/form"; +import { Input } from "~/components/ui/input"; +import { Separator } from "~/components/ui/separator"; const signInGoogle = () => { void authClient.signIn.social({ provider: "google" }); }; +function LoginSeparator() { + return ( +
+ + or + +
+ ); +} + +const signInEmailPasswordSchema = z.object({ + email: z.string().email(), + password: z.string(), +}); + +function LoginEmailPassword() { + const form = useForm>({ + resolver: zodResolver(signInEmailPasswordSchema), + defaultValues: { + email: "", + password: "", + }, + }); + + const onSubmit = (data: z.infer) => { + void authClient.signIn.email({ + ...data, + rememberMe: true, + callbackURL: "/workspaces", + }); + }; + + return ( +
+ + ( + + Email + + + + + + )} + /> + ( + + Password + + + + + + )} + /> +
+ + + Don't have an account?{" "} + + Sign up + + +
+ + + ); +} + export default function Login() { return ( -
+
{/* Logo */}
@@ -75,6 +169,8 @@ export default function Login() { Continue with Google + +
diff --git a/apps/web/app/routes/auth/signup.tsx b/apps/web/app/routes/auth/signup.tsx index 9bb3734da..dfe06f3bf 100644 --- a/apps/web/app/routes/auth/signup.tsx +++ b/apps/web/app/routes/auth/signup.tsx @@ -1,3 +1,143 @@ +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; + +import { authClient } from "~/api/auth-client"; +import { Button } from "~/components/ui/button"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "~/components/ui/card"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "~/components/ui/form"; +import { Input } from "~/components/ui/input"; + +const signUpSchema = z.object({ + name: z.string().min(1, "Name is required"), + email: z.string().email("Invalid email address"), + password: z.string().min(8, "Password must be at least 8 characters"), +}); + +function SignupForm() { + const form = useForm>({ + resolver: zodResolver(signUpSchema), + defaultValues: { + name: "", + email: "", + password: "", + }, + }); + + const onSubmit = async (data: z.infer) => { + const { error } = await authClient.signUp.email({ ...data }); + if (!error) window.location.href = "/workspaces"; + }; + + return ( +
+ + ( + + Name + + + + + + )} + /> + ( + + Email + + + + + + )} + /> + ( + + Password + + + + + + )} + /> +
+ + + Already have an account?{" "} + + Sign in + + +
+ + + ); +} + export default function Signup() { - return
Signup
; + return ( +
+
+
+
+ + + + + +
+
+
+ + + + + Welcome to Ctrlplane + + + Create an account to continue + + + + + + + +
+
+ ); } diff --git a/packages/auth/src/better/config.ts b/packages/auth/src/better/config.ts index 4bcb329ed..6808a11bf 100644 --- a/packages/auth/src/better/config.ts +++ b/packages/auth/src/better/config.ts @@ -38,6 +38,9 @@ export const auth = betterAuth({ clientSecret: env.AUTH_GOOGLE_CLIENT_SECRET ?? "", }, }, + emailAndPassword: { + enabled: true, + }, trustedOrigins: [env.BASE_URL, "http://localhost:5173"], advanced: { database: {