NavigationPanel.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import { WorkspaceUser } from '../WorkspaceUser';
  2. import { AppLogo } from '../AppLogo';
  3. import { FolderItem } from './FolderItem';
  4. import { TrashButton } from './TrashButton';
  5. import { NewFolderButton } from './NewFolderButton';
  6. import { NavigationResizer } from './NavigationResizer';
  7. import { IFolder } from '../../../stores/reducers/folders/slice';
  8. import { IPage } from '../../../stores/reducers/pages/slice';
  9. import { useNavigate } from 'react-router-dom';
  10. import React, { useEffect, useRef } from 'react';
  11. import { useDispatch } from 'react-redux';
  12. import { useAppSelector } from '../../../stores/store';
  13. import { ANIMATION_DURATION, NAV_PANEL_MINIMUM_WIDTH } from '../../_shared/constants';
  14. export const NavigationPanel = ({
  15. onHideMenuClick,
  16. menuHidden,
  17. width,
  18. folders,
  19. pages,
  20. onPageClick,
  21. }: {
  22. onHideMenuClick: () => void;
  23. menuHidden: boolean;
  24. width: number;
  25. folders: IFolder[];
  26. pages: IPage[];
  27. onPageClick: (page: IPage) => void;
  28. }) => {
  29. const el = useRef<HTMLDivElement>(null);
  30. const dispatch = useDispatch();
  31. const foldersStore = useAppSelector((state) => state.folders);
  32. const pagesStore = useAppSelector((state) => state.pages);
  33. const activePageId = useAppSelector((state) => state.activePageId);
  34. return (
  35. <>
  36. <div
  37. className={`absolute inset-0 flex flex-col justify-between bg-surface-1 text-sm`}
  38. style={{
  39. transition: `left ${ANIMATION_DURATION}ms ease-out`,
  40. width: `${width}px`,
  41. left: `${menuHidden ? -width : 0}px`,
  42. }}
  43. >
  44. <div className={'flex flex-col'}>
  45. <AppLogo iconToShow={'hide'} onHideMenuClick={onHideMenuClick}></AppLogo>
  46. <WorkspaceUser></WorkspaceUser>
  47. <div className={'flex flex-col overflow-auto px-2'} style={{ height: 'calc(100vh - 300px)' }} ref={el}>
  48. <WorkspaceApps folders={folders} pages={pages} onPageClick={onPageClick} />
  49. </div>
  50. </div>
  51. <div className={'flex flex-col'}>
  52. <div className={'border-b border-shade-6 px-2 pb-4'}>
  53. {/*<PluginsButton></PluginsButton>*/}
  54. <DesignSpec></DesignSpec>
  55. <TestBackendButton></TestBackendButton>
  56. {/*Trash Button*/}
  57. <TrashButton></TrashButton>
  58. </div>
  59. {/*New Folder Button*/}
  60. <NewFolderButton></NewFolderButton>
  61. </div>
  62. </div>
  63. <NavigationResizer minWidth={NAV_PANEL_MINIMUM_WIDTH}></NavigationResizer>
  64. </>
  65. );
  66. };
  67. type AppsContext = {
  68. folders: IFolder[];
  69. pages: IPage[];
  70. onPageClick: (page: IPage) => void;
  71. };
  72. const WorkspaceApps: React.FC<AppsContext> = ({ folders, pages, onPageClick }) => (
  73. <>
  74. {folders.map((folder, index) => (
  75. <FolderItem
  76. key={index}
  77. folder={folder}
  78. pages={pages.filter((page) => page.folderId === folder.id)}
  79. onPageClick={onPageClick}
  80. ></FolderItem>
  81. ))}
  82. </>
  83. );
  84. export const TestBackendButton = () => {
  85. const navigate = useNavigate();
  86. return (
  87. <button
  88. onClick={() => navigate('/page/api-test')}
  89. className={'flex w-full items-center rounded-lg px-4 py-2 hover:bg-surface-2'}
  90. >
  91. APITest
  92. </button>
  93. );
  94. };
  95. export const DesignSpec = () => {
  96. const navigate = useNavigate();
  97. return (
  98. <button
  99. onClick={() => navigate('page/colors')}
  100. className={'flex w-full items-center rounded-lg px-4 py-2 hover:bg-surface-2'}
  101. >
  102. Design Specs
  103. </button>
  104. );
  105. };