Загрузка данных


import React from 'react';
import { useDispatch } from 'react-redux';

import { Z_INDEX } from '@configs/appConfig';
import features from '@features';
import { useAppSelect } from '@hooks/useAppSelector';
import { useLocalisation } from '@hooks/useLocalisation';
import { HelpCenter } from '@modules/HelpCenter';
import { ModalRoot } from '@modules/ModalRoot';
import { ModalsContainer } from '@modules/ModalsContainer';
import { useAddressDepositWithdrawalFormHotkey } from '@modules/MXT/AddressDepositWithdrawalForm/hooks';
import { useDepositFormHotkey } from '@modules/MXT/DepositForm/hooks/useDepositFormHotkey';
import { NewsWorkspace } from '@modules/NewsWorkspace/NewsWorkspace';
import { isSidebarOpenSelector } from '@store/selectors/modals';
import { savedWorkspacesSelector, workspaceWidgetsSelector } from '@store/selectors/workspaces';
import { closeSidebarModal, openSidebarModal } from '@store/slices/modals';
import { WorkspaceErrorHandler } from '@terminal/desktop/components/WorkspaceErrorHandler';
import { Sidebar } from '@uikit/Sidebar';

import { EmptyWorkspace } from './components/EmptyWorkspace/EmptyWorkspace';
import { Header } from './components/Header';
import { Profile } from './components/Profile';
import { SidebarContent } from './components/SidebarContent';
import StartPage from './components/StartPage';
import styles from './desktop.module.scss';
import { WorkspaceContainer } from './workspaces/components/WorkspaceContainer';
import { Workspace } from './workspaces/default';
import { Workspace as NewWorkspace } from './workspaces/mesh';

export const DesktopContent: React.FC = () => {
  const hasSavedWorkspaces = useAppSelect((state) => savedWorkspacesSelector(state).length > 0);
  const noWidgets = useAppSelect((state) => workspaceWidgetsSelector(state).length === 0);

  const isSidebarOpen = useAppSelect(isSidebarOpenSelector);
  const dispatch = useDispatch();
  useDepositFormHotkey();
  useAddressDepositWithdrawalFormHotkey();

  const onCloseSidebar = () => {
    dispatch(closeSidebarModal());
  };

  const localisation = useLocalisation();

  const isCurrentWorkspaceHelpCenterWidgets = useAppSelect(
    (state) =>
      state.workspaces.workspaces.find(
        ({ isCurrent, name, isNew }) => isCurrent && !isNew && name === localisation.helpCenter,
      )?.isAddWidgets,
  );

  const isCurrentWorkspaceNewsWidgets = useAppSelect(
    (state) =>
      state.workspaces.workspaces.find(
        ({ isCurrent, name, isNew }) => isCurrent && !isNew && name === localisation.news,
      )?.isAddWidgets,
  );

  const isCurrentWorkspaceSupportWidgets = useAppSelect(
    (state) =>
      state.workspaces.workspaces.find(
        ({ isCurrent, name, isNew }) => isCurrent && !isNew && name === localisation.profile,
      )?.isAddWidgets,
  );

  const isShowCurrentWidgets: boolean = useAppSelect(
    (state) => state.workspaces.workspaces.find(({ isCurrent, code }) => isCurrent && !code)?.isAddWidgets ?? false,
  );

  const isCurrentWorkspaceNew = useAppSelect(
    ({ workspaces }) => workspaces.workspaces.find(({ isCurrent }) => isCurrent)?.isNew,
  );

  const handleToggle = () => {
    if (isSidebarOpen) {
      dispatch(closeSidebarModal());
    } else {
      dispatch(openSidebarModal());
    }
  };

  return (
    <>
      <Header />
      <div className={styles['main-workspace-wrapper']}>
        {isSidebarOpen && (
          <Sidebar
            className={styles['sidebar-container-main']}
            sidebarBodyClassName={styles['sidebar-body-main']}
            width={550}
            open={isSidebarOpen}
            onClose={onCloseSidebar}
            zIndex={Z_INDEX.APP_SIDEBAR}
          >
            <SidebarContent />
          </Sidebar>
        )}
        <WorkspaceContainer isMobileView={false}>
          {isShowCurrentWidgets && noWidgets && hasSavedWorkspaces && !isCurrentWorkspaceNew && (
            <EmptyWorkspace onAddWidgetClick={handleToggle} />
          )}
          {isShowCurrentWidgets && noWidgets && isCurrentWorkspaceNew && (
            <div className={styles['start-page']}>
              <StartPage />
            </div>
          )}
          <WorkspaceErrorHandler isMobileView={false}>
            {features.meshLayout ? <NewWorkspace /> : <Workspace />}
          </WorkspaceErrorHandler>
        </WorkspaceContainer>
        {isCurrentWorkspaceHelpCenterWidgets === false && <HelpCenter />}
        {isCurrentWorkspaceNewsWidgets === false && <NewsWorkspace />}
        {isCurrentWorkspaceSupportWidgets === false && <Profile />}
        <ModalsContainer />
        <ModalRoot />
      </div>
    </>
  );
};

















import React from 'react';

import { Button } from '@uikit/Button';

