Enhance LoginDialog component by adding signup functionality, including form fields for full name, email, and phone number. Implement state management for signup process and error handling. Update UI to toggle between login and signup views, improving user experience.

This commit is contained in:
iamkiddy 2025-11-07 20:28:22 +00:00
parent 561d2ee2b5
commit 75a89fc07c
2 changed files with 145 additions and 17 deletions

View File

@ -495,10 +495,10 @@ export default function BookNowPage() {
} }
required required
> >
<SelectTrigger id="appointmentType" className="h-11"> <SelectTrigger id="appointmentType" className="h-11 bg-white">
<SelectValue placeholder="Select appointment type" /> <SelectValue placeholder="Select appointment type" />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent className="bg-white">
<SelectItem value="initial-consultation"> <SelectItem value="initial-consultation">
Initial Consultation Initial Consultation
</SelectItem> </SelectItem>
@ -555,7 +555,7 @@ export default function BookNowPage() {
<SelectTrigger id="preferredTime" className="h-11"> <SelectTrigger id="preferredTime" className="h-11">
<SelectValue placeholder="Select time" /> <SelectValue placeholder="Select time" />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent className="bg-white">
<SelectItem value="9:00 AM">9:00 AM</SelectItem> <SelectItem value="9:00 AM">9:00 AM</SelectItem>
<SelectItem value="10:00 AM">10:00 AM</SelectItem> <SelectItem value="10:00 AM">10:00 AM</SelectItem>
<SelectItem value="11:00 AM">11:00 AM</SelectItem> <SelectItem value="11:00 AM">11:00 AM</SelectItem>

View File

@ -11,7 +11,6 @@ import {
DialogTitle, DialogTitle,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { Eye, EyeOff, Loader2 } from "lucide-react"; import { Eye, EyeOff, Loader2 } from "lucide-react";
import Link from "next/link";
interface LoginDialogProps { interface LoginDialogProps {
open: boolean; open: boolean;
@ -19,14 +18,22 @@ interface LoginDialogProps {
onLoginSuccess: () => void; onLoginSuccess: () => void;
} }
// Login Dialog component
export function LoginDialog({ open, onOpenChange, onLoginSuccess }: LoginDialogProps) { export function LoginDialog({ open, onOpenChange, onLoginSuccess }: LoginDialogProps) {
const [isSignup, setIsSignup] = useState(false);
const [loginData, setLoginData] = useState({ const [loginData, setLoginData] = useState({
email: "", email: "",
password: "", password: "",
}); });
const [signupData, setSignupData] = useState({
fullName: "",
email: "",
phone: "",
});
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const [rememberMe, setRememberMe] = useState(false); const [rememberMe, setRememberMe] = useState(false);
const [loginLoading, setLoginLoading] = useState(false); const [loginLoading, setLoginLoading] = useState(false);
const [signupLoading, setSignupLoading] = useState(false);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const handleLogin = async (e: React.FormEvent) => { const handleLogin = async (e: React.FormEvent) => {
@ -49,19 +56,138 @@ export function LoginDialog({ open, onOpenChange, onLoginSuccess }: LoginDialogP
} }
}; };
const handleSignup = async (e: React.FormEvent) => {
e.preventDefault();
setSignupLoading(true);
setError(null);
try {
// Simulate signup API call
await new Promise((resolve) => setTimeout(resolve, 1000));
// After successful signup, automatically log in and proceed
setSignupLoading(false);
onOpenChange(false);
onLoginSuccess();
} catch (err) {
setError("Signup failed. Please try again.");
setSignupLoading(false);
}
};
const handleSwitchToSignup = () => {
setIsSignup(true);
setError(null);
setLoginData({ email: "", password: "" });
};
const handleSwitchToLogin = () => {
setIsSignup(false);
setError(null);
setSignupData({ fullName: "", email: "", phone: "" });
};
return ( return (
<Dialog open={open} onOpenChange={onOpenChange}> <Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-md bg-white"> <DialogContent className="sm:max-w-md bg-white">
<DialogHeader> <DialogHeader>
<DialogTitle className="text-3xl font-bold bg-linear-to-r from-rose-600 via-pink-600 to-rose-600 bg-clip-text text-transparent"> <DialogTitle className="text-3xl font-bold bg-linear-to-r from-rose-600 via-pink-600 to-rose-600 bg-clip-text text-transparent">
Welcome back {isSignup ? "Create an account" : "Welcome back"}
</DialogTitle> </DialogTitle>
<DialogDescription className="text-gray-600"> <DialogDescription className="text-gray-600">
Please log in to complete your booking {isSignup
? "Sign up to complete your booking"
: "Please log in to complete your booking"}
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
{/* Login Form */} {/* Signup Form */}
{isSignup ? (
<form className="space-y-6 mt-4" onSubmit={handleSignup}>
{error && (
<div className="p-3 bg-red-50 border border-red-200 rounded-lg">
<p className="text-sm text-red-800">{error}</p>
</div>
)}
{/* Full Name Field */}
<div className="space-y-2">
<label htmlFor="signup-fullName" className="text-sm font-medium text-black">
Full Name *
</label>
<Input
id="signup-fullName"
type="text"
placeholder="John Doe"
value={signupData.fullName}
onChange={(e) => setSignupData({ ...signupData, fullName: e.target.value })}
className="h-12 bg-white border-gray-300"
required
/>
</div>
{/* Email Field */}
<div className="space-y-2">
<label htmlFor="signup-email" className="text-sm font-medium text-black">
Email address *
</label>
<Input
id="signup-email"
type="email"
placeholder="Email address"
value={signupData.email}
onChange={(e) => setSignupData({ ...signupData, email: e.target.value })}
className="h-12 bg-white border-gray-300"
required
/>
</div>
{/* Phone Field */}
<div className="space-y-2">
<label htmlFor="signup-phone" className="text-sm font-medium text-black">
Phone Number *
</label>
<Input
id="signup-phone"
type="tel"
placeholder="+1 (555) 123-4567"
value={signupData.phone}
onChange={(e) => setSignupData({ ...signupData, phone: e.target.value })}
className="h-12 bg-white border-gray-300"
required
/>
</div>
{/* Submit Button */}
<Button
type="submit"
disabled={signupLoading}
className="w-full h-12 text-base font-semibold bg-linear-to-r from-rose-500 to-pink-600 hover:from-rose-600 hover:to-pink-700 text-white shadow-lg hover:shadow-xl transition-all disabled:opacity-50 disabled:cursor-not-allowed"
>
{signupLoading ? (
<>
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
Creating account...
</>
) : (
"Sign up"
)}
</Button>
{/* Switch to Login */}
<p className="text-sm text-gray-600 text-center">
Already have an account?{" "}
<button
type="button"
onClick={handleSwitchToLogin}
className="text-blue-600 underline font-medium hover:text-blue-700"
>
Log in
</button>
</p>
</form>
) : (
/* Login Form */
<form className="space-y-6 mt-4" onSubmit={handleLogin}> <form className="space-y-6 mt-4" onSubmit={handleLogin}>
{error && ( {error && (
<div className="p-3 bg-red-50 border border-red-200 rounded-lg"> <div className="p-3 bg-red-50 border border-red-200 rounded-lg">
@ -144,26 +270,28 @@ export function LoginDialog({ open, onOpenChange, onLoginSuccess }: LoginDialogP
/> />
<span className="text-black">Remember me</span> <span className="text-black">Remember me</span>
</label> </label>
<Link <button
href="/forgot-password" type="button"
className="text-blue-600 hover:text-blue-700 font-medium" className="text-blue-600 hover:text-blue-700 font-medium"
onClick={(e) => { onClick={() => onOpenChange(false)}
e.preventDefault();
onOpenChange(false);
}}
> >
Forgot password? Forgot password?
</Link> </button>
</div> </div>
{/* Sign Up Prompt */} {/* Sign Up Prompt */}
<p className="text-sm text-gray-600 text-center"> <p className="text-sm text-gray-600 text-center">
New to Attune Heart Therapy?{" "} New to Attune Heart Therapy?{" "}
<Link href="/signup" className="text-blue-600 underline font-medium"> <button
type="button"
onClick={handleSwitchToSignup}
className="text-blue-600 underline font-medium hover:text-blue-700"
>
Sign up Sign up
</Link> </button>
</p> </p>
</form> </form>
)}
</DialogContent> </DialogContent>
</Dialog> </Dialog>
); );