Skip to content

Commit e0c75e0

Browse files
signUpForm use-form hook set up
1 parent 556c186 commit e0c75e0

File tree

5 files changed

+242
-164
lines changed

5 files changed

+242
-164
lines changed

frontend/src/app/layout.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
1+
'use client';
2+
13
import { Outfit } from 'next/font/google';
24
import './globals.css';
35

46
import { SidebarProvider } from '@/context/SidebarContext';
57
import { ThemeProvider } from '@/context/ThemeContext';
8+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
69

710
const outfit = Outfit({
811
subsets: ["latin"],
912
});
1013

14+
const queryClient = new QueryClient();
15+
16+
1117
export default function RootLayout({
1218
children,
1319
}: Readonly<{
1420
children: React.ReactNode;
1521
}>) {
1622
return (
1723
<html lang="en">
18-
<body className={`${outfit.className} dark:bg-gray-900`}>
19-
<ThemeProvider>
20-
<SidebarProvider>{children}</SidebarProvider>
21-
</ThemeProvider>
24+
<body>
25+
<QueryClientProvider client={queryClient}>
26+
<ThemeProvider>
27+
<SidebarProvider>{children}</SidebarProvider>
28+
</ThemeProvider>
29+
</QueryClientProvider>
2230
</body>
2331
</html>
2432
);

frontend/src/components/auth/SignUpForm.tsx

Lines changed: 103 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,30 @@
11
"use client";
2-
import Checkbox from "@/components/form/input/Checkbox";
32
import Input from "@/components/form/input/InputField";
43
import Label from "@/components/form/Label";
54
import { ChevronLeftIcon, EyeCloseIcon, EyeIcon } from "@/icons";
65
import Link from "next/link";
76
import React, { useState } from "react";
7+
import { namePattern, passwordRules } from "@/utils";
8+
import { useForm } from "react-hook-form";
9+
10+
type FormData = {
11+
firstName: string;
12+
lastName: string;
13+
password: string;
14+
};
815

916
export default function SignUpForm() {
1017
const [showPassword, setShowPassword] = useState(false);
11-
const [isChecked, setIsChecked] = useState(false);
18+
const {
19+
register,
20+
handleSubmit,
21+
formState: { errors },
22+
} = useForm<FormData>();
23+
24+
const onSubmit = (data: FormData) => {
25+
console.log("Form data:", data);
26+
};
27+
1228
return (
1329
<div className="flex flex-col flex-1 lg:w-1/2 w-full overflow-y-auto no-scrollbar">
1430
<div className="w-full max-w-md sm:pt-10 mx-auto mb-5">
@@ -20,170 +36,99 @@ export default function SignUpForm() {
2036
Back to dashboard
2137
</Link>
2238
</div>
39+
2340
<div className="flex flex-col justify-center flex-1 w-full max-w-md mx-auto">
24-
<div>
25-
<div className="mb-5 sm:mb-8">
26-
<h1 className="mb-2 font-semibold text-gray-800 text-title-sm dark:text-white/90 sm:text-title-md">
27-
Sign Up
28-
</h1>
29-
<p className="text-sm text-gray-500 dark:text-gray-400">
30-
Enter your email and password to sign up!
31-
</p>
32-
</div>
33-
<div>
34-
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 sm:gap-5">
35-
<button className="inline-flex items-center justify-center gap-3 py-3 text-sm font-normal text-gray-700 transition-colors bg-gray-100 rounded-lg px-7 hover:bg-gray-200 hover:text-gray-800 dark:bg-white/5 dark:text-white/90 dark:hover:bg-white/10">
36-
<svg
37-
width="20"
38-
height="20"
39-
viewBox="0 0 20 20"
40-
fill="none"
41-
xmlns="http://www.w3.org/2000/svg"
42-
>
43-
<path
44-
d="M18.7511 10.1944C18.7511 9.47495 18.6915 8.94995 18.5626 8.40552H10.1797V11.6527H15.1003C15.0011 12.4597 14.4654 13.675 13.2749 14.4916L13.2582 14.6003L15.9087 16.6126L16.0924 16.6305C17.7788 15.1041 18.7511 12.8583 18.7511 10.1944Z"
45-
fill="#4285F4"
46-
/>
47-
<path
48-
d="M10.1788 18.75C12.5895 18.75 14.6133 17.9722 16.0915 16.6305L13.274 14.4916C12.5201 15.0068 11.5081 15.3666 10.1788 15.3666C7.81773 15.3666 5.81379 13.8402 5.09944 11.7305L4.99473 11.7392L2.23868 13.8295L2.20264 13.9277C3.67087 16.786 6.68674 18.75 10.1788 18.75Z"
49-
fill="#34A853"
50-
/>
51-
<path
52-
d="M5.10014 11.7305C4.91165 11.186 4.80257 10.6027 4.80257 9.99992C4.80257 9.3971 4.91165 8.81379 5.09022 8.26935L5.08523 8.1534L2.29464 6.02954L2.20333 6.0721C1.5982 7.25823 1.25098 8.5902 1.25098 9.99992C1.25098 11.4096 1.5982 12.7415 2.20333 13.9277L5.10014 11.7305Z"
53-
fill="#FBBC05"
54-
/>
55-
<path
56-
d="M10.1789 4.63331C11.8554 4.63331 12.9864 5.34303 13.6312 5.93612L16.1511 3.525C14.6035 2.11528 12.5895 1.25 10.1789 1.25C6.68676 1.25 3.67088 3.21387 2.20264 6.07218L5.08953 8.26943C5.81381 6.15972 7.81776 4.63331 10.1789 4.63331Z"
57-
fill="#EB4335"
58-
/>
59-
</svg>
60-
Sign up with Google
61-
</button>
62-
<button className="inline-flex items-center justify-center gap-3 py-3 text-sm font-normal text-gray-700 transition-colors bg-gray-100 rounded-lg px-7 hover:bg-gray-200 hover:text-gray-800 dark:bg-white/5 dark:text-white/90 dark:hover:bg-white/10">
63-
<svg
64-
width="21"
65-
className="fill-current"
66-
height="20"
67-
viewBox="0 0 21 20"
68-
fill="none"
69-
xmlns="http://www.w3.org/2000/svg"
70-
>
71-
<path d="M15.6705 1.875H18.4272L12.4047 8.75833L19.4897 18.125H13.9422L9.59717 12.4442L4.62554 18.125H1.86721L8.30887 10.7625L1.51221 1.875H7.20054L11.128 7.0675L15.6705 1.875ZM14.703 16.475H16.2305L6.37054 3.43833H4.73137L14.703 16.475Z" />
72-
</svg>
73-
Sign up with X
74-
</button>
41+
<div className="mb-5 sm:mb-8">
42+
<h1 className="mb-2 font-semibold text-gray-800 text-title-sm dark:text-white/90 sm:text-title-md">
43+
Sign Up
44+
</h1>
45+
<p className="text-sm text-gray-500 dark:text-gray-400">
46+
Enter your name to sign up!
47+
</p>
48+
</div>
49+
50+
<form onSubmit={handleSubmit(onSubmit)}>
51+
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2">
52+
{/* First Name */}
53+
<div>
54+
<Label>
55+
First Name<span className="text-error-500">*</span>
56+
</Label>
57+
<Input
58+
placeholder="Enter your first name"
59+
{...register("firstName", {
60+
required: "First name is required",
61+
pattern: namePattern,
62+
})}
63+
error={!!errors.firstName}
64+
hint={errors.firstName?.message}
65+
/>
7566
</div>
76-
<div className="relative py-3 sm:py-5">
77-
<div className="absolute inset-0 flex items-center">
78-
<div className="w-full border-t border-gray-200 dark:border-gray-800"></div>
79-
</div>
80-
<div className="relative flex justify-center text-sm">
81-
<span className="p-2 text-gray-400 bg-white dark:bg-gray-900 sm:px-5 sm:py-2">
82-
Or
67+
68+
{/* Last Name */}
69+
<div>
70+
<Label>
71+
Last Name<span className="text-error-500">*</span>
72+
</Label>
73+
<Input
74+
placeholder="Enter your last name"
75+
{...register("lastName", {
76+
required: "Last name is required",
77+
pattern: namePattern,
78+
})}
79+
error={!!errors.lastName}
80+
hint={errors.lastName?.message}
81+
/>
82+
</div>
83+
84+
{/* Password */}
85+
<div className="sm:col-span-2">
86+
<Label>
87+
Password<span className="text-error-500">*</span>
88+
</Label>
89+
<div className="relative">
90+
<Input
91+
placeholder="Enter your password"
92+
type={showPassword ? "text" : "password"}
93+
{...register("password", passwordRules())}
94+
error={!!errors.password}
95+
hint={errors.password?.message}
96+
/>
97+
<span
98+
onClick={() => setShowPassword(!showPassword)}
99+
className="absolute z-30 cursor-pointer right-4 top-1/2 -translate-y-1/2"
100+
>
101+
{showPassword ? (
102+
<EyeIcon className="fill-gray-500 dark:fill-gray-400" />
103+
) : (
104+
<EyeCloseIcon className="fill-gray-500 dark:fill-gray-400" />
105+
)}
83106
</span>
84107
</div>
85108
</div>
86-
<form>
87-
<div className="space-y-5">
88-
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2">
89-
{/* <!-- First Name --> */}
90-
<div className="sm:col-span-1">
91-
<Label>
92-
First Name<span className="text-error-500">*</span>
93-
</Label>
94-
<Input
95-
type="text"
96-
id="fname"
97-
name="fname"
98-
placeholder="Enter your first name"
99-
/>
100-
</div>
101-
{/* <!-- Last Name --> */}
102-
<div className="sm:col-span-1">
103-
<Label>
104-
Last Name<span className="text-error-500">*</span>
105-
</Label>
106-
<Input
107-
type="text"
108-
id="lname"
109-
name="lname"
110-
placeholder="Enter your last name"
111-
/>
112-
</div>
113-
</div>
114-
{/* <!-- Email --> */}
115-
<div>
116-
<Label>
117-
Email<span className="text-error-500">*</span>
118-
</Label>
119-
<Input
120-
type="email"
121-
id="email"
122-
name="email"
123-
placeholder="Enter your email"
124-
/>
125-
</div>
126-
{/* <!-- Password --> */}
127-
<div>
128-
<Label>
129-
Password<span className="text-error-500">*</span>
130-
</Label>
131-
<div className="relative">
132-
<Input
133-
placeholder="Enter your password"
134-
type={showPassword ? "text" : "password"}
135-
/>
136-
<span
137-
onClick={() => setShowPassword(!showPassword)}
138-
className="absolute z-30 -translate-y-1/2 cursor-pointer right-4 top-1/2"
139-
>
140-
{showPassword ? (
141-
<EyeIcon className="fill-gray-500 dark:fill-gray-400" />
142-
) : (
143-
<EyeCloseIcon className="fill-gray-500 dark:fill-gray-400" />
144-
)}
145-
</span>
146-
</div>
147-
</div>
148-
{/* <!-- Checkbox --> */}
149-
<div className="flex items-center gap-3">
150-
<Checkbox
151-
className="w-5 h-5"
152-
checked={isChecked}
153-
onChange={setIsChecked}
154-
/>
155-
<p className="inline-block font-normal text-gray-500 dark:text-gray-400">
156-
By creating an account means you agree to the{" "}
157-
<span className="text-gray-800 dark:text-white/90">
158-
Terms and Conditions,
159-
</span>{" "}
160-
and our{" "}
161-
<span className="text-gray-800 dark:text-white">
162-
Privacy Policy
163-
</span>
164-
</p>
165-
</div>
166-
{/* <!-- Button --> */}
167-
<div>
168-
<button className="flex items-center justify-center w-full px-4 py-3 text-sm font-medium text-white transition rounded-lg bg-brand-500 shadow-theme-xs hover:bg-brand-600">
169-
Sign Up
170-
</button>
171-
</div>
172-
</div>
173-
</form>
174109

175-
<div className="mt-5">
176-
<p className="text-sm font-normal text-center text-gray-700 dark:text-gray-400 sm:text-start">
177-
Already have an account?
178-
<Link
179-
href="/signin"
180-
className="text-brand-500 hover:text-brand-600 dark:text-brand-400"
181-
>
182-
Sign In
183-
</Link>
184-
</p>
110+
{/* Submit Button */}
111+
<div className="sm:col-span-2">
112+
<button
113+
type="submit"
114+
className="flex items-center justify-center w-full px-4 py-3 text-sm font-medium text-white transition rounded-lg bg-brand-500 shadow-theme-xs hover:bg-brand-600"
115+
>
116+
Sign Up
117+
</button>
185118
</div>
186119
</div>
120+
</form>
121+
122+
<div className="mt-5">
123+
<p className="text-sm font-normal text-center text-gray-700 dark:text-gray-400 sm:text-start">
124+
Already have an account?{" "}
125+
<Link
126+
href="/signin"
127+
className="text-brand-500 hover:text-brand-600 dark:text-brand-400"
128+
>
129+
Sign In
130+
</Link>
131+
</p>
187132
</div>
188133
</div>
189134
</div>

frontend/src/components/form/input/InputField.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ interface InputProps {
88
defaultValue?: string | number;
99
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
1010
className?: string;
11-
min?: string;
12-
max?: string;
11+
min?: string | number;
12+
max?: string | number;
1313
step?: number;
1414
disabled?: boolean;
1515
success?: boolean;

0 commit comments

Comments
 (0)