import styles from '../../desktop.module.scss';
import { useStableKeys } from '../StartPage/components/MiniTile';
// TODO: перенести в радар

interface IEmptyWorkspace {
  onAddWidgetClick: React.MouseEventHandler<HTMLButtonElement>;
}

export const EmptyWorkspace: React.FC<IEmptyWorkspace> = ({ onAddWidgetClick }) => {
  const dotKeysEmptyState = useStableKeys('empty-state-dot', 12);
  const lineKeysEmptyState = useStableKeys('empty-state-line', 6);
  return (
    <div className={styles['start-view']}>
      <div className={styles['grid-container']}>
        <div className={styles.block}>
          <img
            src="/images/Candles.png"
            alt="Candles small"
            className={styles['candle-image']}
          />
        </div>
        <div className={styles.block}>
          <div className={styles.smallGrid}>
            {dotKeysEmptyState.map((key) => (
              <div
                key={key}
                className={styles.dot}
              />
            ))}
          </div>
        </div>
        <div className={styles.block}>
          <div className={styles.lineGroup}>
            {lineKeysEmptyState.map((key) => (
              <div
                key={key}
                className={styles.line}
              />
            ))}
          </div>
        </div>
        <div className={styles.block}>
          <img
            src="/images/Chart.png"
            alt="Chart small"
            className={styles['candle-image']}
          />
        </div>
      </div>
      <div className={styles['main-title']}>Нет открытых виджетов</div>
      <div className={styles['main-text']}>Добавьте виджеты или используйте шаблон рабочего стола</div>
      <Button
        variant="filled-primary"
        onClick={onAddWidgetClick}
        iconEnabled="start"
        Icon="plus"
        text="Виджет"
      />
    </div>
  );
};















import { Loader } from '@components/Loader';



import React from 'react';

import './loader.scss';
import { Spinner } from '@components/Spinner';
import { TextMad } from '@components/TextMad';

export function Loader(): JSX.Element {
  return (
    <div className="loader-container">
      <Spinner />
      <div className="text-holder">
        <TextMad>Данные загружаются</TextMad>
        <TextMad>Пожалуйста подождите</TextMad>
      </div>
    </div>
  );
}


















@import 'colors.scss';

.main-workspace-wrapper {
  flex: 1;
  width: 100%;
  position: relative;
  background-color: red;
  min-height: 0;
}

.main-workspace {
  background-color: $background-bottom;
  overflow: hidden;
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;

  .start-view {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
    height: 100%;
    margin-top: 12%;

    .grid-container {
      display: grid;
      gap: 4px;
      grid-template-columns: repeat(2, auto);
      cursor: pointer;

      .block {
        background-color: $surface-button-basis-secondary;
        border-radius: 4px;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 54px;
        width: 127px;
        overflow: hidden;

        .candle-image {
          position: relative;
          top: 6px;
          width: 50px;
          opacity: 0.6;
          transition: all 0.4s ease;
          mix-blend-mode: screen;
          filter: brightness(1.4);
        }

        .smallGrid {
          display: grid;
          grid-template-columns: repeat(4, auto);
          gap: 10px;
          transition: all 0.4s ease;
        }

        .dot {
          width: 2px;
          height: 2px;
          border-radius: 50%;
          background-color: $surface-icon-basis-disabled;
          transition: all 0.4s ease;
        }

        .lineGroup {
          display: flex;
          flex-direction: column;
          justify-content: center;
          margin: 12px;
          gap: 5px;
          border-radius: 1px;
          transition: all 0.4s ease;
        }

        .line {
          height: 1px;
          width: 39px;
          background-color: $surface-icon-basis-disabled;
          transition: background-color 0.2s ease;
        }
      }

      &:hover .candle-image {
        transform: scale(1.2) translateY(-3px);
      }

      &:hover .line {
        background-color: $surface-icon-basis-muted-secondary;
        width: 45px;
      }

      &:hover .smallGrid,
      &:hover .lineGroup {
        transform: scale(1.15);
      }

      &:hover .lineGroup {
        gap: 6px;
      }

      &:hover .smallGrid {
        transform: scale(1.4);
      }

      &:hover .block {
        background-color: $action-surface-hover;
      }
    }

    .main-title {
      font-size: 32px;
      line-height: 36px;
      color: var(--thm-text-button-primary);
      margin-top: 32px;
    }

    .main-text {
      font-size: 14px;
      line-height: 16px;
      color: var(--thm-text-button-primary);
      margin: 24px 0 32px 0;
    }

    .bottom-text {
      font-size: 12px;
      line-height: 16px;
      color: var(--thm-text-button-primary);
      margin-top: 20px;
    }
  }

  .connect-side-block {
    height: 100%;
    width: 50%;
    position: absolute;
    top: 0;
    background-color: $terminal-bauhaus;
    opacity: 0.5;
  }
}

.main-workspace-mobile {
  display: none;
}

.sidebar-container-main {
  :global {
    .ant-drawer-body {
      padding: 0 24px 24px 24px;
    }
  }
}

.sidebar-body-main {
  &::-webkit-scrollbar {
    width: 8px;
  }
}

.start-page {
  height: 100%;
  box-sizing: border-box;
  padding-block: 100px 32px;
  overflow-y: auto;
}