chore: more wip

This commit is contained in:
Lluis Agusti
2025-07-01 20:00:24 +04:00
parent c18099b72b
commit 689c985dca
6 changed files with 142 additions and 65 deletions

View File

@@ -1,6 +1,7 @@
"use client";
import { Button } from "@/components/atoms/Button/Button";
import { Input } from "@/components/atoms/Input/Input";
import { Link } from "@/components/atoms/Link/Link";
import { AuthCard } from "@/components/auth/AuthCard";
import AuthFeedback from "@/components/auth/AuthFeedback";
import { EmailNotAllowedModal } from "@/components/auth/EmailNotAllowedModal";
@@ -61,7 +62,7 @@ export default function LoginPage() {
</>
) : null}
<Form {...form}>
<form onSubmit={handleSubmit} className="flex w-full flex-col gap-6">
<form onSubmit={handleSubmit} className="flex w-full flex-col gap-1">
<FormField
control={form.control}
name="email"
@@ -87,6 +88,11 @@ export default function LoginPage() {
type="password"
autoComplete="current-password"
error={form.formState.errors.password?.message}
hint={
<Link variant="secondary" href="/reset-password">
Forgot password?
</Link>
}
{...field}
/>
)}

View File

@@ -160,7 +160,10 @@ export default function ResetPasswordPage() {
<div className="flex h-full min-h-[85vh] flex-col items-center justify-center">
<AuthCard title="Reset Password">
{user ? (
<form onSubmit={changePasswordForm.handleSubmit(onChangePassword)}>
<form
onSubmit={changePasswordForm.handleSubmit(onChangePassword)}
className="flex w-full flex-col gap-1"
>
<Form {...changePasswordForm}>
<FormField
control={changePasswordForm.control}
@@ -222,7 +225,10 @@ export default function ResetPasswordPage() {
</Form>
</form>
) : (
<form onSubmit={sendEmailForm.handleSubmit(onSendEmail)}>
<form
onSubmit={sendEmailForm.handleSubmit(onSendEmail)}
className="flex w-full flex-col gap-1"
>
<Form {...sendEmailForm}>
<FormField
control={sendEmailForm.control}

View File

@@ -0,0 +1,29 @@
import { AuthCard } from "@/components/auth/AuthCard";
import { Skeleton } from "@/components/ui/skeleton";
export function LoadingSignup() {
return (
<div className="flex h-full min-h-[85vh] flex-col items-center justify-center">
<AuthCard title="">
<Skeleton className="mx-auto h-8 w-48" />
<Skeleton className="h-12 w-full rounded-md" />
<div className="w-full space-y-6">
<div className="space-y-2">
<Skeleton className="h-4 w-12" />
<Skeleton className="h-12 w-full rounded-md" />
</div>
<div className="space-y-2">
<Skeleton className="h-4 w-16" />
<Skeleton className="h-12 w-full rounded-md" />
</div>
<Skeleton className="h-16 w-full rounded-md" />
<Skeleton className="h-12 w-full rounded-md" />
<div className="flex justify-center space-x-1">
<Skeleton className="h-4 w-32" />
<Skeleton className="h-4 w-12" />
</div>
</div>
</AuthCard>
</div>
);
}

View File

@@ -2,6 +2,8 @@
import { Button } from "@/components/atoms/Button/Button";
import { Input } from "@/components/atoms/Input/Input";
import { Link } from "@/components/atoms/Link/Link";
import { Text } from "@/components/atoms/Text/Text";
import { AuthCard } from "@/components/auth/AuthCard";
import AuthFeedback from "@/components/auth/AuthFeedback";
import { EmailNotAllowedModal } from "@/components/auth/EmailNotAllowedModal";
@@ -15,11 +17,10 @@ import {
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import LoadingBox from "@/components/ui/loading";
import { getBehaveAs } from "@/lib/utils";
import Link from "next/link";
import { WarningOctagonIcon } from "@phosphor-icons/react/dist/ssr";
import { LoadingSignup } from "./components/LoadingSignup";
import { useSignupPage } from "./useSignupPage";
export default function SignupPage() {
@@ -41,7 +42,7 @@ export default function SignupPage() {
} = useSignupPage();
if (isUserLoading || isLoggedIn) {
return <LoadingBox className="h-[80vh]" />;
return <LoadingSignup />;
}
if (!isSupabaseAvailable) {
@@ -52,6 +53,10 @@ export default function SignupPage() {
);
}
const confirmPasswordError = form.formState.errors.confirmPassword?.message;
const withConfirmPassword = form.getValues("confirmPassword").length > 0;
const termsError = form.formState.errors.agreeToTerms?.message;
return (
<div className="flex h-full min-h-[85vh] flex-col items-center justify-center">
<AuthCard title="Create a new account">
@@ -73,7 +78,7 @@ export default function SignupPage() {
) : null}
<Form {...form}>
<form onSubmit={handleSubmit} className="flex w-full flex-col gap-6">
<form onSubmit={handleSubmit} className="flex w-full flex-col gap-1">
<FormField
control={form.control}
name="email"
@@ -112,16 +117,75 @@ export default function SignupPage() {
placeholder="********"
type="password"
autoComplete="new-password"
error={form.formState.errors.confirmPassword?.message}
error={confirmPasswordError}
{...field}
/>
<p className="text-sm font-normal leading-tight text-slate-500">
Password needs to be at least 12 characters long
</p>
{!confirmPasswordError && !withConfirmPassword ? (
<Text
variant="small"
className="relative -top-7 !text-slate-500"
>
Password needs to be at least 12 characters long
</Text>
) : null}
</div>
)}
/>
<FormField
control={form.control}
name="agreeToTerms"
render={({ field }) => (
<>
<FormItem className="mt-6 flex w-full flex-row items-center -space-y-1 space-x-2">
<FormControl>
<Checkbox
checked={field.value}
onCheckedChange={field.onChange}
className="relative bottom-px"
/>
</FormControl>
<div>
<FormLabel className="flex items-center gap-1">
<Text
variant="body-medium"
className="inline-block text-slate-950"
>
I agree to the
</Text>
<Link
href="https://auto-gpt.notion.site/Terms-of-Use-11400ef5bece80d0b087d7831c5fd6bf"
variant="secondary"
>
Terms of Use
</Link>
<Text
variant="body-medium"
className="inline-block text-slate-950"
>
and
</Text>
<Link
href="https://www.notion.so/auto-gpt/Privacy-Policy-ab11c9c20dbd4de1a15dcffe84d77984"
variant="secondary"
>
Privacy Policy
</Link>
</FormLabel>
</div>
</FormItem>
{termsError ? (
<div className="flex items-center gap-2">
<WarningOctagonIcon className="h-4 w-4 text-red-500" />
<Text variant="small-medium" className="!text-red-500">
{termsError}
</Text>
</div>
) : null}
</>
)}
/>
{/* Turnstile CAPTCHA Component */}
<Turnstile
key={captchaKey}
@@ -142,43 +206,6 @@ export default function SignupPage() {
>
Sign up
</Button>
<FormField
control={form.control}
name="agreeToTerms"
render={({ field }) => (
<FormItem className="mt-6 flex flex-row items-start -space-y-1 space-x-2">
<FormControl>
<Checkbox
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
<div className="">
<FormLabel>
<span className="mr-1 text-sm font-normal leading-normal text-slate-950">
I agree to the
</span>
<Link
href="https://auto-gpt.notion.site/Terms-of-Use-11400ef5bece80d0b087d7831c5fd6bf"
className="text-sm font-normal leading-normal text-slate-950 underline"
>
Terms of Use
</Link>
<span className="mx-1 text-sm font-normal leading-normal text-slate-950">
and
</span>
<Link
href="https://www.notion.so/auto-gpt/Privacy-Policy-ab11c9c20dbd4de1a15dcffe84d77984"
className="text-sm font-normal leading-normal text-slate-950 underline"
>
Privacy Policy
</Link>
</FormLabel>
<FormMessage />
</div>
</FormItem>
)}
/>
</form>
</Form>
<AuthFeedback

View File

@@ -1,5 +1,6 @@
import { Input as BaseInput, type InputProps } from "@/components/ui/input";
import { cn } from "@/lib/utils";
import { ReactNode } from "react";
import { Text } from "../Text/Text";
import { useInput } from "./useInput";
@@ -8,6 +9,7 @@ export interface TextFieldProps extends InputProps {
hideLabel?: boolean;
decimalCount?: number; // Only used for type="amount"
error?: string;
hint?: ReactNode;
}
export function Input({
@@ -16,6 +18,7 @@ export function Input({
placeholder,
hideLabel = false,
decimalCount,
hint,
error,
...props
}: TextFieldProps) {
@@ -48,13 +51,19 @@ export function Input({
);
const inputWithError = (
<div className="flex flex-col gap-1">
<div className="relative mb-6">
{input}
{error && (
<Text variant="small-medium" as="span" className="!text-red-500">
{error}
</Text>
)}
<Text
variant="small-medium"
as="span"
className={cn(
"absolute left-0 top-full mt-1 !text-red-500 transition-opacity duration-200",
error ? "opacity-100" : "opacity-0",
)}
>
{error || " "}{" "}
{/* Always render with space to maintain consistent height calculation */}
</Text>
</div>
);
@@ -62,9 +71,12 @@ export function Input({
inputWithError
) : (
<label className="flex flex-col gap-2">
<Text variant="body-medium" as="span" className="text-black">
{label}
</Text>
<div className="flex items-center justify-between">
<Text variant="body-medium" as="span" className="text-black">
{label}
</Text>
{hint}
</div>
{inputWithError}
</label>
);

View File

@@ -19,17 +19,14 @@ AuthCard.BottomText = function BottomText({
<div
className={cn(
className,
"mt-8 inline-flex w-full items-center justify-center",
"mt-8 inline-flex w-full items-center justify-center gap-1",
)}
>
<span className="text-sm font-medium leading-normal text-slate-950">
<Text variant="body-medium" className="text-slate-950">
{text}
</span>
</Text>
{link ? (
<Link
href={link.href}
className="ml-1 text-sm font-medium leading-normal text-slate-950 underline"
>
<Link href={link.href} variant="secondary">
{link.text}
</Link>
) : null}