project-list-root.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import { ReactNode, useEffect } from 'react'
  2. import {
  3. ProjectListProvider,
  4. useProjectListContext,
  5. } from '../context/project-list-context'
  6. import { SplitTestProvider } from '@/shared/context/split-test-context'
  7. import { ColorPickerProvider } from '../context/color-picker-context'
  8. import * as eventTracking from '../../../infrastructure/event-tracking'
  9. import { useTranslation } from 'react-i18next'
  10. import useWaitForI18n from '../../../shared/hooks/use-wait-for-i18n'
  11. import LoadingBranded from '../../../shared/components/loading-branded'
  12. import SystemMessages from '../../../shared/components/system-messages'
  13. import withErrorBoundary from '../../../infrastructure/error-boundary'
  14. import { GenericErrorBoundaryFallback } from '@/shared/components/generic-error-boundary-fallback'
  15. import getMeta from '@/utils/meta'
  16. import DefaultNavbar from '@/shared/components/navbar/default-navbar'
  17. import Footer from '@/shared/components/footer/footer'
  18. import WelcomePageContent from '@/features/project-list/components/welcome-page-content'
  19. import { ProjectListDsNav } from '@/features/project-list/components/project-list-ds-nav'
  20. import { DsNavStyleProvider } from '@/features/project-list/components/use-is-ds-nav'
  21. import CookieBanner from '@/shared/components/cookie-banner'
  22. import useThemedPage from '@/shared/hooks/use-themed-page'
  23. import { UserSettingsProvider } from '@/shared/context/user-settings-context'
  24. import { TutorialProvider } from '@/shared/context/tutorial-context'
  25. function ProjectListRoot() {
  26. const { isReady } = useWaitForI18n()
  27. if (!isReady) {
  28. return null
  29. }
  30. return <ProjectListRootInner />
  31. }
  32. export function ProjectListRootInner() {
  33. return (
  34. <ProjectListProvider>
  35. <ColorPickerProvider>
  36. <SplitTestProvider>
  37. <TutorialProvider>
  38. <UserSettingsProvider>
  39. <ProjectListPageContent />
  40. </UserSettingsProvider>
  41. </TutorialProvider>
  42. </SplitTestProvider>
  43. </ColorPickerProvider>
  44. </ProjectListProvider>
  45. )
  46. }
  47. function DefaultNavbarAndFooter({ children }: { children: ReactNode }) {
  48. const navbarProps = getMeta('ol-navbar')
  49. const footerProps = getMeta('ol-footer')
  50. return (
  51. <>
  52. <DefaultNavbar {...navbarProps} />
  53. <main
  54. className="content content-alt project-list-react"
  55. aria-labelledby="main-content"
  56. >
  57. {children}
  58. </main>
  59. <Footer {...footerProps} />
  60. </>
  61. )
  62. }
  63. function DefaultPageContentWrapper({ children }: { children: ReactNode }) {
  64. return (
  65. <DefaultNavbarAndFooter>
  66. <SystemMessages />
  67. <div className="project-list-wrapper">{children}</div>
  68. </DefaultNavbarAndFooter>
  69. )
  70. }
  71. function ProjectListPageContent() {
  72. useThemedPage('themed-project-dashboard')
  73. const { totalProjectsCount, isLoading, loadProgress } =
  74. useProjectListContext()
  75. useEffect(() => {
  76. eventTracking.sendMB('loads_v2_dash', {})
  77. }, [])
  78. const { t } = useTranslation()
  79. if (isLoading) {
  80. const loadingComponent = (
  81. <LoadingBranded loadProgress={loadProgress} label={t('loading')} />
  82. )
  83. return loadingComponent
  84. }
  85. if (totalProjectsCount === 0) {
  86. return (
  87. <>
  88. <DefaultPageContentWrapper>
  89. <WelcomePageContent />
  90. </DefaultPageContentWrapper>
  91. <CookieBanner />
  92. </>
  93. )
  94. }
  95. return (
  96. <DsNavStyleProvider>
  97. <ProjectListDsNav />
  98. </DsNavStyleProvider>
  99. )
  100. }
  101. export default withErrorBoundary(ProjectListRoot, () => (
  102. <GenericErrorBoundaryFallback />
  103. ))