project-list-root.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import {
  2. ProjectListProvider,
  3. useProjectListContext,
  4. } from '../context/project-list-context'
  5. import * as eventTracking from '../../../infrastructure/event-tracking'
  6. import { Col, Row } from 'react-bootstrap'
  7. import { useTranslation } from 'react-i18next'
  8. import useWaitForI18n from '../../../shared/hooks/use-wait-for-i18n'
  9. import CurrentPlanWidget from './current-plan-widget/current-plan-widget'
  10. import NewProjectButton from './new-project-button'
  11. import ProjectListTable from './table/project-list-table'
  12. import SidebarFilters from './sidebar/sidebar-filters'
  13. import AddAffiliation, { useAddAffiliation } from './sidebar/add-affiliation'
  14. import SurveyWidget from './survey-widget'
  15. import WelcomeMessage from './welcome-message'
  16. import LoadingBranded from '../../../shared/components/loading-branded'
  17. import SystemMessages from './notifications/system-messages'
  18. import UserNotifications from './notifications/user-notifications'
  19. import SearchForm from './search-form'
  20. import ProjectsDropdown from './dropdown/projects-dropdown'
  21. import SortByDropdown from './dropdown/sort-by-dropdown'
  22. import ProjectTools from './table/project-tools/project-tools'
  23. import LoadMore from './load-more'
  24. import { useEffect } from 'react'
  25. function ProjectListRoot() {
  26. const { isReady } = useWaitForI18n()
  27. return isReady ? (
  28. <ProjectListProvider>
  29. <ProjectListPageContent />
  30. </ProjectListProvider>
  31. ) : null
  32. }
  33. function ProjectListPageContent() {
  34. const {
  35. totalProjectsCount,
  36. error,
  37. isLoading,
  38. loadProgress,
  39. searchText,
  40. setSearchText,
  41. selectedProjects,
  42. } = useProjectListContext()
  43. const { show: showAddAffiliationWidget } = useAddAffiliation()
  44. useEffect(() => {
  45. eventTracking.sendMB('loads_v2_dash', {})
  46. }, [])
  47. return isLoading ? (
  48. <div className="loading-container">
  49. <LoadingBranded loadProgress={loadProgress} />
  50. </div>
  51. ) : (
  52. <>
  53. <SystemMessages />
  54. <div className="project-list-wrapper clearfix">
  55. {totalProjectsCount > 0 ? (
  56. <>
  57. <div className="project-list-sidebar-wrapper-react hidden-xs">
  58. <div className="project-list-sidebar-subwrapper">
  59. <aside className="project-list-sidebar-react">
  60. <NewProjectButton id="new-project-button-sidebar" />
  61. <SidebarFilters />
  62. {showAddAffiliationWidget && <hr />}
  63. <AddAffiliation />
  64. </aside>
  65. </div>
  66. </div>
  67. <div className="project-list-main-react">
  68. {error ? <DashApiError /> : ''}
  69. <Row>
  70. <Col xs={12}>
  71. <UserNotifications />
  72. </Col>
  73. </Row>
  74. <Row>
  75. <Col md={7} className="hidden-xs">
  76. <SearchForm
  77. inputValue={searchText}
  78. setInputValue={setSearchText}
  79. />
  80. </Col>
  81. <Col md={5}>
  82. <div className="project-tools">
  83. <div className="hidden-xs">
  84. {selectedProjects.length === 0 ? (
  85. <CurrentPlanWidget />
  86. ) : (
  87. <ProjectTools />
  88. )}
  89. </div>
  90. <div className="visible-xs">
  91. <CurrentPlanWidget />
  92. </div>
  93. </div>
  94. </Col>
  95. </Row>
  96. <div className="project-list-sidebar-survey-wrapper">
  97. <SurveyWidget />
  98. </div>
  99. <div className="visible-xs mt-1">
  100. <div role="toolbar" className="projects-toolbar">
  101. <ProjectsDropdown />
  102. <SortByDropdown />
  103. </div>
  104. </div>
  105. <Row className="row-spaced">
  106. <Col xs={12}>
  107. <div className="card project-list-card">
  108. <div className="visible-xs pt-2 pb-3">
  109. <div className="clearfix">
  110. <NewProjectButton
  111. id="new-project-button-projects-table"
  112. className="pull-left me-2"
  113. />
  114. <SearchForm
  115. inputValue={searchText}
  116. setInputValue={setSearchText}
  117. className="overflow-hidden"
  118. formGroupProps={{ className: 'mb-0' }}
  119. />
  120. </div>
  121. </div>
  122. <ProjectListTable />
  123. </div>
  124. </Col>
  125. </Row>
  126. <Row className="row-spaced">
  127. <Col xs={12}>
  128. <LoadMore />
  129. </Col>
  130. </Row>
  131. </div>
  132. </>
  133. ) : (
  134. <div className="project-list-welcome-wrapper">
  135. {error ? <DashApiError /> : ''}
  136. <Row className="row-spaced">
  137. <Col
  138. xs={8}
  139. xsOffset={2}
  140. md={8}
  141. mdOffset={2}
  142. className="project-list-empty-col"
  143. >
  144. <Row>
  145. <Col xs={12}>
  146. <UserNotifications />
  147. </Col>
  148. </Row>
  149. <WelcomeMessage />
  150. </Col>
  151. </Row>
  152. </div>
  153. )}
  154. </div>
  155. </>
  156. )
  157. }
  158. function DashApiError() {
  159. const { t } = useTranslation()
  160. return (
  161. <Row className="row-spaced">
  162. <Col xs={8} xsOffset={2} aria-live="polite" className="text-center">
  163. <div className="alert alert-danger">
  164. {t('generic_something_went_wrong')}
  165. </div>
  166. </Col>
  167. </Row>
  168. )
  169. }
  170. export default ProjectListRoot