Files
supabase/apps/studio/pages/claim-project.tsx
Alaister YoungandAlaister Young ca2b50a0a7 chore(ui-patterns): collapse the admonition shim into ui-patterns/Admonition (#48377)
Follow-up to #48344: collapses the two resolution paths for the
Admonition module into one.

`src/admonition.tsx` was a back-compat shim re-exporting
`src/Admonition/`. Two ways to resolve one module is exactly what
produced the macOS self-import bug fixed in #48344, and the local
typecheck errors that #48374 worked around. This removes the shim and
standardizes on the PascalCase subpath, matching every other export in
the package.

**Changed:**

- Codemodded all 246 `ui-patterns/admonition` imports to
`ui-patterns/Admonition` (240 `.tsx`, 5 `.mdx`, 1 `.ts` across studio,
docs, www, design-system, and lite-studio)
- Pointed the 5 internal `'../admonition'` imports back at the
`'../Admonition'` directory

**Removed:**

- `packages/ui-patterns/src/admonition.tsx`, and its `./admonition`
entry in the exports map (regenerated with `pnpm gen:exports`)

## To test

- `grep -r "ui-patterns/admonition" --include='*.ts*'` → no hits
- `pnpm test:case-hazards` → passes
- `pnpm typecheck` → all 15 tasks green
- `pnpm --filter studio run lint:ratchet` → passes
- `pnpm --filter ui-patterns vitest run src/Admonition` → 11 tests pass

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

## Summary by CodeRabbit

* **Bug Fixes**
* Standardized Admonition component imports across the application and
documentation.
* Improved compatibility with case-sensitive environments by using the
canonical component path.
  * Removed the legacy Admonition import entry point.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-07-29 00:48:56 +08:00

130 lines
4.2 KiB
TypeScript

import { useParams } from 'common'
import Head from 'next/head'
import { PropsWithChildren, useMemo, useState } from 'react'
import { Admonition } from 'ui-patterns/Admonition'
import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader'
import { ProjectClaimBenefits } from '@/components/interfaces/Organization/ProjectClaim/benefits'
import { ProjectClaimChooseOrg } from '@/components/interfaces/Organization/ProjectClaim/choose-org'
import { ProjectClaimConfirm } from '@/components/interfaces/Organization/ProjectClaim/confirm'
import { ProjectClaimLayout } from '@/components/interfaces/Organization/ProjectClaim/layout'
import { useApiAuthorizationQuery } from '@/data/api-authorization/api-authorization-query'
import { useOrganizationProjectClaimQuery } from '@/data/organizations/organization-project-claim-query'
import { useOrganizationsQuery } from '@/data/organizations/organizations-query'
import { useCustomContent } from '@/hooks/custom-content/useCustomContent'
import { withAuth } from '@/hooks/misc/withAuth'
import type { NextPageWithLayout } from '@/types'
const ClaimProjectPageLayout = ({ children }: PropsWithChildren) => {
const { appTitle } = useCustomContent(['app:title'])
return (
<>
<Head>
<title>{`Claim project | ${appTitle ?? 'Supabase'}`}</title>
</Head>
{children}
</>
)
}
const ClaimProjectPage: NextPageWithLayout = () => {
const { auth_id, token: claimToken } = useParams()
const [selectedOrgSlug, setSelectedOrgSlug] = useState<string>()
const [step, setStep] = useState<'choose-org' | 'benefits' | 'confirm'>('choose-org')
const {
data: requester,
isPending: isLoadingRequester,
isError: isErrorRequester,
error: errorRequester,
} = useApiAuthorizationQuery({ id: auth_id })
const { data: organizations } = useOrganizationsQuery()
const selectedOrganization = useMemo(() => {
return (organizations || []).find((org) => org.slug === selectedOrgSlug)
}, [selectedOrgSlug, organizations])
const {
data: projectClaim,
error: errorProjectClaim,
isError: isErrorProjectClaim,
isPending: isLoadingProjectClaim,
isSuccess: isSuccessProjectClaim,
} = useOrganizationProjectClaimQuery(
{
slug: selectedOrgSlug!,
token: claimToken!,
},
{
enabled: !!claimToken && !!selectedOrgSlug,
}
)
if ((selectedOrgSlug && claimToken && isLoadingProjectClaim) || isLoadingRequester) {
return (
<ProjectClaimLayout title="Claim a project" className="py-6">
<div className="space-y-2">
<ShimmeringLoader />
<ShimmeringLoader className="w-3/4" />
<ShimmeringLoader className="w-1/2" />
</div>
</ProjectClaimLayout>
)
}
if ((selectedOrgSlug && claimToken && isErrorProjectClaim) || isErrorRequester) {
return (
<ProjectClaimLayout title="Claim a project" className="py-6">
<Admonition type="warning" title="Failed to retrieve project claim request details">
<p>Please retry your claim request from the requesting app</p>
{!!errorProjectClaim && <p className="mt-2">Error: {errorProjectClaim?.message}</p>}
{!!errorRequester && <p className="mt-2">Error: {errorRequester?.message}</p>}
</Admonition>
</ProjectClaimLayout>
)
}
if (step === 'choose-org' || !selectedOrganization) {
return (
<ProjectClaimChooseOrg
onChoose={(orgSlug) => {
setSelectedOrgSlug(orgSlug)
setStep('benefits')
}}
/>
)
}
if (isSuccessProjectClaim) {
if (step === 'benefits') {
return (
<ProjectClaimBenefits
projectClaim={projectClaim}
requester={requester}
onContinue={() => setStep('confirm')}
/>
)
}
return (
<ProjectClaimConfirm
setStep={setStep}
selectedOrganization={selectedOrganization}
projectClaim={projectClaim}
requester={requester}
/>
)
}
return null
}
ClaimProjectPage.getLayout = (page) => (
<ClaimProjectPageLayout>
<main className="flex flex-col w-full min-h-screen overflow-y-auto">{page}</main>
</ClaimProjectPageLayout>
)
export default withAuth(ClaimProjectPage)