Implement authentication checks on booking page to require user login before accessing appointment features. Update form fields and buttons to disable when not authenticated, and enhance user experience with appropriate prompts and dialog handling.
This commit is contained in:
parent
77bc00999d
commit
e05f81ddae
@ -104,6 +104,14 @@ export default function BookNowPage() {
|
|||||||
const [showSignupDialog, setShowSignupDialog] = useState(false);
|
const [showSignupDialog, setShowSignupDialog] = useState(false);
|
||||||
const [loginPrefillEmail, setLoginPrefillEmail] = useState<string | undefined>(undefined);
|
const [loginPrefillEmail, setLoginPrefillEmail] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
|
// Require authentication before accessing booking page
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isAuthenticated) {
|
||||||
|
// Show login dialog immediately if not authenticated
|
||||||
|
setShowLoginDialog(true);
|
||||||
|
}
|
||||||
|
}, [isAuthenticated]);
|
||||||
|
|
||||||
// Helper function to convert day name to day number (0-6)
|
// Helper function to convert day name to day number (0-6)
|
||||||
const getDayNumber = (dayName: string): number => {
|
const getDayNumber = (dayName: string): number => {
|
||||||
const dayMap: Record<string, number> = {
|
const dayMap: Record<string, number> = {
|
||||||
@ -241,15 +249,21 @@ export default function BookNowPage() {
|
|||||||
const handleLoginSuccess = async () => {
|
const handleLoginSuccess = async () => {
|
||||||
// Close login dialog
|
// Close login dialog
|
||||||
setShowLoginDialog(false);
|
setShowLoginDialog(false);
|
||||||
// After successful login, proceed with booking submission
|
// If there's a pending booking submission, proceed with it
|
||||||
|
// Otherwise, just close the dialog and allow user to fill the form
|
||||||
|
if (formData.selectedSlots.length > 0 && formData.firstName && formData.lastName && formData.email) {
|
||||||
await submitBooking();
|
await submitBooking();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSignupSuccess = async () => {
|
const handleSignupSuccess = async () => {
|
||||||
// Close signup dialog
|
// Close signup dialog
|
||||||
setShowSignupDialog(false);
|
setShowSignupDialog(false);
|
||||||
// After successful signup, proceed with booking submission
|
// If there's a pending booking submission, proceed with it
|
||||||
|
// Otherwise, just close the dialog and allow user to fill the form
|
||||||
|
if (formData.selectedSlots.length > 0 && formData.firstName && formData.lastName && formData.email) {
|
||||||
await submitBooking();
|
await submitBooking();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSwitchToSignup = () => {
|
const handleSwitchToSignup = () => {
|
||||||
@ -652,6 +666,13 @@ export default function BookNowPage() {
|
|||||||
<p className={`text-sm ${isDark ? 'text-red-200' : 'text-red-800'}`}>{error}</p>
|
<p className={`text-sm ${isDark ? 'text-red-200' : 'text-red-800'}`}>{error}</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{!isAuthenticated && (
|
||||||
|
<div className={`mb-6 p-4 rounded-lg border ${isDark ? 'bg-yellow-900/20 border-yellow-800' : 'bg-yellow-50 border-yellow-200'}`}>
|
||||||
|
<p className={`text-sm ${isDark ? 'text-yellow-200' : 'text-yellow-800'}`}>
|
||||||
|
Please log in to book an appointment. The login dialog should appear automatically.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<form onSubmit={handleSubmit} className="space-y-6">
|
<form onSubmit={handleSubmit} className="space-y-6">
|
||||||
{/* Personal Information Section */}
|
{/* Personal Information Section */}
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
@ -678,6 +699,7 @@ export default function BookNowPage() {
|
|||||||
}
|
}
|
||||||
maxLength={100}
|
maxLength={100}
|
||||||
required
|
required
|
||||||
|
disabled={!isAuthenticated}
|
||||||
className={`h-11 ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900 placeholder:text-gray-500'}`}
|
className={`h-11 ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900 placeholder:text-gray-500'}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -699,6 +721,7 @@ export default function BookNowPage() {
|
|||||||
}
|
}
|
||||||
maxLength={100}
|
maxLength={100}
|
||||||
required
|
required
|
||||||
|
disabled={!isAuthenticated}
|
||||||
className={`h-11 ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900 placeholder:text-gray-500'}`}
|
className={`h-11 ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900 placeholder:text-gray-500'}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -720,6 +743,7 @@ export default function BookNowPage() {
|
|||||||
onChange={(e) => handleChange("email", e.target.value)}
|
onChange={(e) => handleChange("email", e.target.value)}
|
||||||
maxLength={100}
|
maxLength={100}
|
||||||
required
|
required
|
||||||
|
disabled={!isAuthenticated}
|
||||||
className={`h-11 ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900 placeholder:text-gray-500'}`}
|
className={`h-11 ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900 placeholder:text-gray-500'}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -740,6 +764,7 @@ export default function BookNowPage() {
|
|||||||
onChange={(e) => handleChange("phone", e.target.value)}
|
onChange={(e) => handleChange("phone", e.target.value)}
|
||||||
maxLength={100}
|
maxLength={100}
|
||||||
required
|
required
|
||||||
|
disabled={!isAuthenticated}
|
||||||
className={`h-11 ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900 placeholder:text-gray-500'}`}
|
className={`h-11 ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900 placeholder:text-gray-500'}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -814,9 +839,14 @@ export default function BookNowPage() {
|
|||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
if (!isAuthenticated) {
|
||||||
|
setShowLoginDialog(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Pass the specific day and time slot for this button
|
// Pass the specific day and time slot for this button
|
||||||
handleSlotToggle(currentDay, normalizedTimeSlot);
|
handleSlotToggle(currentDay, normalizedTimeSlot);
|
||||||
}}
|
}}
|
||||||
|
disabled={!isAuthenticated}
|
||||||
aria-pressed={isSelected}
|
aria-pressed={isSelected}
|
||||||
className={`flex items-center gap-2 cursor-pointer px-4 py-2 rounded-lg border-2 transition-all focus:outline-none focus:ring-2 focus:ring-rose-500 ${
|
className={`flex items-center gap-2 cursor-pointer px-4 py-2 rounded-lg border-2 transition-all focus:outline-none focus:ring-2 focus:ring-rose-500 ${
|
||||||
isSelected
|
isSelected
|
||||||
@ -861,6 +891,7 @@ export default function BookNowPage() {
|
|||||||
value={formData.message}
|
value={formData.message}
|
||||||
onChange={(e) => handleChange("message", e.target.value)}
|
onChange={(e) => handleChange("message", e.target.value)}
|
||||||
maxLength={100}
|
maxLength={100}
|
||||||
|
disabled={!isAuthenticated}
|
||||||
className={`w-full rounded-md border px-3 py-2 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-rose-500 focus-visible:border-rose-500 disabled:cursor-not-allowed disabled:opacity-50 ${isDark ? 'border-gray-600 bg-gray-700 text-white placeholder:text-gray-400 focus-visible:ring-rose-400 focus-visible:border-rose-400' : 'border-gray-300 bg-white text-gray-900 placeholder:text-gray-500'}`}
|
className={`w-full rounded-md border px-3 py-2 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-rose-500 focus-visible:border-rose-500 disabled:cursor-not-allowed disabled:opacity-50 ${isDark ? 'border-gray-600 bg-gray-700 text-white placeholder:text-gray-400 focus-visible:ring-rose-400 focus-visible:border-rose-400' : 'border-gray-300 bg-white text-gray-900 placeholder:text-gray-500'}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -870,7 +901,7 @@ export default function BookNowPage() {
|
|||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
size="lg"
|
size="lg"
|
||||||
disabled={isCreating || availableDaysOfWeek.length === 0 || formData.selectedSlots.length === 0}
|
disabled={!isAuthenticated || isCreating || availableDaysOfWeek.length === 0 || formData.selectedSlots.length === 0}
|
||||||
className="w-full bg-gradient-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 h-12 text-base font-semibold disabled:opacity-50 disabled:cursor-not-allowed"
|
className="w-full bg-gradient-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 h-12 text-base font-semibold disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
>
|
>
|
||||||
{isCreating ? (
|
{isCreating ? (
|
||||||
@ -915,6 +946,12 @@ export default function BookNowPage() {
|
|||||||
<LoginDialog
|
<LoginDialog
|
||||||
open={showLoginDialog}
|
open={showLoginDialog}
|
||||||
onOpenChange={(open) => {
|
onOpenChange={(open) => {
|
||||||
|
// Prevent closing if user is not authenticated (force login)
|
||||||
|
if (!open && !isAuthenticated) {
|
||||||
|
// Redirect to home if they try to close without logging in
|
||||||
|
router.push("/");
|
||||||
|
return;
|
||||||
|
}
|
||||||
setShowLoginDialog(open);
|
setShowLoginDialog(open);
|
||||||
if (!open) {
|
if (!open) {
|
||||||
setLoginPrefillEmail(undefined);
|
setLoginPrefillEmail(undefined);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user