diff --git a/apps/studio/components/interfaces/Organization/NewOrg/NewOrgForm.tsx b/apps/studio/components/interfaces/Organization/NewOrg/NewOrgForm.tsx index 20e307dc5aaba..b2fd21acacb54 100644 --- a/apps/studio/components/interfaces/Organization/NewOrg/NewOrgForm.tsx +++ b/apps/studio/components/interfaces/Organization/NewOrg/NewOrgForm.tsx @@ -2,10 +2,9 @@ import { zodResolver } from '@hookform/resolvers/zod' import { Elements } from '@stripe/react-stripe-js' import type { PaymentIntentResult, PaymentMethod, StripeElementsOptions } from '@stripe/stripe-js' import { loadStripe } from '@stripe/stripe-js' -import _ from 'lodash' +import { groupBy } from 'lodash' import { HelpCircle } from 'lucide-react' import { useTheme } from 'next-themes' -import Link from 'next/link' import { useRouter } from 'next/router' import { parseAsBoolean, parseAsString, useQueryStates } from 'nuqs' import { useEffect, useMemo, useRef, useState } from 'react' @@ -16,6 +15,10 @@ import { z } from 'zod' import { LOCAL_STORAGE_KEYS } from 'common' import { getStripeElementsAppearanceOptions } from 'components/interfaces/Billing/Payment/Payment.utils' import { PaymentConfirmation } from 'components/interfaces/Billing/Payment/PaymentConfirmation' +import { + NewPaymentMethodElement, + type PaymentMethodElementRef, +} from 'components/interfaces/Billing/Payment/PaymentMethods/NewPaymentMethodElement' import SpendCapModal from 'components/interfaces/Billing/SpendCapModal' import { InlineLink } from 'components/ui/InlineLink' import Panel from 'components/ui/Panel' @@ -41,16 +44,9 @@ import { SelectTrigger_Shadcn_, SelectValue_Shadcn_, Switch, - Tooltip, - TooltipContent, - TooltipTrigger, } from 'ui' -import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' -import { - NewPaymentMethodElement, - type PaymentMethodElementRef, -} from '../../Billing/Payment/PaymentMethods/NewPaymentMethodElement' +import { UpgradeExistingOrganizationCallout } from './UpgradeExistingOrganizationCallout' const ORG_KIND_TYPES = { PERSONAL: 'Personal', @@ -132,12 +128,9 @@ export const NewOrgForm = ({ // in onSubmit below, which isn't a critical functionality imo so am okay for now. But ideally perhaps this data can // be computed on the API and returned in /profile or something (since this data is on the account level) const projectsByOrg = useMemo(() => { - return _.groupBy(projects, 'organization_slug') + return groupBy(projects, 'organization_slug') }, [projects]) - const [isOrgCreationConfirmationModalVisible, setIsOrgCreationConfirmationModalVisible] = - useState(false) - const stripeOptionsPaymentMethod: StripeElementsOptions = useMemo( () => ({ @@ -198,6 +191,11 @@ export const NewOrgForm = ({ const [showSpendCapHelperModal, setShowSpendCapHelperModal] = useState(false) const [paymentIntentSecret, setPaymentIntentSecret] = useState(null) + const hasFreeOrgWithProjects = useMemo( + () => freeOrgs.some((it) => projectsByOrg[it.slug]?.length > 0), + [freeOrgs, projectsByOrg] + ) + const { mutate: createOrganization } = useOrganizationCreateMutation({ onSuccess: async (org) => { if ('pending_payment_intent_secret' in org && org.pending_payment_intent_secret) { @@ -299,13 +297,6 @@ export const NewOrgForm = ({ const paymentRef = useRef(null) const onSubmit: SubmitHandler> = async (formValues) => { - const hasFreeOrgWithProjects = freeOrgs.some((it) => projectsByOrg[it.slug]?.length > 0) - - if (hasFreeOrgWithProjects && formValues.plan !== 'FREE') { - setIsOrgCreationConfirmationModalVisible(true) - return - } - setNewOrgLoading(true) if (formValues.plan === 'FREE') { @@ -478,15 +469,7 @@ export const NewOrgForm = ({ description={ <> Which plan fits your organization's needs best?{' '} - - Learn more - - . + Learn more. } > @@ -569,86 +552,13 @@ export const NewOrgForm = ({ )} + + {hasFreeOrgWithProjects && form.getValues('plan') !== 'FREE' && ( + + )} - setIsOrgCreationConfirmationModalVisible(false)} - onConfirm={async () => { - await onSubmit(form.getValues()) - setIsOrgCreationConfirmationModalVisible(false) - }} - variant={'warning'} - > -

- Supabase{' '} - - bills per organization - - . If you want to upgrade your existing projects, upgrade your existing organization - instead. -

- -
    - {freeOrgs - .filter((it) => projectsByOrg[it.slug]?.length > 0) - .map((org) => { - const orgProjects = projectsByOrg[org.slug].map((it) => it.name) - - return ( -
  • -
    -

    {org.name}

    - -
    - {orgProjects.length <= 2 ? ( - {orgProjects.join(' and ')} - ) : ( -
    - {orgProjects.slice(0, 2).join(', ')} and{' '} - - - - {orgProjects.length - 2} other{' '} - {orgProjects.length === 3 ? 'project' : 'project'} - - - -
      - {orgProjects.slice(2).map((project) => ( -
    • {project}
    • - ))} -
    -
    -
    -
    - )} -
    -
    - -
  • - ) - })} -
-
- {stripePromise && paymentIntentSecret && paymentMethod && ( { + return ( + + +

+ Supabase{' '} + + bills per organization + + . If you want to upgrade your existing projects,{' '} + + upgrade your existing organization + {' '} + instead. +

+ + } + /> +
+ ) +} diff --git a/apps/studio/pages/new/[slug].tsx b/apps/studio/pages/new/[slug].tsx index 5d1782ce87b58..d177c1220a25a 100644 --- a/apps/studio/pages/new/[slug].tsx +++ b/apps/studio/pages/new/[slug].tsx @@ -43,7 +43,6 @@ import { ProjectCreateVariables, useProjectCreateMutation, } from 'data/projects/project-create-mutation' -import { useTrack } from 'lib/telemetry/track' import { useCustomContent } from 'hooks/custom-content/useCustomContent' import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' @@ -63,6 +62,7 @@ import { } from 'lib/constants' import passwordStrength from 'lib/password-strength' import { generateStrongPassword } from 'lib/project' +import { useTrack } from 'lib/telemetry/track' import { AWS_REGIONS, type CloudProvider } from 'shared-data' import type { NextPageWithLayout } from 'types' import { @@ -772,18 +772,12 @@ const Wizard: NextPageWithLayout = () => { The size for your dedicated database. You can change this later. Learn more about{' '} compute add-ons {' '} and{' '} compute billing