diff --git a/src/features/create-drop/components/ticket/AcceptPaymentForm.tsx b/src/features/create-drop/components/ticket/AcceptPaymentForm.tsx index 8e63c728..01503fe3 100644 --- a/src/features/create-drop/components/ticket/AcceptPaymentForm.tsx +++ b/src/features/create-drop/components/ticket/AcceptPaymentForm.tsx @@ -18,7 +18,7 @@ const STRIPE_PURCHASE_IMAGE = purchaseWithStripe.href.replace(purchaseWithStripe const contentItem = (title: string, subtitle: string) => { return ( - + {title} @@ -129,13 +129,7 @@ const AcceptPaymentForm = (props: EventStepFormProps) => { return ( - + Enable Stripe Checkout { )} - + Enable $NEAR Checkout { fontWeight="400" textAlign="left" > - Allow attendees to purchase tickets with $NEAR. Attendees will need a NEAR wallet. + Allow attendees to purchase tickets with $NEAR. The funds will go directly into your + wallet. - {contentItem( - 'Receive $NEAR', - 'Any earnings will be deposited directly into your NEAR wallet.', - )} - void; + isOpen: boolean; + prevEventData?: { + priceByDropId?: Record; + eventId: string; + stripeAccountId?: string; + }; +} + +export const EventCreationStatusModal = ({ + isOpen, + setIsOpen, + isSuccess, + prevEventData, +}: EventCreationStatusModalProps) => { + const [isSetting, setIsSetting] = useState(false); + const navigate = useNavigate(); + const toast = useToast(); + + const handlePostEventCreation = async () => { + if (isSuccess) { + setIsSetting(true); + + if (prevEventData?.stripeAccountId !== undefined) { + let response: Response | undefined; + try { + const url = `${EVENTS_WORKER_BASE}/stripe/create-event`; + const body = { + priceByDropId: prevEventData.priceByDropId, + stripeAccountId: prevEventData.stripeAccountId, + eventId: prevEventData.eventId, + }; + response = await fetch(url, { + method: 'POST', + body: JSON.stringify(body), + }); + } catch (error) { + return; + } + + if (!response?.ok) { + toast({ + title: 'Unable to upload event to stripe', + description: `Please delete the event and try again later. If the error persists, contact support.`, + status: 'error', + duration: 10000, + isClosable: true, + }); + } else { + localStorage.removeItem('EVENT_INFO_SUCCESS_DATA'); + } + } else { + localStorage.removeItem('EVENT_INFO_SUCCESS_DATA'); + } + setIsSetting(false); + navigate('/events'); + } else { + localStorage.removeItem('EVENT_INFO_SUCCESS_DATA'); + } + setIsOpen(); + }; + + const bodyMessage = () => { + if (!isSuccess) { + return 'Please try again later. If the error persists, contact support.'; + } + + if (prevEventData?.stripeAccountId !== undefined) { + return 'The last step is to upload the event details to stripe so that you can receive funds.'; + } + + return `You're all set! Your event has been created and you can view it in the events page.`; + }; + + const buttonMessage = () => { + if (!isSuccess) { + return 'Close'; + } + + if (prevEventData?.stripeAccountId !== undefined) { + return 'Upload to Stripe'; + } + + return 'View Event'; + }; + + return ( + { + console.log('close'); + }} + > + + + } // replace with your actual icon + left="50%" + overflow="visible !important" + position="absolute" + top={-6} // Half of the icon size to make it center on the edge + transform="translateX(-50%) translateY(-10%)" + variant="outline" + width="60px" + zIndex={1500} // Higher than ModalContent to overlap + /> + + {isSuccess ? 'Event Created Successfully' : 'Event Creation Failed'} + + + + + {bodyMessage()} + + + + + + + + + ); +}; diff --git a/src/features/create-drop/routes/CreateTicketDropPage.tsx b/src/features/create-drop/routes/CreateTicketDropPage.tsx index 40ddf678..02625fce 100644 --- a/src/features/create-drop/routes/CreateTicketDropPage.tsx +++ b/src/features/create-drop/routes/CreateTicketDropPage.tsx @@ -1,14 +1,19 @@ -import { Button, HStack } from '@chakra-ui/react'; +import { Button, HStack, useToast } from '@chakra-ui/react'; import { type ReactElement, useState, useEffect } from 'react'; import { type Action, type Wallet } from '@near-wallet-selector/core'; +import keypomInstance from '@/lib/keypom'; import { get } from '@/utils/localStorage'; import { type IBreadcrumbItem } from '@/components/Breadcrumbs'; import { IconBox } from '@/components/IconBox'; import { LinkIcon } from '@/components/Icons'; import { Step } from '@/components/Step'; import { useAuthWalletContext } from '@/contexts/AuthWalletContext'; -import { EVENTS_WORKER_BASE, KEYPOM_EVENTS_CONTRACT } from '@/constants/common'; +import { + EVENTS_WORKER_BASE, + KEYPOM_EVENTS_CONTRACT, + KEYPOM_MARKETPLACE_CONTRACT, +} from '@/constants/common'; import { CreateTicketDropLayout } from '../components/CreateTicketDropLayout'; import { CollectInfoForm } from '../components/ticket/CollectInfoForm'; @@ -29,6 +34,7 @@ import { serializeMediaForWorker, } from '../components/ticket/helpers'; import { AcceptPaymentForm } from '../components/ticket/AcceptPaymentForm'; +import { EventCreationStatusModal } from '../components/ticket/EventCreationStatusModal'; interface TicketStep { title: string; @@ -240,10 +246,18 @@ const placeholderData: TicketDropFormData = { export default function NewTicketDrop() { const [currentStep, setCurrentStep] = useState(0); const [isModalOpen, setIsModalOpen] = useState(false); + + const [eventCreationSuccess, setEventCreationSuccess] = useState(); + const [prevEventData, setPrevEventData] = useState< + | { priceByDropId?: Record; eventId: string; stripeAccountId?: string } + | undefined + >(); + const [isSettingKey, setIsSettingKey] = useState(false); const [formData, setFormData] = useState(placeholderData); const { selector, accountId } = useAuthWalletContext(); const [wallet, setWallet] = useState(); + const toast = useToast(); useEffect(() => { async function fetchWallet() { @@ -260,6 +274,32 @@ export default function NewTicketDrop() { fetchWallet(); }, [selector]); + useEffect(() => { + async function checkForEventCreation() { + const eventData = localStorage.getItem('EVENT_INFO_SUCCESS_DATA'); + + if (eventData) { + const { eventId, stripeAccountId, priceByDropId } = JSON.parse(eventData); + setPrevEventData({ priceByDropId, eventId, stripeAccountId }); + + try { + await keypomInstance.viewCall({ + contractId: KEYPOM_MARKETPLACE_CONTRACT, + methodName: 'get_event_information', + args: { event_id: eventId }, + }); + setEventCreationSuccess(true); + } catch (e) { + setEventCreationSuccess(false); + } + + localStorage.removeItem('EVENT_INFO_SUCCESS_DATA'); + } + } + + checkForEventCreation(); + }, []); + const handleClearForm = () => { switch (currentStep) { case 0: @@ -346,7 +386,9 @@ export default function NewTicketDrop() { eventId, priceByDropId, }; - localStorage.setItem('STRIPE_ACCOUNT_INFO', JSON.stringify(stripeAccountInfo)); + localStorage.setItem('EVENT_INFO_SUCCESS_DATA', JSON.stringify(stripeAccountInfo)); + } else { + localStorage.setItem('EVENT_INFO_SUCCESS_DATA', JSON.stringify({ eventId })); } await wallet.signAndSendTransaction({ @@ -354,6 +396,14 @@ export default function NewTicketDrop() { receiverId: KEYPOM_EVENTS_CONTRACT, actions, }); + } else { + toast({ + title: 'Unable to upload event images', + description: `Please try again later. If the error persists, contact support.`, + status: 'error', + duration: 5000, + isClosable: true, + }); } setIsSettingKey(false); }; @@ -408,6 +458,14 @@ export default function NewTicketDrop() { isSetting={isSettingKey} onModalClose={handleModalClose} /> + { + setEventCreationSuccess(undefined); + }} + />