Refactor RSVP form to improve guest input usability
All checks were successful
Build and Push Docker Images / changes (push) Successful in 5s
Build and Push Docker Images / build-backend (push) Has been skipped
Build and Push Docker Images / build-frontend (push) Successful in 1m10s

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:
2025-03-17 18:42:19 +01:00
parent 479cb7ade8
commit 0410d148d3

View File

@@ -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>