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:
parent
561d2ee2b5
commit
75a89fc07c
@ -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>
|
||||||
|
|||||||
@ -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>
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user