mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 04:46: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 { INode } from '~/redux/types';
|
||||||
import { getPrettyDate } from '~/utils/dom';
|
import { getPrettyDate } from '~/utils/dom';
|
||||||
import { URLS } from '~/constants/urls';
|
import { URLS } from '~/constants/urls';
|
||||||
import { Link, useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
node?: Partial<INode>;
|
node?: Partial<INode>;
|
||||||
|
|
|
@ -4,14 +4,10 @@ import styles from './styles.module.scss';
|
||||||
import { LabNode } from '~/components/lab/LabNode';
|
import { LabNode } from '~/components/lab/LabNode';
|
||||||
import { EMPTY_NODE, NODE_TYPES } from '~/redux/node/constants';
|
import { EMPTY_NODE, NODE_TYPES } from '~/redux/node/constants';
|
||||||
import { values } from 'ramda';
|
import { values } from 'ramda';
|
||||||
import { ILabNode } from '~/redux/lab/types';
|
|
||||||
import { useLabPagination } from '~/utils/hooks/lab/useLabPagination';
|
import { useLabPagination } from '~/utils/hooks/lab/useLabPagination';
|
||||||
|
import { useLabContext } from '~/utils/context/LabContextProvider';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {}
|
||||||
isLoading: boolean;
|
|
||||||
nodes: ILabNode[];
|
|
||||||
onLoadMore: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const breakpointCols = {
|
const breakpointCols = {
|
||||||
default: 2,
|
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}`)), []);
|
const columns = useMemo(() => Array.from(document.querySelectorAll(`.${styles.column}`)), []);
|
||||||
|
|
||||||
useLabPagination(isLoading, columns, onLoadMore);
|
useLabPagination(isLoading, columns, onLoadMore);
|
||||||
|
|
|
@ -2,25 +2,16 @@ import React, { FC } from 'react';
|
||||||
import styles from './styles.module.scss';
|
import styles from './styles.module.scss';
|
||||||
import { LabBanner } from '~/components/lab/LabBanner';
|
import { LabBanner } from '~/components/lab/LabBanner';
|
||||||
import { Group } from '~/components/containers/Group';
|
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 { LabTags } from '~/components/lab/LabTags';
|
||||||
import { LabHeroes } from '~/components/lab/LabHeroes';
|
import { LabHeroes } from '~/components/lab/LabHeroes';
|
||||||
import { FlowRecentItem } from '~/components/flow/FlowRecentItem';
|
import { FlowRecentItem } from '~/components/flow/FlowRecentItem';
|
||||||
import { SubTitle } from '~/components/common/SubTitle';
|
import { SubTitle } from '~/components/common/SubTitle';
|
||||||
|
import { useLabContext } from '~/utils/context/LabContextProvider';
|
||||||
|
|
||||||
interface IProps {}
|
interface IProps {}
|
||||||
|
|
||||||
const LabStats: FC<IProps> = () => {
|
const LabStats: FC<IProps> = () => {
|
||||||
const tags = useShallowSelect(selectLabStatsTags);
|
const { isLoadingStats, tags, heroes, updates } = useLabContext();
|
||||||
const heroes = useShallowSelect(selectLabStatsHeroes);
|
|
||||||
const isLoading = useShallowSelect(selectLabStatsLoading);
|
|
||||||
const updates = useShallowSelect(selectLabUpdatesNodes);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Group>
|
<Group>
|
||||||
|
@ -28,14 +19,14 @@ const LabStats: FC<IProps> = () => {
|
||||||
|
|
||||||
<div className={styles.card}>
|
<div className={styles.card}>
|
||||||
<Group>
|
<Group>
|
||||||
{(!!tags.length || isLoading) && (
|
{(!!tags.length || isLoadingStats) && (
|
||||||
<SubTitle isLoading={isLoading} className={styles.title}>
|
<SubTitle isLoading={isLoadingStats} className={styles.title}>
|
||||||
Тэги
|
Тэги
|
||||||
</SubTitle>
|
</SubTitle>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className={styles.tags}>
|
<div className={styles.tags}>
|
||||||
<LabTags tags={tags} isLoading={isLoading} />
|
<LabTags tags={tags} isLoading={isLoadingStats} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div />
|
<div />
|
||||||
|
@ -53,14 +44,14 @@ const LabStats: FC<IProps> = () => {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(!!heroes.length || isLoading) && (
|
{(!!heroes.length || isLoadingStats) && (
|
||||||
<SubTitle isLoading={isLoading} className={styles.title}>
|
<SubTitle isLoading={isLoadingStats} className={styles.title}>
|
||||||
Важные
|
Важные
|
||||||
</SubTitle>
|
</SubTitle>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className={styles.heroes}>
|
<div className={styles.heroes}>
|
||||||
<LabHeroes nodes={heroes} isLoading={isLoading} />
|
<LabHeroes nodes={heroes} isLoading={isLoadingStats} />
|
||||||
</div>
|
</div>
|
||||||
</Group>
|
</Group>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,13 +2,13 @@ import React, { FC } from 'react';
|
||||||
import { URLS } from '~/constants/urls';
|
import { URLS } from '~/constants/urls';
|
||||||
import { ErrorNotFound } from '~/containers/pages/ErrorNotFound';
|
import { ErrorNotFound } from '~/containers/pages/ErrorNotFound';
|
||||||
import { Redirect, Route, Switch, useLocation } from 'react-router';
|
import { Redirect, Route, Switch, useLocation } from 'react-router';
|
||||||
import { LabLayout } from '~/layouts/LabLayout';
|
|
||||||
import { useShallowSelect } from '~/utils/hooks/useShallowSelect';
|
import { useShallowSelect } from '~/utils/hooks/useShallowSelect';
|
||||||
import { selectAuthUser } from '~/redux/auth/selectors';
|
import { selectAuthUser } from '~/redux/auth/selectors';
|
||||||
import { ProfileLayout } from '~/layouts/ProfileLayout';
|
import { ProfileLayout } from '~/layouts/ProfileLayout';
|
||||||
import FlowPage from '~/pages';
|
import FlowPage from '~/pages';
|
||||||
import BorisPage from '~/pages/boris';
|
import BorisPage from '~/pages/boris';
|
||||||
import NodePage from '~/pages/node/[id]';
|
import NodePage from '~/pages/node/[id]';
|
||||||
|
import LabPage from '~/pages/lab';
|
||||||
|
|
||||||
interface IProps {}
|
interface IProps {}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ const MainRouter: FC<IProps> = () => {
|
||||||
<Route path={URLS.ERRORS.NOT_FOUND} component={ErrorNotFound} />
|
<Route path={URLS.ERRORS.NOT_FOUND} component={ErrorNotFound} />
|
||||||
<Route path={URLS.PROFILE_PAGE(':username')} component={ProfileLayout} />
|
<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} />
|
<Route path={URLS.BASE} component={FlowPage} />
|
||||||
<Redirect to="/" />
|
<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 styles from './styles.module.scss';
|
||||||
import { Sticky } from '~/components/containers/Sticky';
|
import { Sticky } from '~/components/containers/Sticky';
|
||||||
import { Container } from '~/containers/main/Container';
|
import { Container } from '~/containers/main/Container';
|
||||||
import { LabGrid } from '~/containers/lab/LabGrid';
|
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 { Group } from '~/components/containers/Group';
|
||||||
import { LabHead } from '~/components/lab/LabHead';
|
import { LabHead } from '~/components/lab/LabHead';
|
||||||
import { LabStats } from '~/containers/lab/LabStats';
|
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 { SidebarRouter } from '~/containers/main/SidebarRouter';
|
||||||
import { Superpower } from '~/components/boris/Superpower';
|
import { useLabContext } from '~/utils/context/LabContextProvider';
|
||||||
import { Toggle } from '~/components/input/Toggle';
|
|
||||||
import { usePersistedState } from '~/utils/hooks/usePersistedState';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { useLabPagination } from '~/utils/hooks/lab/useLabPagination';
|
|
||||||
|
|
||||||
interface IProps {}
|
interface IProps {}
|
||||||
|
|
||||||
const LabLayout: FC<IProps> = () => {
|
const LabLayout: FC<IProps> = () => {
|
||||||
const { is_loading, nodes, count } = useShallowSelect(selectLabList);
|
const { isLoading } = useLabContext();
|
||||||
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;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
|
@ -44,10 +20,10 @@ const LabLayout: FC<IProps> = () => {
|
||||||
<div className={styles.wrap}>
|
<div className={styles.wrap}>
|
||||||
<Group className={styles.content}>
|
<Group className={styles.content}>
|
||||||
<div className={styles.head}>
|
<div className={styles.head}>
|
||||||
<LabHead isLoading={isInitialLoading} />
|
<LabHead isLoading={isLoading} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<LabGrid nodes={nodes} isLoading={isInitialLoading} onLoadMore={onLoadMore} />
|
<LabGrid />
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<div className={styles.panel}>
|
<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