@@ -169,6 +198,7 @@ export default function SignUp() {
id="full_name"
placeholder="First and last name"
{...field}
+ onBlur={() => validateField("full_name")}
/>
@@ -187,6 +217,7 @@ export default function SignUp() {
type="email"
placeholder="helloworld@email.com"
{...field}
+ onBlur={() => validateField("email")}
/>
@@ -206,8 +237,10 @@ export default function SignUp() {
type={isPasswordVisible ? "text" : "password"}
placeholder="Password (at least 8 characters)"
{...field}
+ onBlur={() => validateField("password")}
/>
+
)}
diff --git a/components/ui/form-skeleton.tsx b/components/ui/form-skeleton.tsx
new file mode 100644
index 000000000..8420568a9
--- /dev/null
+++ b/components/ui/form-skeleton.tsx
@@ -0,0 +1,20 @@
+import { cn } from "@/lib/utils";
+
+interface FormSkeletonProps {
+ className?: string;
+ fieldCount?: number;
+}
+
+export function FormSkeleton({ className, fieldCount = 4 }: FormSkeletonProps) {
+ return (
+
+ {Array.from({ length: fieldCount }).map((_, index) => (
+
+ ))}
+
+
+ );
+}
\ No newline at end of file
diff --git a/components/ui/password-strength.tsx b/components/ui/password-strength.tsx
new file mode 100644
index 000000000..a9b55f28b
--- /dev/null
+++ b/components/ui/password-strength.tsx
@@ -0,0 +1,105 @@
+import { useEffect, useState } from "react";
+import { cn } from "@/lib/utils";
+
+interface PasswordStrengthProps {
+ password: string;
+ className?: string;
+}
+
+export function PasswordStrength({ password, className }: PasswordStrengthProps) {
+ const [strength, setStrength] = useState(0);
+ const [message, setMessage] = useState("");
+
+ useEffect(() => {
+ if (!password) {
+ setStrength(0);
+ setMessage("");
+ return;
+ }
+
+ let score = 0;
+ let feedback = [];
+
+ // Length check
+ if (password.length >= 8) {
+ score += 1;
+ } else {
+ feedback.push("At least 8 characters");
+ }
+
+ // Uppercase check
+ if (/[A-Z]/.test(password)) {
+ score += 1;
+ } else {
+ feedback.push("One uppercase letter");
+ }
+
+ // Lowercase check
+ if (/[a-z]/.test(password)) {
+ score += 1;
+ } else {
+ feedback.push("One lowercase letter");
+ }
+
+ // Number check
+ if (/[0-9]/.test(password)) {
+ score += 1;
+ } else {
+ feedback.push("One number");
+ }
+
+ // Special character check
+ if (/[^A-Za-z0-9]/.test(password)) {
+ score += 1;
+ } else {
+ feedback.push("One special character");
+ }
+
+ setStrength(score);
+
+ if (score === 0) {
+ setMessage("");
+ } else if (score <= 2) {
+ setMessage("Weak - " + feedback.join(", "));
+ } else if (score <= 3) {
+ setMessage("Medium - " + feedback.join(", "));
+ } else if (score <= 4) {
+ setMessage("Strong - " + feedback.join(", "));
+ } else {
+ setMessage("Very Strong");
+ }
+ }, [password]);
+
+ const getStrengthColor = () => {
+ if (strength <= 2) return "bg-red-500";
+ if (strength <= 3) return "bg-yellow-500";
+ if (strength <= 4) return "bg-blue-500";
+ return "bg-green-500";
+ };
+
+ return (
+
+
+ {message && (
+
+ {message}
+
+ )}
+
+ );
+}
\ No newline at end of file