Merge pull request 'feat/booking-panel' (#57) from feat/booking-panel into master

Reviewed-on: http://35.207.46.142/ATTUNE-HEART-THERAPY/website/pulls/57
This commit is contained in:
Hammond 2025-12-04 19:53:22 +00:00
commit a7a24d1a64
2 changed files with 43 additions and 6 deletions

View File

@ -104,6 +104,14 @@ export default function BookNowPage() {
const [showSignupDialog, setShowSignupDialog] = useState(false);
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)
const getDayNumber = (dayName: string): number => {
const dayMap: Record<string, number> = {
@ -241,15 +249,21 @@ export default function BookNowPage() {
const handleLoginSuccess = async () => {
// Close login dialog
setShowLoginDialog(false);
// After successful login, proceed with booking submission
await submitBooking();
// 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();
}
};
const handleSignupSuccess = async () => {
// Close signup dialog
setShowSignupDialog(false);
// After successful signup, proceed with booking submission
await submitBooking();
// 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();
}
};
const handleSwitchToSignup = () => {
@ -652,6 +666,13 @@ export default function BookNowPage() {
<p className={`text-sm ${isDark ? 'text-red-200' : 'text-red-800'}`}>{error}</p>
</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">
{/* Personal Information Section */}
<div className="space-y-4">
@ -678,6 +699,7 @@ export default function BookNowPage() {
}
maxLength={100}
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'}`}
/>
</div>
@ -699,6 +721,7 @@ export default function BookNowPage() {
}
maxLength={100}
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'}`}
/>
</div>
@ -720,6 +743,7 @@ export default function BookNowPage() {
onChange={(e) => handleChange("email", e.target.value)}
maxLength={100}
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'}`}
/>
</div>
@ -740,6 +764,7 @@ export default function BookNowPage() {
onChange={(e) => handleChange("phone", e.target.value)}
maxLength={100}
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'}`}
/>
</div>
@ -814,9 +839,14 @@ export default function BookNowPage() {
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
if (!isAuthenticated) {
setShowLoginDialog(true);
return;
}
// Pass the specific day and time slot for this button
handleSlotToggle(currentDay, normalizedTimeSlot);
}}
disabled={!isAuthenticated}
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 ${
isSelected
@ -861,6 +891,7 @@ export default function BookNowPage() {
value={formData.message}
onChange={(e) => handleChange("message", e.target.value)}
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'}`}
/>
</div>
@ -870,7 +901,7 @@ export default function BookNowPage() {
<Button
type="submit"
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"
>
{isCreating ? (
@ -915,6 +946,12 @@ export default function BookNowPage() {
<LoginDialog
open={showLoginDialog}
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);
if (!open) {
setLoginPrefillEmail(undefined);

View File

@ -84,7 +84,7 @@ export function Navbar() {
whileTap={{ scale: 0.95 }}
>
<Link
href={isAuthenticated && !isAdmin ? "/user/dashboard" : "/"}
href="/"
className="flex items-center gap-1.5 sm:gap-2"
>
<div className="bg-gradient-to-r from-rose-500 to-pink-600 p-1.5 sm:p-2 rounded-lg sm:rounded-xl">