mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
made lab use provider and context
This commit is contained in:
parent
cb314e9f8d
commit
96f1529f2b
9 changed files with 129 additions and 56 deletions
|
@ -6,7 +6,7 @@ import styles from './styles.module.scss';
|
|||
import { INode } from '~/redux/types';
|
||||
import { getPrettyDate } from '~/utils/dom';
|
||||
import { URLS } from '~/constants/urls';
|
||||
import { Link, useHistory } from 'react-router-dom';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
interface IProps {
|
||||
node?: Partial<INode>;
|
||||
|
|
|
@ -4,14 +4,10 @@ import styles from './styles.module.scss';
|
|||
import { LabNode } from '~/components/lab/LabNode';
|
||||
import { EMPTY_NODE, NODE_TYPES } from '~/redux/node/constants';
|
||||
import { values } from 'ramda';
|
||||
import { ILabNode } from '~/redux/lab/types';
|
||||
import { useLabPagination } from '~/utils/hooks/lab/useLabPagination';
|
||||
import { useLabContext } from '~/utils/context/LabContextProvider';
|
||||
|
||||
interface IProps {
|
||||
isLoading: boolean;
|
||||
nodes: ILabNode[];
|
||||
onLoadMore: () => void;
|
||||
}
|
||||
interface IProps {}
|
||||
|
||||
const breakpointCols = {
|
||||
default: 2,
|
||||
|
@ -30,7 +26,9 @@ const LoadingNode = () => (
|
|||
/>
|
||||
);
|
||||
|
||||
const LabGrid: FC<IProps> = ({ isLoading, nodes, onLoadMore }) => {
|
||||
const LabGrid: FC<IProps> = () => {
|
||||
const { isLoading, nodes, onLoadMore } = useLabContext();
|
||||
|
||||
const columns = useMemo(() => Array.from(document.querySelectorAll(`.${styles.column}`)), []);
|
||||
|
||||
useLabPagination(isLoading, columns, onLoadMore);
|
||||
|
|
|
@ -2,25 +2,16 @@ import React, { FC } from 'react';
|
|||
import styles from './styles.module.scss';
|
||||
import { LabBanner } from '~/components/lab/LabBanner';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { useShallowSelect } from '~/utils/hooks/useShallowSelect';
|
||||
import {
|
||||
selectLabStatsHeroes,
|
||||
selectLabStatsLoading,
|
||||
selectLabStatsTags,
|
||||
selectLabUpdatesNodes
|
||||
} from '~/redux/lab/selectors';
|
||||
import { LabTags } from '~/components/lab/LabTags';
|
||||
import { LabHeroes } from '~/components/lab/LabHeroes';
|
||||
import { FlowRecentItem } from '~/components/flow/FlowRecentItem';
|
||||
import { SubTitle } from '~/components/common/SubTitle';
|
||||
import { useLabContext } from '~/utils/context/LabContextProvider';
|
||||
|
||||
interface IProps {}
|
||||
|
||||
const LabStats: FC<IProps> = () => {
|
||||
const tags = useShallowSelect(selectLabStatsTags);
|
||||
const heroes = useShallowSelect(selectLabStatsHeroes);
|
||||
const isLoading = useShallowSelect(selectLabStatsLoading);
|
||||
const updates = useShallowSelect(selectLabUpdatesNodes);
|
||||
const { isLoadingStats, tags, heroes, updates } = useLabContext();
|
||||
|
||||
return (
|
||||
<Group>
|
||||
|
@ -28,14 +19,14 @@ const LabStats: FC<IProps> = () => {
|
|||
|
||||
<div className={styles.card}>
|
||||
<Group>
|
||||
{(!!tags.length || isLoading) && (
|
||||
<SubTitle isLoading={isLoading} className={styles.title}>
|
||||
{(!!tags.length || isLoadingStats) && (
|
||||
<SubTitle isLoading={isLoadingStats} className={styles.title}>
|
||||
Тэги
|
||||
</SubTitle>
|
||||
)}
|
||||
|
||||
<div className={styles.tags}>
|
||||
<LabTags tags={tags} isLoading={isLoading} />
|
||||
<LabTags tags={tags} isLoading={isLoadingStats} />
|
||||
</div>
|
||||
|
||||
<div />
|
||||
|
@ -53,14 +44,14 @@ const LabStats: FC<IProps> = () => {
|
|||
</>
|
||||
)}
|
||||
|
||||
{(!!heroes.length || isLoading) && (
|
||||
<SubTitle isLoading={isLoading} className={styles.title}>
|
||||
{(!!heroes.length || isLoadingStats) && (
|
||||
<SubTitle isLoading={isLoadingStats} className={styles.title}>
|
||||
Важные
|
||||
</SubTitle>
|
||||
)}
|
||||
|
||||
<div className={styles.heroes}>
|
||||
<LabHeroes nodes={heroes} isLoading={isLoading} />
|
||||
<LabHeroes nodes={heroes} isLoading={isLoadingStats} />
|
||||
</div>
|
||||
</Group>
|
||||
</div>
|
||||
|
|
|
@ -2,13 +2,13 @@ import React, { FC } from 'react';
|
|||
import { URLS } from '~/constants/urls';
|
||||
import { ErrorNotFound } from '~/containers/pages/ErrorNotFound';
|
||||
import { Redirect, Route, Switch, useLocation } from 'react-router';
|
||||
import { LabLayout } from '~/layouts/LabLayout';
|
||||
import { useShallowSelect } from '~/utils/hooks/useShallowSelect';
|
||||
import { selectAuthUser } from '~/redux/auth/selectors';
|
||||
import { ProfileLayout } from '~/layouts/ProfileLayout';
|
||||
import FlowPage from '~/pages';
|
||||
import BorisPage from '~/pages/boris';
|
||||
import NodePage from '~/pages/node/[id]';
|
||||
import LabPage from '~/pages/lab';
|
||||
|
||||
interface IProps {}
|
||||
|
||||
|
@ -23,7 +23,7 @@ const MainRouter: FC<IProps> = () => {
|
|||
<Route path={URLS.ERRORS.NOT_FOUND} component={ErrorNotFound} />
|
||||
<Route path={URLS.PROFILE_PAGE(':username')} component={ProfileLayout} />
|
||||
|
||||
{is_user && <Route path={URLS.LAB} component={LabLayout} />}
|
||||
{is_user && <Route path={URLS.LAB} component={LabPage} />}
|
||||
|
||||
<Route path={URLS.BASE} component={FlowPage} />
|
||||
<Redirect to="/" />
|
||||
|
|
|
@ -1,42 +1,18 @@
|
|||
import React, { FC, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import React, { FC } from 'react';
|
||||
import styles from './styles.module.scss';
|
||||
import { Sticky } from '~/components/containers/Sticky';
|
||||
import { Container } from '~/containers/main/Container';
|
||||
import { LabGrid } from '~/containers/lab/LabGrid';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { labGetList, labGetMore, labGetStats } from '~/redux/lab/actions';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { LabHead } from '~/components/lab/LabHead';
|
||||
import { LabStats } from '~/containers/lab/LabStats';
|
||||
import { useShallowSelect } from '~/utils/hooks/useShallowSelect';
|
||||
import { selectLabList } from '~/redux/lab/selectors';
|
||||
import { SidebarRouter } from '~/containers/main/SidebarRouter';
|
||||
import { Superpower } from '~/components/boris/Superpower';
|
||||
import { Toggle } from '~/components/input/Toggle';
|
||||
import { usePersistedState } from '~/utils/hooks/usePersistedState';
|
||||
import classNames from 'classnames';
|
||||
import { useLabPagination } from '~/utils/hooks/lab/useLabPagination';
|
||||
import { useLabContext } from '~/utils/context/LabContextProvider';
|
||||
|
||||
interface IProps {}
|
||||
|
||||
const LabLayout: FC<IProps> = () => {
|
||||
const { is_loading, nodes, count } = useShallowSelect(selectLabList);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(labGetList());
|
||||
dispatch(labGetStats());
|
||||
}, [dispatch]);
|
||||
|
||||
const onLoadMore = useCallback(() => {
|
||||
if (nodes.length >= count) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(labGetMore());
|
||||
}, [nodes, count, dispatch]);
|
||||
|
||||
const isInitialLoading = is_loading && !nodes.length;
|
||||
const { isLoading } = useLabContext();
|
||||
|
||||
return (
|
||||
<Container>
|
||||
|
@ -44,10 +20,10 @@ const LabLayout: FC<IProps> = () => {
|
|||
<div className={styles.wrap}>
|
||||
<Group className={styles.content}>
|
||||
<div className={styles.head}>
|
||||
<LabHead isLoading={isInitialLoading} />
|
||||
<LabHead isLoading={isLoading} />
|
||||
</div>
|
||||
|
||||
<LabGrid nodes={nodes} isLoading={isInitialLoading} onLoadMore={onLoadMore} />
|
||||
<LabGrid />
|
||||
</Group>
|
||||
|
||||
<div className={styles.panel}>
|
||||
|
|
13
src/pages/lab.tsx
Normal file
13
src/pages/lab.tsx
Normal file
|
@ -0,0 +1,13 @@
|
|||
import React, { VFC } from 'react';
|
||||
import { LabLayout } from '~/layouts/LabLayout';
|
||||
import { LabProvider } from '~/utils/providers/LabProvider';
|
||||
|
||||
interface LabPageProps {}
|
||||
|
||||
const LabPage: VFC<LabPageProps> = () => (
|
||||
<LabProvider>
|
||||
<LabLayout />
|
||||
</LabProvider>
|
||||
);
|
||||
|
||||
export default LabPage;
|
34
src/utils/context/LabContextProvider.tsx
Normal file
34
src/utils/context/LabContextProvider.tsx
Normal file
|
@ -0,0 +1,34 @@
|
|||
import { ILabNode } from '~/redux/lab/types';
|
||||
import React, { createContext, FC, useContext } from 'react';
|
||||
import { INode, ITag } from '~/redux/types';
|
||||
|
||||
export interface LabContextProps {
|
||||
isLoading: boolean;
|
||||
nodes: ILabNode[];
|
||||
count: number;
|
||||
onLoadMore: () => void;
|
||||
|
||||
tags: ITag[];
|
||||
heroes: Partial<INode>[];
|
||||
isLoadingStats: boolean;
|
||||
updates: Partial<INode>[];
|
||||
}
|
||||
|
||||
const defaultValues: LabContextProps = {
|
||||
isLoading: false,
|
||||
nodes: [],
|
||||
count: 0,
|
||||
onLoadMore: () => {},
|
||||
tags: [],
|
||||
heroes: [],
|
||||
isLoadingStats: false,
|
||||
updates: [],
|
||||
};
|
||||
|
||||
const LabContext = createContext<LabContextProps>(defaultValues);
|
||||
|
||||
export const LabContextProvider: FC<LabContextProps> = ({ children, ...rest }) => (
|
||||
<LabContext.Provider value={rest}>{children}</LabContext.Provider>
|
||||
);
|
||||
|
||||
export const useLabContext = () => useContext(LabContext);
|
35
src/utils/hooks/lab/useLab.ts
Normal file
35
src/utils/hooks/lab/useLab.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { useShallowSelect } from '~/utils/hooks/useShallowSelect';
|
||||
import {
|
||||
selectLabList,
|
||||
selectLabStatsHeroes,
|
||||
selectLabStatsLoading,
|
||||
selectLabStatsTags,
|
||||
selectLabUpdatesNodes,
|
||||
} from '~/redux/lab/selectors';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { labGetList, labGetMore, labGetStats } from '~/redux/lab/actions';
|
||||
|
||||
export const useLab = () => {
|
||||
const { is_loading: isLoading, nodes, count } = useShallowSelect(selectLabList);
|
||||
const dispatch = useDispatch();
|
||||
const tags = useShallowSelect(selectLabStatsTags);
|
||||
const heroes = useShallowSelect(selectLabStatsHeroes);
|
||||
const isLoadingStats = useShallowSelect(selectLabStatsLoading);
|
||||
const updates = useShallowSelect(selectLabUpdatesNodes);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(labGetList());
|
||||
dispatch(labGetStats());
|
||||
}, [dispatch]);
|
||||
|
||||
const onLoadMore = useCallback(() => {
|
||||
if (nodes.length >= count) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(labGetMore());
|
||||
}, [nodes, count, dispatch]);
|
||||
|
||||
return { isLoading, nodes, count, onLoadMore, tags, heroes, isLoadingStats, updates };
|
||||
};
|
26
src/utils/providers/LabProvider.tsx
Normal file
26
src/utils/providers/LabProvider.tsx
Normal file
|
@ -0,0 +1,26 @@
|
|||
import React, { FC } from 'react';
|
||||
import { LabContextProvider } from '~/utils/context/LabContextProvider';
|
||||
import { useLab } from '~/utils/hooks/lab/useLab';
|
||||
|
||||
interface LabProviderProps {}
|
||||
|
||||
const LabProvider: FC<LabProviderProps> = ({ children }) => {
|
||||
const { isLoading, nodes, count, onLoadMore, tags, heroes, isLoadingStats, updates } = useLab();
|
||||
|
||||
return (
|
||||
<LabContextProvider
|
||||
isLoading={isLoading && !nodes.length}
|
||||
nodes={nodes}
|
||||
count={count}
|
||||
onLoadMore={onLoadMore}
|
||||
tags={tags}
|
||||
heroes={heroes}
|
||||
isLoadingStats={isLoadingStats}
|
||||
updates={updates}
|
||||
>
|
||||
{children}
|
||||
</LabContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export { LabProvider };
|
Loading…
Add table
Add a link
Reference in a new issue