project-list-root.tsx 3.1 KB

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