Add gift registry page
This commit is contained in:
512
frontend/src/app/(public)/invite/[slug]/gifts/page.tsx
Normal file
512
frontend/src/app/(public)/invite/[slug]/gifts/page.tsx
Normal file
@@ -0,0 +1,512 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { useParams, useSearchParams } from "next/navigation";
|
||||||
|
import { useGifts } from "@/context/gift-context";
|
||||||
|
import { useGuests } from "@/context/guest-context";
|
||||||
|
import { GiftItem, GiftPurchase } from "@/client/types.gen";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { AlertCircle, ExternalLink, Gift, Loader2 } from "lucide-react";
|
||||||
|
|
||||||
|
export default function GiftRegistryPage() {
|
||||||
|
const { slug } = useParams<{ slug: string }>();
|
||||||
|
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const invitationCode = searchParams.get("code");
|
||||||
|
|
||||||
|
// States
|
||||||
|
const [activeTab, setActiveTab] = useState("available");
|
||||||
|
const [isReserving, setIsReserving] = useState(false);
|
||||||
|
const [selectedGift, setSelectedGift] = useState<GiftItem | null>(null);
|
||||||
|
const [quantity, setQuantity] = useState("1");
|
||||||
|
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
||||||
|
const [availableGifts, setAvailableGifts] = useState<GiftItem[]>([]);
|
||||||
|
const [reservedGifts, setReservedGifts] = useState<GiftItem[]>([]);
|
||||||
|
const [guestPurchases, setGuestPurchases] = useState<GiftPurchase[]>([]);
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
|
// Context hooks
|
||||||
|
const {
|
||||||
|
items,
|
||||||
|
isLoadingItems,
|
||||||
|
refetchItems,
|
||||||
|
reserveItem,
|
||||||
|
cancelReservation,
|
||||||
|
setCurrentEventId,
|
||||||
|
fetchPurchasesByGuest,
|
||||||
|
} = useGifts();
|
||||||
|
|
||||||
|
const { findGuestByInvitationCode, guests, isLoadingGuests } = useGuests();
|
||||||
|
|
||||||
|
// Find current guest based on invitation code
|
||||||
|
const currentGuest = invitationCode
|
||||||
|
? findGuestByInvitationCode(invitationCode)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
// Initialize when guest data is available
|
||||||
|
useEffect(() => {
|
||||||
|
if (isLoadingGuests || !invitationCode) return;
|
||||||
|
|
||||||
|
if (!currentGuest) {
|
||||||
|
setErrorMessage(
|
||||||
|
"Invalid invitation code. Please check your invitation link.",
|
||||||
|
);
|
||||||
|
setIsLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load event gifts
|
||||||
|
const eventId = currentGuest.event_id;
|
||||||
|
if (eventId) {
|
||||||
|
setCurrentEventId(eventId);
|
||||||
|
refetchItems(undefined, eventId)
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error fetching gifts:", error);
|
||||||
|
setErrorMessage(
|
||||||
|
"Unable to load gift registry. Please try again later.",
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fetch guest's purchases/reservations
|
||||||
|
fetchPurchasesByGuest(currentGuest.id)
|
||||||
|
.then((purchases) => {
|
||||||
|
if (purchases) {
|
||||||
|
setGuestPurchases(purchases);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error fetching guest purchases:", error);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setErrorMessage("No event found for this invitation.");
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
currentGuest,
|
||||||
|
invitationCode,
|
||||||
|
isLoadingGuests,
|
||||||
|
refetchItems,
|
||||||
|
setCurrentEventId,
|
||||||
|
fetchPurchasesByGuest,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Process gifts into available and reserved categories
|
||||||
|
useEffect(() => {
|
||||||
|
if (items && guestPurchases.length >= 0) {
|
||||||
|
// Get IDs of gifts that this guest has reserved
|
||||||
|
const reservedGiftIds = new Set(
|
||||||
|
guestPurchases.map((purchase) => purchase.gift_id),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Available gifts (visible and not fully reserved)
|
||||||
|
const available = items.filter(
|
||||||
|
(item) =>
|
||||||
|
item.is_visible &&
|
||||||
|
!reservedGiftIds.has(item.id) &&
|
||||||
|
(item.status === "available" ||
|
||||||
|
(item.quantity_requested &&
|
||||||
|
item.quantity_received &&
|
||||||
|
item.quantity_received < item.quantity_requested)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Reserved gifts (this guest has reserved them)
|
||||||
|
const reserved = items.filter((item) => reservedGiftIds.has(item.id));
|
||||||
|
|
||||||
|
setAvailableGifts(available);
|
||||||
|
setReservedGifts(reserved);
|
||||||
|
}
|
||||||
|
}, [items, guestPurchases]);
|
||||||
|
|
||||||
|
// Format priority for display
|
||||||
|
const formatPriority = (priority: string) => {
|
||||||
|
switch (priority) {
|
||||||
|
case "must_have":
|
||||||
|
return {
|
||||||
|
label: "Must Have",
|
||||||
|
color: "bg-red-100 text-red-800 border-red-200",
|
||||||
|
};
|
||||||
|
case "high":
|
||||||
|
return {
|
||||||
|
label: "High",
|
||||||
|
color: "bg-orange-100 text-orange-800 border-orange-200",
|
||||||
|
};
|
||||||
|
case "medium":
|
||||||
|
return {
|
||||||
|
label: "Medium",
|
||||||
|
color: "bg-blue-100 text-blue-800 border-blue-200",
|
||||||
|
};
|
||||||
|
case "low":
|
||||||
|
return {
|
||||||
|
label: "Low",
|
||||||
|
color: "bg-green-100 text-green-800 border-green-200",
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return {
|
||||||
|
label: priority,
|
||||||
|
color: "bg-gray-100 text-gray-800 border-gray-200",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reserve gift handler
|
||||||
|
const handleReserveClick = (gift: GiftItem) => {
|
||||||
|
setSelectedGift(gift);
|
||||||
|
setQuantity("1");
|
||||||
|
setIsReserving(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove reservation handler
|
||||||
|
const handleRemoveReservation = async (gift: GiftItem) => {
|
||||||
|
if (!currentGuest) {
|
||||||
|
setErrorMessage("Guest information not found.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await cancelReservation(gift.id, currentGuest.id);
|
||||||
|
|
||||||
|
// Refresh data
|
||||||
|
if (currentGuest.event_id) {
|
||||||
|
await refetchItems(undefined, currentGuest.event_id);
|
||||||
|
const updatedPurchases = await fetchPurchasesByGuest(currentGuest.id);
|
||||||
|
if (updatedPurchases) {
|
||||||
|
setGuestPurchases(updatedPurchases);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error removing reservation:", error);
|
||||||
|
setErrorMessage("Unable to remove reservation. Please try again.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Confirm reservation handler
|
||||||
|
const handleConfirmReservation = async () => {
|
||||||
|
console.debug("Confirm reservation:", currentGuest);
|
||||||
|
if (!selectedGift || !currentGuest) {
|
||||||
|
console.error("Missing information ", { selectedGift, currentGuest });
|
||||||
|
setErrorMessage("Required information missing.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log("Reserving: ", { selectedGift, currentGuest });
|
||||||
|
|
||||||
|
try {
|
||||||
|
await reserveItem(
|
||||||
|
selectedGift.id,
|
||||||
|
currentGuest.id,
|
||||||
|
parseInt(quantity, 10),
|
||||||
|
);
|
||||||
|
setIsReserving(false);
|
||||||
|
|
||||||
|
// Refresh data
|
||||||
|
if (currentGuest.event_id) {
|
||||||
|
await refetchItems(undefined, currentGuest.event_id);
|
||||||
|
const updatedPurchases = await fetchPurchasesByGuest(currentGuest.id);
|
||||||
|
if (updatedPurchases) {
|
||||||
|
setGuestPurchases(updatedPurchases);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error reserving gift:", error);
|
||||||
|
setErrorMessage("Unable to reserve gift. Please try again.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get reservation quantity for a gift
|
||||||
|
const getReservationQuantity = (gift: GiftItem): number => {
|
||||||
|
const purchase = guestPurchases.find((p) => p.gift_id === gift.id);
|
||||||
|
return purchase?.quantity || 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate quantity options for the dialog
|
||||||
|
const getQuantityOptions = (gift: GiftItem) => {
|
||||||
|
if (!gift.quantity_requested) return [1]; // Default to 1 if no quantity specified
|
||||||
|
|
||||||
|
const remaining = gift.quantity_requested - (gift.quantity_received || 0);
|
||||||
|
return Array.from(
|
||||||
|
{ length: remaining > 0 ? remaining : 1 },
|
||||||
|
(_, i) => i + 1,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Loading state
|
||||||
|
if (isLoading || isLoadingGuests || isLoadingItems) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center justify-center min-h-[300px] p-8">
|
||||||
|
<Loader2 className="h-8 w-8 animate-spin text-primary mb-4" />
|
||||||
|
<p className="text-muted-foreground">Loading gift registry...</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error state
|
||||||
|
if (errorMessage) {
|
||||||
|
return (
|
||||||
|
<div className="p-8">
|
||||||
|
<Alert variant="destructive">
|
||||||
|
<AlertCircle className="h-4 w-4" />
|
||||||
|
<AlertTitle>Error</AlertTitle>
|
||||||
|
<AlertDescription>{errorMessage}</AlertDescription>
|
||||||
|
</Alert>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="container max-w-4xl mx-auto px-4 py-8">
|
||||||
|
<div className="flex flex-col items-center mb-8">
|
||||||
|
<h1 className="text-3xl font-bold mb-2 text-center">
|
||||||
|
Gift Registry 🎁
|
||||||
|
</h1>
|
||||||
|
<p className="text-muted-foreground text-center">
|
||||||
|
Choose a gift from the wishlist to help celebrate Emma's 1st birthday
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Tabs
|
||||||
|
defaultValue="available"
|
||||||
|
value={activeTab}
|
||||||
|
onValueChange={setActiveTab}
|
||||||
|
className="w-full"
|
||||||
|
>
|
||||||
|
<TabsList className="grid w-full grid-cols-2 mb-6">
|
||||||
|
<TabsTrigger value="available" className="text-base">
|
||||||
|
Available Gifts
|
||||||
|
</TabsTrigger>
|
||||||
|
<TabsTrigger value="reserved" className="text-base">
|
||||||
|
Your Reservations{" "}
|
||||||
|
{reservedGifts.length > 0 && `(${reservedGifts.length})`}
|
||||||
|
</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
<TabsContent value="available">
|
||||||
|
{availableGifts.length === 0 ? (
|
||||||
|
<Alert>
|
||||||
|
<AlertTitle>No Available Gifts</AlertTitle>
|
||||||
|
<AlertDescription>
|
||||||
|
All gifts have been reserved or there are no gifts available at
|
||||||
|
this time.
|
||||||
|
</AlertDescription>
|
||||||
|
</Alert>
|
||||||
|
) : (
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>Name</TableHead>
|
||||||
|
<TableHead>Priority</TableHead>
|
||||||
|
<TableHead>Link</TableHead>
|
||||||
|
<TableHead>Description</TableHead>
|
||||||
|
<TableHead></TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{availableGifts.map((gift) => {
|
||||||
|
const priority = formatPriority(gift.priority || "medium");
|
||||||
|
return (
|
||||||
|
<TableRow key={gift.id}>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{gift.name}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Badge variant="outline" className={priority.color}>
|
||||||
|
{priority.label}
|
||||||
|
</Badge>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
{gift.purchase_url ? (
|
||||||
|
<a
|
||||||
|
href={gift.purchase_url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center text-primary hover:underline"
|
||||||
|
>
|
||||||
|
<ExternalLink size={14} className="mr-1" />
|
||||||
|
View Store
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<span className="text-muted-foreground text-sm">
|
||||||
|
None
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{gift.description || ""}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
onClick={() => handleReserveClick(gift)}
|
||||||
|
>
|
||||||
|
<Gift className="h-4 w-4 mr-1" />
|
||||||
|
Reserve
|
||||||
|
</Button>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="reserved">
|
||||||
|
{reservedGifts.length === 0 ? (
|
||||||
|
<Alert>
|
||||||
|
<AlertTitle>No Reservations</AlertTitle>
|
||||||
|
<AlertDescription>
|
||||||
|
You haven't reserved any gifts yet. Switch to the "Available
|
||||||
|
Gifts" tab to make a selection.
|
||||||
|
</AlertDescription>
|
||||||
|
</Alert>
|
||||||
|
) : (
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>Name</TableHead>
|
||||||
|
<TableHead>Priority</TableHead>
|
||||||
|
<TableHead>Link</TableHead>
|
||||||
|
<TableHead>Quantity</TableHead>
|
||||||
|
<TableHead>Description</TableHead>
|
||||||
|
<TableHead></TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{reservedGifts.map((gift) => {
|
||||||
|
const priority = formatPriority(gift.priority || "medium");
|
||||||
|
const quantity = getReservationQuantity(gift);
|
||||||
|
return (
|
||||||
|
<TableRow key={gift.id}>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{gift.name}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Badge variant="outline" className={priority.color}>
|
||||||
|
{priority.label}
|
||||||
|
</Badge>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
{gift.purchase_url ? (
|
||||||
|
<a
|
||||||
|
href={gift.purchase_url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center text-primary hover:underline"
|
||||||
|
>
|
||||||
|
<ExternalLink size={14} className="mr-1" />
|
||||||
|
View Store
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<span className="text-muted-foreground text-sm">
|
||||||
|
None
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{quantity}</TableCell>
|
||||||
|
<TableCell>{gift.description || ""}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => handleRemoveReservation(gift)}
|
||||||
|
>
|
||||||
|
Remove
|
||||||
|
</Button>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
{/* Reservation Dialog */}
|
||||||
|
<Dialog open={isReserving} onOpenChange={setIsReserving}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Reserve Gift</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
{selectedGift?.name} - {selectedGift?.description}
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
|
||||||
|
<div className="py-4">
|
||||||
|
<div className="mb-4">
|
||||||
|
<label className="block text-sm font-medium mb-1">
|
||||||
|
How many would you like to reserve?
|
||||||
|
</label>
|
||||||
|
<Select value={quantity} onValueChange={setQuantity}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select quantity" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{selectedGift &&
|
||||||
|
getQuantityOptions(selectedGift).map((num) => (
|
||||||
|
<SelectItem key={num} value={num.toString()}>
|
||||||
|
{num}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{selectedGift?.purchase_url && (
|
||||||
|
<div className="mt-4 p-3 bg-muted rounded-md text-sm">
|
||||||
|
<p className="font-medium mb-1">Where to buy:</p>
|
||||||
|
<a
|
||||||
|
href={selectedGift.purchase_url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-primary inline-flex items-center hover:underline"
|
||||||
|
>
|
||||||
|
<ExternalLink size={14} className="mr-1" />
|
||||||
|
Visit Store
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<DialogFooter>
|
||||||
|
<Button variant="outline" onClick={() => setIsReserving(false)}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleConfirmReservation}>
|
||||||
|
Confirm Reservation
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -8,8 +8,9 @@ import { Loader2 } from "lucide-react";
|
|||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { RSVPModal } from "@/components/rsvp/rsvp-modal";
|
import { RSVPModal } from "@/components/rsvp/rsvp-modal";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams, useSearchParams } from "next/navigation";
|
||||||
import { getServerFileUrl } from "@/lib/utils";
|
import { getServerFileUrl } from "@/lib/utils";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
// Helper function to get server file URL (assuming it exists in your codebase)
|
// Helper function to get server file URL (assuming it exists in your codebase)
|
||||||
// If not, replace with your actual implementation
|
// If not, replace with your actual implementation
|
||||||
@@ -20,6 +21,7 @@ const InvitationPage = () => {
|
|||||||
const [showRSVP, setShowRSVP] = useState(false);
|
const [showRSVP, setShowRSVP] = useState(false);
|
||||||
const { themes, isLoadingThemes } = useEventThemes();
|
const { themes, isLoadingThemes } = useEventThemes();
|
||||||
const guestId = "current-guest-id-placeholder";
|
const guestId = "current-guest-id-placeholder";
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
|
||||||
// Fetch event data when slug is available
|
// Fetch event data when slug is available
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -160,6 +162,8 @@ const InvitationPage = () => {
|
|||||||
const foregroundImageUrl = getServerFileUrl(eventTheme?.foreground_image_url);
|
const foregroundImageUrl = getServerFileUrl(eventTheme?.foreground_image_url);
|
||||||
const backgroundImageUrl = getServerFileUrl(eventTheme?.background_image_url);
|
const backgroundImageUrl = getServerFileUrl(eventTheme?.background_image_url);
|
||||||
const threeAnimalsImgUrl = getAssetUrl("three-animals");
|
const threeAnimalsImgUrl = getAssetUrl("three-animals");
|
||||||
|
const invitationCode = searchParams.get("code");
|
||||||
|
const giftRegistryPageUrl = `/invite/${slug}/gifts?code=${invitationCode}`;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="min-h-screen overflow-hidden pb-10 pt-0"
|
className="min-h-screen overflow-hidden pb-10 pt-0"
|
||||||
@@ -395,6 +399,7 @@ const InvitationPage = () => {
|
|||||||
color: "white",
|
color: "white",
|
||||||
}}
|
}}
|
||||||
onClick={() => setShowRSVP(true)}
|
onClick={() => setShowRSVP(true)}
|
||||||
|
disabled={!invitationCode}
|
||||||
>
|
>
|
||||||
PRESENZA
|
PRESENZA
|
||||||
</Button>
|
</Button>
|
||||||
@@ -415,9 +420,9 @@ const InvitationPage = () => {
|
|||||||
backgroundColor: colors.secondary,
|
backgroundColor: colors.secondary,
|
||||||
color: "white",
|
color: "white",
|
||||||
}}
|
}}
|
||||||
onClick={() => window.open(`/gifts/${slug}`, "_blank")}
|
disabled={!invitationCode}
|
||||||
>
|
>
|
||||||
LISTA REGALI
|
<Link href={giftRegistryPageUrl}>LISTA REGALI</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user