Files
supabase/apps/studio/pages/new/index.tsx
Joshen Lim 0f4fc7eee9 Chore/projects pagination part 04 (#39348)
* CmdK OrgProjectSwitcher to swap useProjectsQuery with useProjectsInfiniteQuery

* Remove usage of useProjectsQuery in ProjectDropdown

* Remove usage of useProjectsQuery in NotificationsPopover

* Remove usage of useProjectsQuery in NotificationsFilter

* Remove usage of useProjectsQuery from LoadingState

* Clean

* Remove usage of getProjects from org-ai-details and fix missing key props in AIOnboarding

* Remove useAutoProjectsPrefetch from org/[slug]/index

* Fix TS  + clean up

* Clean

* Remove usage of useProjectsQuery in NewOrgForm
2025-10-08 21:42:49 +08:00

109 lines
2.9 KiB
TypeScript

import HCaptcha from '@hcaptcha/react-hcaptcha'
import { useCallback, useEffect, useState } from 'react'
import { NewOrgForm } from 'components/interfaces/Organization/NewOrg/NewOrgForm'
import AppLayout from 'components/layouts/AppLayout/AppLayout'
import DefaultLayout from 'components/layouts/DefaultLayout'
import WizardLayout from 'components/layouts/WizardLayout'
import { SetupIntentResponse, useSetupIntent } from 'data/stripe/setup-intent-mutation'
import type { NextPageWithLayout } from 'types'
/**
* No org selected yet, create a new one
*/
const Wizard: NextPageWithLayout = () => {
const [intent, setIntent] = useState<SetupIntentResponse>()
const [captchaToken, setCaptchaToken] = useState<string | null>(null)
const [captchaRef, setCaptchaRef] = useState<HCaptcha | null>(null)
const [selectedPlan, setSelectedPlan] = useState<string | null>(null)
const { mutate: setupIntent } = useSetupIntent({ onSuccess: (res) => setIntent(res) })
const captchaRefCallback = useCallback((node: any) => {
setCaptchaRef(node)
}, [])
const initSetupIntent = async (hcaptchaToken: string | undefined) => {
if (!hcaptchaToken) return console.error('Hcaptcha token is required')
// Force a reload of Elements, necessary for Stripe
// Also mitigates card testing to some extent as we generate a new captcha token
setIntent(undefined)
setupIntent({ hcaptchaToken })
}
const loadPaymentForm = async (force = false) => {
if (selectedPlan == null || selectedPlan === 'FREE') return
if (intent != null && !force) return
if (captchaRef) {
let token = captchaToken
try {
if (!token) {
const captchaResponse = await captchaRef.execute({ async: true })
token = captchaResponse?.response ?? null
}
} catch (error) {
return
}
await initSetupIntent(token ?? undefined)
resetCaptcha()
}
}
useEffect(() => {
loadPaymentForm()
}, [captchaRef, selectedPlan])
const resetSetupIntent = () => {
setIntent(undefined)
return loadPaymentForm(true)
}
const onLocalCancel = () => {
setIntent(undefined)
}
const resetCaptcha = () => {
setCaptchaToken(null)
captchaRef?.resetCaptcha()
}
return (
<>
<HCaptcha
ref={captchaRefCallback}
sitekey={process.env.NEXT_PUBLIC_HCAPTCHA_SITE_KEY!}
size="invisible"
onVerify={(token) => {
setCaptchaToken(token)
}}
onClose={onLocalCancel}
onExpire={() => {
setCaptchaToken(null)
}}
/>
<NewOrgForm
setupIntent={intent}
onPaymentMethodReset={() => resetSetupIntent()}
onPlanSelected={(plan) => setSelectedPlan(plan)}
/>
</>
)
}
Wizard.getLayout = (page) => (
<AppLayout>
<DefaultLayout headerTitle="New organization">
<WizardLayout>{page}</WizardLayout>
</DefaultLayout>
</AppLayout>
)
export default Wizard