Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 45 additions & 31 deletions components/BookEvent.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use client';

import {useState} from "react";
const [error, setError] = useState<string | null>(null);
const [isSubmitting, setIsSubmitting] = useState(false);
Comment on lines +4 to +5
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: React hooks called outside component function.

Lines 4-5 declare useState hooks at the module/top level, before the BookEvent component function is defined on line 9. This violates React's Rules of Hooks and will cause an immediate runtime crash with "Invalid hook call. Hooks can only be called inside the body of a function component."

Additionally, having imports on lines 6-7 after executable statements (lines 4-5) is invalid JavaScript syntax.

These hooks must be moved inside the BookEvent component function body.

🔧 Required fix: Move hooks inside component
 'use client';

 import {useState} from "react";
-const [error, setError] = useState<string | null>(null);
-const [isSubmitting, setIsSubmitting] = useState(false);
 import {createBooking} from "`@/lib/actions/booking.actions`";
 import posthog from "posthog-js";

 const BookEvent = ({ eventId, slug }: { eventId: string, slug: string;}) => {
     const [email, setEmail] = useState('');
     const [submitted, setSubmitted] = useState(false);
+    const [error, setError] = useState<string | null>(null);
+    const [isSubmitting, setIsSubmitting] = useState(false);

     const handleSubmit = async (e: React.FormEvent) => {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/BookEvent.tsx` around lines 4 - 5, The useState calls (useState,
setError, setIsSubmitting) were declared at module scope which violates the
Rules of Hooks and precedes imports; move those hook declarations inside the
BookEvent function body so they are executed during render. Locate the top-level
const [error, setError] = useState<string | null>(null) and const [isSubmitting,
setIsSubmitting] = useState(false) and cut/paste them into the start of the
BookEvent component function (immediately after the function signature) and
remove the top-level instances so imports remain at top-level and hooks run only
inside the BookEvent component.

import {createBooking} from "@/lib/actions/booking.actions";
import posthog from "posthog-js";

Expand All @@ -9,40 +11,52 @@ const BookEvent = ({ eventId, slug }: { eventId: string, slug: string;}) => {
const [submitted, setSubmitted] = useState(false);

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
e.preventDefault();
setIsSubmitting(true);
setError(null);

const { success } = await createBooking({ eventId, slug, email });
try {
const response = await createBooking({ eventId, slug, email });

if(success) {
setSubmitted(true);
posthog.capture('event_booked', { eventId, slug, email })
} else {
console.error('Booking creation failed')
posthog.captureException('Booking creation failed')
}
if (response.success) {
setSubmitted(true);
posthog.capture('event_booked', { eventId, slug, email });
} else {
setError(response.error || "An unexpected error occurred. Please try again.");
posthog.captureException('Booking creation failed');
}
} catch (err) {
setError("A network error occurred. Please try again.");
} finally {
setIsSubmitting(false);
}
};


return (
<div id="book-event">
{submitted ? (
<p className="text-sm">Thank you for signing up!</p>
): (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="email">Email Address</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
id="email"
placeholder="Enter your email address"
/>
</div>

<button type="submit" className="button-submit">Submit</button>
</form>
)}
</div>
)
}
export default BookEvent
{submitted ? (
<p className="text-sm">Thank you for signing up!</p>
) : (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="email">Email Address</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
id="email"
placeholder="Enter your email address"
disabled={isSubmitting} // 1. Freeze input when submitting
/>
Comment on lines +44 to +51
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Consider adding required attribute to email input.

The email input has type="email" for format validation but lacks the required attribute. Users can currently submit the form with an empty email, which will fail at the backend validation. Adding required would provide immediate client-side feedback and improve UX.

📋 Suggested enhancement
                 <input
                     type="email"
                     value={email}
                     onChange={(e) => setEmail(e.target.value)}
                     id="email"
                     placeholder="Enter your email address"
+                    required
                     disabled={isSubmitting}
                 />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
id="email"
placeholder="Enter your email address"
disabled={isSubmitting} // 1. Freeze input when submitting
/>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
id="email"
placeholder="Enter your email address"
required
disabled={isSubmitting} // 1. Freeze input when submitting
/>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/BookEvent.tsx` around lines 44 - 51, Add the HTML required
attribute to the email input in the BookEvent component to enforce client-side
non-empty validation: update the <input> with id "email" (the one using
value={email}, onChange={e => setEmail(e.target.value)} and
disabled={isSubmitting}) to include required so the browser prevents empty
submissions before backend validation.

{/* 2. Show the red error message under the input if an error occurs */}
{error && <p className="text-red-500 text-xs mt-1">{error}</p>}
</div>

{/* 3. Disable the button and change text dynamically */}
<button type="submit" className="button-submit" disabled={isSubmitting}>
{isSubmitting ? "Submitting..." : "Submit"}
</button>
</form>
)}
</div>