Files
Joshen Lim 22b3419a28 Extract project creation form into its own component (#47957)
## Context

This is just a pre-requisite to consolidating the project creation UI as
there's another page that has the project creation flow too
[here](https://github.com/supabase/supabase/blob/master/apps/studio/pages/integrations/vercel/%5Bslug%5D/deploy-button/new-project.tsx).
So the next step will just be to use the same `ProjectCreationForm`
there

No functional changes here - just moving things around

## To test
- [ ] Verify that project creation still works



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a full “create project” experience with eligibility-aware
defaults, advanced configuration sections, optional GitHub integration,
and compute-cost confirmation when applicable.
* **Improvements**
  * Enhanced project-creation success/error handling and navigation.
* Refined CLI backup/restore dialogs (better layout/wording,
accessibility updates, and improved section separation).
* **Documentation**
* Standardized all relevant documentation links across the app using a
shared `DOCS_URL` source.
* **Refactor**
* Refactored the “New Project” page to delegate the wizard UI and flow
to a reusable creation component.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-16 14:00:55 +08:00

125 lines
5.1 KiB
TypeScript

import { useParams } from 'common'
import { ExternalLink } from 'lucide-react'
import Link from 'next/link'
import { Alert, AlertDescription, AlertTitle, Button, WarningIcon } from 'ui'
import {
PageSection,
PageSectionContent,
PageSectionDescription,
PageSectionMeta,
PageSectionSummary,
PageSectionTitle,
} from 'ui-patterns/PageSection'
import { getPhoneProviderValidationSchema, PROVIDERS_SCHEMAS } from '../AuthProvidersFormValidation'
import type { Provider } from './AuthProvidersForm.types'
import { ProviderForm } from './ProviderForm'
import { AlertError } from '@/components/ui/AlertError'
import { ResourceList } from '@/components/ui/Resource/ResourceList'
import { HorizontalShimmerWithIcon } from '@/components/ui/Shimmers'
import { useAuthConfigQuery } from '@/data/auth/auth-config-query'
import { DOCS_URL } from '@/lib/constants'
export const AuthProvidersForm = () => {
const { ref: projectRef } = useParams()
const {
data: authConfig,
error: authConfigError,
isPending: isLoading,
isError,
isSuccess,
} = useAuthConfigQuery({ projectRef })
return (
<PageSection>
<PageSectionMeta>
<PageSectionSummary>
<PageSectionTitle>Auth Providers</PageSectionTitle>
<PageSectionDescription>
Authenticate your users through a suite of providers and login methods
</PageSectionDescription>
</PageSectionSummary>
</PageSectionMeta>
<PageSectionContent>
{isError ? (
<AlertError
error={authConfigError}
subject="Failed to retrieve auth configuration for hooks"
/>
) : (
<div className="-space-y-px">
{authConfig?.EXTERNAL_EMAIL_ENABLED && authConfig?.MAILER_OTP_EXP > 3600 && (
<Alert className="flex w-full items-center justify-between my-3" variant="warning">
<WarningIcon />
<div>
<AlertTitle>OTP expiry exceeds recommended threshold</AlertTitle>
<AlertDescription className="flex flex-col gap-y-3">
<p>
We have detected that you have enabled the email provider with the OTP expiry
set to more than an hour. It is recommended to set this value to less than an
hour.
</p>
<Button asChild variant="default" className="w-min" icon={<ExternalLink />}>
<Link href={`${DOCS_URL}/guides/platform/going-into-prod#security`}>
View security recommendations
</Link>
</Button>
</AlertDescription>
</div>
</Alert>
)}
<ResourceList>
{isLoading &&
PROVIDERS_SCHEMAS.map((provider) => (
<div
key={`provider_${provider.title}`}
className="py-4 px-6 border-b last:border-b-none"
>
<HorizontalShimmerWithIcon />
</div>
))}
{isSuccess &&
PROVIDERS_SCHEMAS.map((provider) => {
const providerSchema =
provider.title === 'Phone'
? {
...provider,
validationSchema: getPhoneProviderValidationSchema(authConfig),
}
: provider
let isActive = false
if (providerSchema.title === 'SAML 2.0') {
isActive = authConfig && authConfig['SAML_ENABLED']
} else if (providerSchema.title === 'LinkedIn (OIDC)') {
isActive = authConfig && authConfig['EXTERNAL_LINKEDIN_OIDC_ENABLED']
} else if (providerSchema.title === 'Slack (OIDC)') {
isActive = authConfig && authConfig['EXTERNAL_SLACK_OIDC_ENABLED']
} else if (providerSchema.title.includes('Web3')) {
isActive = authConfig && authConfig['EXTERNAL_WEB3_SOLANA_ENABLED']
} else if (providerSchema.title.includes('X / Twitter (OAuth 2.0)')) {
isActive = authConfig && (authConfig as any)['EXTERNAL_X_ENABLED']
} else if (providerSchema.title === 'Twitter (Deprecated)') {
isActive = authConfig && authConfig['EXTERNAL_TWITTER_ENABLED']
} else {
isActive =
authConfig &&
(authConfig as any)[`EXTERNAL_${providerSchema.title.toUpperCase()}_ENABLED`]
}
return (
<ProviderForm
key={`provider_${providerSchema.title}`}
config={authConfig!}
provider={providerSchema as unknown as Provider}
isActive={isActive}
/>
)
})}
</ResourceList>
</div>
)}
</PageSectionContent>
</PageSection>
)
}