project-list-root.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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 ProjectListDefault from '@/features/project-list/components/project-list-default'
  20. import { ProjectListDsNav } from '@/features/project-list/components/project-list-ds-nav'
  21. import {
  22. DsNavStyleProvider,
  23. hasDsNav,
  24. } from '@/features/project-list/components/use-is-ds-nav'
  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. <ProjectListPageContent />
  38. </SplitTestProvider>
  39. </ColorPickerProvider>
  40. </ProjectListProvider>
  41. )
  42. }
  43. function DefaultNavbarAndFooter({ children }: { children: ReactNode }) {
  44. const navbarProps = getMeta('ol-navbar')
  45. const footerProps = getMeta('ol-footer')
  46. return (
  47. <>
  48. <DefaultNavbar {...navbarProps} />
  49. <main
  50. id="main-content"
  51. className="content content-alt project-list-react"
  52. >
  53. {children}
  54. </main>
  55. <Footer {...footerProps} />
  56. </>
  57. )
  58. }
  59. function DefaultPageContentWrapper({ children }: { children: ReactNode }) {
  60. return (
  61. <DefaultNavbarAndFooter>
  62. <SystemMessages />
  63. <div className="project-list-wrapper">{children}</div>
  64. </DefaultNavbarAndFooter>
  65. )
  66. }
  67. function ProjectListPageContent() {
  68. const { totalProjectsCount, isLoading, loadProgress } =
  69. useProjectListContext()
  70. useEffect(() => {
  71. eventTracking.sendMB('loads_v2_dash', {})
  72. }, [])
  73. const { t } = useTranslation()
  74. if (isLoading) {
  75. const loadingComponent = (
  76. <LoadingBranded loadProgress={loadProgress} label={t('loading')} />
  77. )
  78. if (hasDsNav()) {
  79. return loadingComponent
  80. } else {
  81. return (
  82. <DefaultNavbarAndFooter>
  83. <div className="loading-container">{loadingComponent}</div>
  84. </DefaultNavbarAndFooter>
  85. )
  86. }
  87. }
  88. if (totalProjectsCount === 0) {
  89. return (
  90. <DefaultPageContentWrapper>
  91. <WelcomePageContent />
  92. </DefaultPageContentWrapper>
  93. )
  94. } else if (hasDsNav()) {
  95. return (
  96. <DsNavStyleProvider>
  97. <ProjectListDsNav />
  98. </DsNavStyleProvider>
  99. )
  100. } else {
  101. return (
  102. <DefaultPageContentWrapper>
  103. <ProjectListDefault />
  104. </DefaultPageContentWrapper>
  105. )
  106. }
  107. }
  108. export default withErrorBoundary(ProjectListRoot, GenericErrorBoundaryFallback)