Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature(unlock-app): Improve UX for asynchronous event creation #15279

Merged
merged 5 commits into from
Dec 18, 2024
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
128 changes: 73 additions & 55 deletions unlock-app/src/components/content/event/LockDeploying.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import { Button } from '@unlock-protocol/ui'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { FiExternalLink as ExternalLinkIcon } from 'react-icons/fi'
import {
AnimationContent,
DeployStatus,
} from '~/components/interface/locks/Create/elements/CreateLockFormSummary'
import { AnimationContent } from '~/components/interface/locks/Create/elements/CreateLockFormSummary'
import { useConfig } from '~/utils/withConfig'
import { TransactionDetails } from './NewEvent'
import { useEffect, useState } from 'react'
Expand All @@ -26,91 +23,112 @@ export const LockDeploying = ({
const config = useConfig()
const router = useRouter()
const [loadingEventPage, setLoadingEventPage] = useState(false)
const [eventData, setEventData] = useState<{
status: EventStatus
}>({
status: EventStatus.PENDING,
})
const [eventStatus, setEventStatus] = useState<EventStatus>(
EventStatus.PENDING
)
const { hash: transactionHash, network, slug } = transactionDetails

// Poll for event status every 2 seconds
useInterval(async () => {
if (slug) {
const { data: event } = await locksmith.getEvent(slug)
setEventData({
status: event.data?.status as EventStatus,
})
const [title, setTitle] = useState('Waiting for your transaction to be mined')
const [message, setMessage] = useState(
compact
? 'Please do not close this drawer'
: 'Please do not close this window'
)

// Update title and message when event is deployed
useEffect(() => {
if (eventStatus === EventStatus.DEPLOYED) {
setTitle('🚀​ Your contract was successfully deployed')
setMessage(
'Did you know that you can airdrop tickets to your fren by sending them email?'
)
}
}, 2000)
}, [eventStatus])

let status: DeployStatus = 'progress'
let title = 'Waiting for your transaction to be mined'
let message = compact
? 'Please do not close this drawer'
: 'Please do not close this window'
// Poll for event status every 5 seconds
useInterval(
async () => {
if (!slug) return
try {
const { data: event } = await locksmith.getEvent(slug)
// @ts-ignore
setEventStatus(event.status as EventStatus)
} catch (error) {
console.error('Failed to fetch event status:', error)
}
},
eventStatus === EventStatus.DEPLOYED ? null : 5000
)

// Scroll to top on mount
useEffect(() => {
window?.scrollTo(0, 0)
}, [])

if (eventData.status === EventStatus.DEPLOYED) {
status = 'deployed'
title = '🚀​ Your contract was successfully deployed'
message =
'Did you know that you can airdrop tickets to your fren by sending them email?'
const goToEventPage = () => {
if (!slug) return
setLoadingEventPage(true)
router.push(
getEventPath({
event: { slug },
})
)
}

const goToEventPage = () => {
if (slug) {
setLoadingEventPage(true)
router.push(
getEventPath({
event: {
slug,
},
})
)
}
const renderBlockExplorerLink = () => {
const explorerUrl = config.networks[network].explorer?.urls?.transaction
if (!explorerUrl) return null

return (
<Link
target="_blank"
rel="noopener noreferrer"
className={`inline-flex items-center gap-3 mt-3 font-bold lg:mt-auto lg:ml-auto text-brand-ui-primary ${
compact ? 'text-base' : 'text-lg'
}`}
href={explorerUrl(transactionHash)}
>
View on block explorer
<ExternalLinkIcon size={compact ? 16 : 20} />
</Link>
)
}

return (
<div>
<div className="flex flex-col items-stretch p-4 border border-gray-400 rounded-xl">
<AnimationContent status={status} />
<AnimationContent
status={
eventStatus === EventStatus.DEPLOYED ? 'deployed' : 'progress'
}
/>
<div className="grid grid-cols-1 lg:grid-cols-2">
<div className="flex flex-col">
<span className={`text-base ${compact ? 'text-sm' : ''}`}>
Status
</span>
<span className={`font-bold ${compact ? 'text-base' : 'text-lg'}`}>
{status === 'progress' ? 'In progress...' : 'Deployed'}
{eventStatus === EventStatus.DEPLOYED
? 'Deployed'
: 'In progress...'}
</span>
</div>
{config.networks[network].explorer?.urls?.transaction && (
<Link
target="_blank"
rel="noopener noreferrer"
className={`inline-flex items-center gap-3 mt-3 font-bold lg:mt-auto lg:ml-auto text-brand-ui-primary ${compact ? 'text-base' : 'text-lg'}`}
href={config.networks[network].explorer.urls.transaction(
transactionHash
)}
>
View on block explorer
<ExternalLinkIcon size={compact ? 16 : 20} />
</Link>
)}
{renderBlockExplorerLink()}
</div>
</div>

<div className="flex flex-col items-center my-12 text-center">
<h3
className={`block mb-4 font-bold ${compact ? 'text-xl md:text-2xl' : 'text-2xl md:text-4xl'}`}
className={`block mb-4 font-bold ${
compact ? 'text-xl md:text-2xl' : 'text-2xl md:text-4xl'
}`}
>
{title}
</h3>
<span className={`mb-4 font-base ${compact ? 'text-sm' : ''}`}>
{message}
</span>
{status === 'deployed' && !compact && (
{eventStatus === EventStatus.DEPLOYED && !compact && (
<div className="flex flex-col items-center content-center text-center">
<p>We made a page for your event! Go check it out!</p>
<Button
Expand Down
Loading