claim-project.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import { useParams } from 'common'
  2. import Head from 'next/head'
  3. import { PropsWithChildren, useMemo, useState } from 'react'
  4. import { Admonition } from 'ui-patterns/admonition'
  5. import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader'
  6. import { ProjectClaimBenefits } from '@/components/interfaces/Organization/ProjectClaim/benefits'
  7. import { ProjectClaimChooseOrg } from '@/components/interfaces/Organization/ProjectClaim/choose-org'
  8. import { ProjectClaimConfirm } from '@/components/interfaces/Organization/ProjectClaim/confirm'
  9. import { ProjectClaimLayout } from '@/components/interfaces/Organization/ProjectClaim/layout'
  10. import { useApiAuthorizationQuery } from '@/data/api-authorization/api-authorization-query'
  11. import { useOrganizationProjectClaimQuery } from '@/data/organizations/organization-project-claim-query'
  12. import { useOrganizationsQuery } from '@/data/organizations/organizations-query'
  13. import { useCustomContent } from '@/hooks/custom-content/useCustomContent'
  14. import { withAuth } from '@/hooks/misc/withAuth'
  15. import type { NextPageWithLayout } from '@/types'
  16. const ClaimProjectPageLayout = ({ children }: PropsWithChildren) => {
  17. const { appTitle } = useCustomContent(['app:title'])
  18. return (
  19. <>
  20. <Head>
  21. <title>{`Claim project | ${appTitle ?? 'Briven'}`}</title>
  22. </Head>
  23. {children}
  24. </>
  25. )
  26. }
  27. const ClaimProjectPage: NextPageWithLayout = () => {
  28. const { auth_id, token: claimToken } = useParams()
  29. const [selectedOrgSlug, setSelectedOrgSlug] = useState<string>()
  30. const [step, setStep] = useState<'choose-org' | 'benefits' | 'confirm'>('choose-org')
  31. const {
  32. data: requester,
  33. isPending: isLoadingRequester,
  34. isError: isErrorRequester,
  35. error: errorRequester,
  36. } = useApiAuthorizationQuery({ id: auth_id })
  37. const { data: organizations } = useOrganizationsQuery()
  38. const selectedOrganization = useMemo(() => {
  39. return (organizations || []).find((org) => org.slug === selectedOrgSlug)
  40. }, [selectedOrgSlug, organizations])
  41. const {
  42. data: projectClaim,
  43. error: errorProjectClaim,
  44. isError: isErrorProjectClaim,
  45. isPending: isLoadingProjectClaim,
  46. isSuccess: isSuccessProjectClaim,
  47. } = useOrganizationProjectClaimQuery(
  48. {
  49. slug: selectedOrgSlug!,
  50. token: claimToken!,
  51. },
  52. {
  53. enabled: !!claimToken && !!selectedOrgSlug,
  54. }
  55. )
  56. if ((selectedOrgSlug && claimToken && isLoadingProjectClaim) || isLoadingRequester) {
  57. return (
  58. <ProjectClaimLayout title="Claim a project" className="py-6">
  59. <div className="space-y-2">
  60. <ShimmeringLoader />
  61. <ShimmeringLoader className="w-3/4" />
  62. <ShimmeringLoader className="w-1/2" />
  63. </div>
  64. </ProjectClaimLayout>
  65. )
  66. }
  67. if ((selectedOrgSlug && claimToken && isErrorProjectClaim) || isErrorRequester) {
  68. return (
  69. <ProjectClaimLayout title="Claim a project" className="py-6">
  70. <Admonition type="warning" title="Failed to retrieve project claim request details">
  71. <p>Please retry your claim request from the requesting app</p>
  72. {!!errorProjectClaim && <p className="mt-2">Error: {errorProjectClaim?.message}</p>}
  73. {!!errorRequester && <p className="mt-2">Error: {errorRequester?.message}</p>}
  74. </Admonition>
  75. </ProjectClaimLayout>
  76. )
  77. }
  78. if (step === 'choose-org' || !selectedOrganization) {
  79. return (
  80. <ProjectClaimChooseOrg
  81. onChoose={(orgSlug) => {
  82. setSelectedOrgSlug(orgSlug)
  83. setStep('benefits')
  84. }}
  85. />
  86. )
  87. }
  88. if (isSuccessProjectClaim) {
  89. if (step === 'benefits') {
  90. return (
  91. <ProjectClaimBenefits
  92. projectClaim={projectClaim}
  93. requester={requester}
  94. onContinue={() => setStep('confirm')}
  95. />
  96. )
  97. }
  98. return (
  99. <ProjectClaimConfirm
  100. setStep={setStep}
  101. selectedOrganization={selectedOrganization}
  102. projectClaim={projectClaim}
  103. requester={requester}
  104. />
  105. )
  106. }
  107. return null
  108. }
  109. ClaimProjectPage.getLayout = (page) => (
  110. <ClaimProjectPageLayout>
  111. <main className="flex flex-col w-full min-h-screen overflow-y-auto">{page}</main>
  112. </ClaimProjectPageLayout>
  113. )
  114. export default withAuth(ClaimProjectPage)