Refactor RSVP form to improve guest input usability
Added buttons to increment and decrement the number of guests for better user experience, particularly on mobile devices. Introduced direct numeric input handling to ensure valid input. Updated theme settings and adjusted styles for improved visual consistency.
This commit is contained in:
@@ -16,8 +16,9 @@ import {
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { RsvpStatus } from "@/client/types.gen";
|
||||
import { useSearchParams, useParams } from "next/navigation";
|
||||
import { Loader2 } from "lucide-react";
|
||||
import { Loader2, Plus, Minus } from "lucide-react";
|
||||
import { motion } from "framer-motion";
|
||||
import { useTheme } from "next-themes";
|
||||
|
||||
interface RSVPProps {
|
||||
eventId: string;
|
||||
@@ -44,6 +45,11 @@ export const RSVP: React.FC<RSVPProps> = ({ eventId, onRSVPSuccess }) => {
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [success, setSuccess] = useState<boolean>(false);
|
||||
const { setTheme } = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
setTheme("light");
|
||||
}, [setTheme]);
|
||||
|
||||
// Load event data based on slug or event ID
|
||||
useEffect(() => {
|
||||
@@ -119,6 +125,24 @@ export const RSVP: React.FC<RSVPProps> = ({ eventId, onRSVPSuccess }) => {
|
||||
}
|
||||
}, [searchParams, guests, findGuestByInvitationCode]);
|
||||
|
||||
// Handler for incrementing the number of guests
|
||||
const incrementGuests = () => {
|
||||
setNumberOfGuests((prev) => prev + 1);
|
||||
};
|
||||
|
||||
// Handler for decrementing the number of guests
|
||||
const decrementGuests = () => {
|
||||
setNumberOfGuests((prev) => Math.max(1, prev - 1));
|
||||
};
|
||||
|
||||
// Handler for direct number input
|
||||
const handleGuestsInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value === "" ? 1 : parseInt(e.target.value, 10);
|
||||
if (!isNaN(value)) {
|
||||
setNumberOfGuests(Math.max(1, value));
|
||||
}
|
||||
};
|
||||
|
||||
const submitRsvp = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -317,7 +341,7 @@ export const RSVP: React.FC<RSVPProps> = ({ eventId, onRSVPSuccess }) => {
|
||||
id="status"
|
||||
className="w-full"
|
||||
style={{
|
||||
borderColor: colors.backgroundDark,
|
||||
borderColor: colors.background,
|
||||
backgroundColor: "white",
|
||||
color: colors.text,
|
||||
}}
|
||||
@@ -328,12 +352,7 @@ export const RSVP: React.FC<RSVPProps> = ({ eventId, onRSVPSuccess }) => {
|
||||
{status === "maybe" && "Forse"}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent
|
||||
style={{
|
||||
backgroundColor: colors.background,
|
||||
borderColor: colors.backgroundDark,
|
||||
}}
|
||||
>
|
||||
<SelectContent className="data-[radix-select-content]:rounded-md data-[radix-select-content]:bg-[--event-background] data-[radix-select-content]:border-[--event-backgroundDark]">
|
||||
<SelectItem value="attending">Parteciperò</SelectItem>
|
||||
<SelectItem value="not_attending">Non parteciperò</SelectItem>
|
||||
<SelectItem value="maybe">Forse</SelectItem>
|
||||
@@ -349,20 +368,52 @@ export const RSVP: React.FC<RSVPProps> = ({ eventId, onRSVPSuccess }) => {
|
||||
>
|
||||
Numero di Ospiti
|
||||
</Label>
|
||||
<Input
|
||||
id="number_of_guests"
|
||||
type="number"
|
||||
min={1}
|
||||
value={number_of_guests}
|
||||
onChange={(e) =>
|
||||
setNumberOfGuests(Math.max(1, Number(e.target.value)))
|
||||
}
|
||||
style={{
|
||||
borderColor: colors.backgroundDark,
|
||||
backgroundColor: "white",
|
||||
color: colors.text,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Custom number input with buttons for better mobile experience */}
|
||||
<div className="flex items-center">
|
||||
<Button
|
||||
type="button"
|
||||
onClick={decrementGuests}
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="h-10 w-10 rounded-r-none"
|
||||
style={{
|
||||
borderColor: colors.backgroundDark,
|
||||
backgroundColor: "white",
|
||||
color: colors.text,
|
||||
}}
|
||||
>
|
||||
<Minus className="h-4 w-4" />
|
||||
</Button>
|
||||
<Input
|
||||
id="number_of_guests"
|
||||
type="text"
|
||||
inputMode="numeric"
|
||||
pattern="[0-9]*"
|
||||
value={number_of_guests}
|
||||
onChange={handleGuestsInputChange}
|
||||
className="h-10 rounded-none text-center"
|
||||
style={{
|
||||
borderColor: colors.backgroundDark,
|
||||
backgroundColor: "white",
|
||||
color: colors.text,
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={incrementGuests}
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="h-10 w-10 rounded-l-none"
|
||||
style={{
|
||||
borderColor: colors.backgroundDark,
|
||||
backgroundColor: "white",
|
||||
color: colors.text,
|
||||
}}
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-sm mt-1" style={{ color: colors.textLight }}>
|
||||
Quante persone (incluso te) parteciperanno?
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user