project-list-root.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. function ProjectListRoot() {
  25. const { isReady } = useWaitForI18n()
  26. if (!isReady) {
  27. return null
  28. }
  29. return <ProjectListRootInner />
  30. }
  31. export function ProjectListRootInner() {
  32. return (
  33. <ProjectListProvider>
  34. <ColorPickerProvider>
  35. <SplitTestProvider>
  36. <UserSettingsProvider>
  37. <ProjectListPageContent />
  38. </UserSettingsProvider>
  39. </SplitTestProvider>
  40. </ColorPickerProvider>
  41. </ProjectListProvider>
  42. )
  43. }
  44. function DefaultNavbarAndFooter({ children }: { children: ReactNode }) {
  45. const navbarProps = getMeta('ol-navbar')
  46. const footerProps = getMeta('ol-footer')
  47. return (
  48. <>
  49. <DefaultNavbar {...navbarProps} />
  50. <main
  51. className="content content-alt project-list-react"
  52. aria-labelledby="main-content"
  53. >
  54. {children}
  55. </main>
  56. <Footer {...footerProps} />
  57. </>
  58. )
  59. }
  60. function DefaultPageContentWrapper({ children }: { children: ReactNode }) {
  61. return (
  62. <DefaultNavbarAndFooter>
  63. <SystemMessages />
  64. <div className="project-list-wrapper">{children}</div>
  65. </DefaultNavbarAndFooter>
  66. )
  67. }
  68. function ProjectListPageContent() {
  69. useThemedPage('themed-project-dashboard')
  70. const { totalProjectsCount, isLoading, loadProgress } =
  71. useProjectListContext()
  72. useEffect(() => {
  73. eventTracking.sendMB('loads_v2_dash', {})
  74. }, [])
  75. const { t } = useTranslation()
  76. if (isLoading) {
  77. const loadingComponent = (
  78. <LoadingBranded loadProgress={loadProgress} label={t('loading')} />
  79. )
  80. return loadingComponent
  81. }
  82. if (totalProjectsCount === 0) {
  83. return (
  84. <>
  85. <DefaultPageContentWrapper>
  86. <WelcomePageContent />
  87. </DefaultPageContentWrapper>
  88. <CookieBanner />
  89. </>
  90. )
  91. }
  92. return (
  93. <DsNavStyleProvider>
  94. <ProjectListDsNav />
  95. </DsNavStyleProvider>
  96. )
  97. }
  98. export default withErrorBoundary(ProjectListRoot, () => (
  99. <GenericErrorBoundaryFallback />
  100. ))