feat/book-now #6
@ -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