mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
made boris with hooks
This commit is contained in:
parent
639c952c2c
commit
20926609b9
9 changed files with 85 additions and 79 deletions
|
@ -13,7 +13,7 @@ import { IComment, IFile, INode } from '~/redux/types';
|
||||||
interface IProps {
|
interface IProps {
|
||||||
isLoadingComments: boolean;
|
isLoadingComments: boolean;
|
||||||
commentCount: number;
|
commentCount: number;
|
||||||
node: INode;
|
node?: INode;
|
||||||
comments: IComment[];
|
comments: IComment[];
|
||||||
onDelete: (id: IComment['id'], locked: boolean) => void;
|
onDelete: (id: IComment['id'], locked: boolean) => void;
|
||||||
onLoadMoreComments: () => void;
|
onLoadMoreComments: () => void;
|
||||||
|
@ -34,7 +34,7 @@ const BorisComments: FC<IProps> = ({
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Group className={styles.grid}>
|
<Group className={styles.grid}>
|
||||||
{user.is_user && <NodeCommentForm isBefore nodeId={node.id} />}
|
{user.is_user && <NodeCommentForm isBefore nodeId={node?.id} />}
|
||||||
|
|
||||||
{isLoadingComments ? (
|
{isLoadingComments ? (
|
||||||
<NodeNoComments is_loading count={7} />
|
<NodeNoComments is_loading count={7} />
|
||||||
|
|
|
@ -19,8 +19,8 @@ interface IProps {
|
||||||
commentsOrder: 'ASC' | 'DESC';
|
commentsOrder: 'ASC' | 'DESC';
|
||||||
comments: IComment[];
|
comments: IComment[];
|
||||||
commentsCount: number;
|
commentsCount: number;
|
||||||
|
related?: INodeRelated;
|
||||||
isLoadingComments: boolean;
|
isLoadingComments: boolean;
|
||||||
related: INodeRelated;
|
|
||||||
onDeleteComment: (id: IComment['id'], locked: boolean) => void;
|
onDeleteComment: (id: IComment['id'], locked: boolean) => void;
|
||||||
onLoadMoreComments: () => void;
|
onLoadMoreComments: () => void;
|
||||||
onShowPhotoswipe: (images: IFile[], index: number) => void;
|
onShowPhotoswipe: (images: IFile[], index: number) => void;
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { Link } from 'react-router-dom';
|
||||||
interface IProps {
|
interface IProps {
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
node?: INode;
|
node?: INode;
|
||||||
related: INodeRelated;
|
related?: INodeRelated;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NodeRelatedBlock: FC<IProps> = ({ isLoading, node, related }) => {
|
const NodeRelatedBlock: FC<IProps> = ({ isLoading, node, related }) => {
|
||||||
|
|
|
@ -27,16 +27,27 @@ import { useHistory, useLocation } from 'react-router';
|
||||||
import { Card } from '~/components/containers/Card';
|
import { Card } from '~/components/containers/Card';
|
||||||
import { SidebarRouter } from '~/containers/main/SidebarRouter';
|
import { SidebarRouter } from '~/containers/main/SidebarRouter';
|
||||||
import { BorisContactItem } from '~/components/boris/BorisContactItem';
|
import { BorisContactItem } from '~/components/boris/BorisContactItem';
|
||||||
|
import { useNode } from '~/utils/hooks/node/useNode';
|
||||||
|
import { useNodeComments } from '~/utils/hooks/node/useNodeComments';
|
||||||
|
|
||||||
type IProps = {};
|
type IProps = {};
|
||||||
|
|
||||||
|
const borisNodeID = 696;
|
||||||
|
|
||||||
const BorisLayout: FC<IProps> = () => {
|
const BorisLayout: FC<IProps> = () => {
|
||||||
const title = useRandomPhrase('BORIS_TITLE');
|
const title = useRandomPhrase('BORIS_TITLE');
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const node = useShallowSelect(selectNode);
|
const { node } = useNode(borisNodeID);
|
||||||
|
const {
|
||||||
|
comments,
|
||||||
|
isLoading: isLoadingComments,
|
||||||
|
count: commentCount,
|
||||||
|
onLoadMoreComments,
|
||||||
|
onShowPhotoswipe,
|
||||||
|
onDelete,
|
||||||
|
} = useNodeComments(borisNodeID);
|
||||||
const user = useShallowSelect(selectUser);
|
const user = useShallowSelect(selectUser);
|
||||||
const stats = useShallowSelect(selectBorisStats);
|
const stats = useShallowSelect(selectBorisStats);
|
||||||
const comments = useShallowSelect(selectNodeComments);
|
|
||||||
const is_tester = useShallowSelect(selectAuthIsTester);
|
const is_tester = useShallowSelect(selectAuthIsTester);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -54,11 +65,6 @@ const BorisLayout: FC<IProps> = () => {
|
||||||
dispatch(authSetUser({ last_seen_boris: last_comment.created_at }));
|
dispatch(authSetUser({ last_seen_boris: last_comment.created_at }));
|
||||||
}, [user.last_seen_boris, dispatch, comments]);
|
}, [user.last_seen_boris, dispatch, comments]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (node.is_loading) return;
|
|
||||||
dispatch(nodeLoadNode(696, 'DESC'));
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(borisLoadStats());
|
dispatch(borisLoadStats());
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
@ -111,13 +117,13 @@ const BorisLayout: FC<IProps> = () => {
|
||||||
<Route path={`${URLS.BORIS}/ui`} component={BorisUIDemo} />
|
<Route path={`${URLS.BORIS}/ui`} component={BorisUIDemo} />
|
||||||
|
|
||||||
<BorisComments
|
<BorisComments
|
||||||
isLoadingComments={node.is_loading_comments}
|
isLoadingComments={isLoadingComments}
|
||||||
commentCount={node.comment_count}
|
commentCount={commentCount}
|
||||||
node={node.current}
|
node={node}
|
||||||
comments={node.comments}
|
comments={comments}
|
||||||
onDelete={console.log}
|
onDelete={onDelete}
|
||||||
onLoadMoreComments={console.log}
|
onLoadMoreComments={onLoadMoreComments}
|
||||||
onShowPhotoswipe={console.log}
|
onShowPhotoswipe={onShowPhotoswipe}
|
||||||
/>
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,90 +1,79 @@
|
||||||
import React, { FC, memo, useCallback } from 'react';
|
import React, { FC, memo } from 'react';
|
||||||
import { Route, RouteComponentProps } from 'react-router';
|
import { Route, RouteComponentProps } from 'react-router';
|
||||||
import { selectNode } from '~/redux/node/selectors';
|
|
||||||
import { Card } from '~/components/containers/Card';
|
import { Card } from '~/components/containers/Card';
|
||||||
|
|
||||||
import { NodePanel } from '~/components/node/NodePanel';
|
import { NodePanel } from '~/components/node/NodePanel';
|
||||||
import { Footer } from '~/components/main/Footer';
|
import { Footer } from '~/components/main/Footer';
|
||||||
|
|
||||||
import { SidebarRouter } from '~/containers/main/SidebarRouter';
|
import { SidebarRouter } from '~/containers/main/SidebarRouter';
|
||||||
import { useShallowSelect } from '~/utils/hooks/useShallowSelect';
|
|
||||||
import { Container } from '~/containers/main/Container';
|
import { Container } from '~/containers/main/Container';
|
||||||
import { useNodeBlocks } from '~/utils/hooks/node/useNodeBlocks';
|
import { useNodeBlocks } from '~/utils/hooks/node/useNodeBlocks';
|
||||||
import { NodeBottomBlock } from '~/components/node/NodeBottomBlock';
|
import { NodeBottomBlock } from '~/components/node/NodeBottomBlock';
|
||||||
import { useNodeCoverImage } from '~/utils/hooks/node/useNodeCoverImage';
|
import { useNodeCoverImage } from '~/utils/hooks/node/useNodeCoverImage';
|
||||||
import { useScrollToTop } from '~/utils/hooks/useScrollToTop';
|
import { useScrollToTop } from '~/utils/hooks/useScrollToTop';
|
||||||
import { useLoadNode } from '~/utils/hooks/node/useLoadNode';
|
|
||||||
import { URLS } from '~/constants/urls';
|
import { URLS } from '~/constants/urls';
|
||||||
import { EditorEditDialog } from '~/containers/dialogs/EditorEditDialog';
|
import { EditorEditDialog } from '~/containers/dialogs/EditorEditDialog';
|
||||||
import { useOnNodeSeen } from '~/utils/hooks/node/useOnNodeSeen';
|
import { useOnNodeSeen } from '~/utils/hooks/node/useOnNodeSeen';
|
||||||
|
|
||||||
import styles from './styles.module.scss';
|
import styles from './styles.module.scss';
|
||||||
import { useNodeFetcher } from '~/utils/hooks/node/useNodeFetcher';
|
import { useNode } from '~/utils/hooks/node/useNode';
|
||||||
import { useNodeComments } from '~/utils/hooks/node/useNodeComments';
|
import { useNodeComments } from '~/utils/hooks/node/useNodeComments';
|
||||||
import { IFile } from '~/redux/types';
|
import { useNodeRelated } from '~/utils/hooks/node/useNodeRelated';
|
||||||
import { modalShowPhotoswipe } from '~/redux/modal/actions';
|
|
||||||
import { useDispatch } from 'react-redux';
|
|
||||||
|
|
||||||
type IProps = RouteComponentProps<{ id: string }> & {};
|
type IProps = RouteComponentProps<{ id: string }> & {};
|
||||||
|
|
||||||
const NodeLayout: FC<IProps> = memo(
|
const NodeLayout: FC<IProps> = memo(({ match: { params } }) => {
|
||||||
({
|
const id = parseInt(params.id, 10);
|
||||||
match: {
|
const { node, isLoading } = useNode(id);
|
||||||
params: { id },
|
const {
|
||||||
},
|
comments,
|
||||||
}) => {
|
isLoading: isLoadingComments,
|
||||||
const { node, isLoading } = useNodeFetcher(parseInt(id, 10));
|
count: commentsCount,
|
||||||
const {
|
onDelete,
|
||||||
comments,
|
onLoadMoreComments,
|
||||||
isLoading: isLoadingComments,
|
onShowPhotoswipe,
|
||||||
count: commentsCount,
|
} = useNodeComments(id);
|
||||||
onDelete,
|
|
||||||
onLoadMoreComments,
|
|
||||||
onShowPhotoswipe,
|
|
||||||
} = useNodeComments(parseInt(id, 10));
|
|
||||||
|
|
||||||
const { related } = useShallowSelect(selectNode);
|
const { related } = useNodeRelated(id);
|
||||||
|
|
||||||
useNodeCoverImage(node);
|
useNodeCoverImage(node);
|
||||||
useScrollToTop([id]);
|
useScrollToTop([id]);
|
||||||
useOnNodeSeen(node);
|
useOnNodeSeen(node);
|
||||||
useLoadNode(id, isLoading);
|
|
||||||
|
|
||||||
const { head, block } = useNodeBlocks(node, isLoading);
|
const { head, block } = useNodeBlocks(node, isLoading);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.wrap}>
|
<div className={styles.wrap}>
|
||||||
{head}
|
{head}
|
||||||
|
|
||||||
<Container>
|
<Container>
|
||||||
<Card className={styles.node} seamless>
|
<Card className={styles.node} seamless>
|
||||||
{block}
|
{block}
|
||||||
|
|
||||||
<NodePanel node={node} isLoading={isLoading} />
|
<NodePanel node={node} isLoading={isLoading} />
|
||||||
|
|
||||||
<NodeBottomBlock
|
<NodeBottomBlock
|
||||||
node={node}
|
node={node}
|
||||||
comments={comments}
|
comments={comments}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
isLoadingComments={isLoadingComments}
|
isLoadingComments={isLoadingComments}
|
||||||
commentsCount={commentsCount}
|
commentsCount={commentsCount}
|
||||||
commentsOrder="DESC"
|
commentsOrder="DESC"
|
||||||
related={related}
|
related={related}
|
||||||
onShowPhotoswipe={onShowPhotoswipe}
|
onShowPhotoswipe={onShowPhotoswipe}
|
||||||
onDeleteComment={onDelete}
|
onDeleteComment={onDelete}
|
||||||
onLoadMoreComments={onLoadMoreComments}
|
onLoadMoreComments={onLoadMoreComments}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Footer />
|
<Footer />
|
||||||
</Card>
|
</Card>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
<SidebarRouter prefix="/post:id" />
|
<SidebarRouter prefix="/post:id" />
|
||||||
|
|
||||||
<Route path={URLS.NODE_EDIT_URL(':id')} render={() => <EditorEditDialog />} />
|
<Route path={URLS.NODE_EDIT_URL(':id')} render={() => <EditorEditDialog />} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
export { NodeLayout };
|
export { NodeLayout };
|
||||||
|
|
|
@ -93,8 +93,7 @@ export const apiGetNodeComments = ({
|
||||||
.get<ApiGetNodeCommentsResponse>(API.NODE.COMMENT(id), { params: { take, skip } })
|
.get<ApiGetNodeCommentsResponse>(API.NODE.COMMENT(id), { params: { take, skip } })
|
||||||
.then(cleanResult);
|
.then(cleanResult);
|
||||||
|
|
||||||
export const apiGetNodeRelated = ({ id }: ApiGetNodeRelatedRequest) =>
|
export const apiGetNodeRelated = url => api.get<ApiGetNodeRelatedResult>(url).then(cleanResult);
|
||||||
api.get<ApiGetNodeRelatedResult>(API.NODE.RELATED(id)).then(cleanResult);
|
|
||||||
|
|
||||||
export const apiPostNodeTags = ({ id, tags }: ApiPostNodeTagsRequest) =>
|
export const apiPostNodeTags = ({ id, tags }: ApiPostNodeTagsRequest) =>
|
||||||
api
|
api
|
||||||
|
|
|
@ -165,7 +165,7 @@ function* onNodeLoad({ id }: ReturnType<typeof nodeLoadNode>) {
|
||||||
Unwrap<typeof apiGetNodeRelated>
|
Unwrap<typeof apiGetNodeRelated>
|
||||||
] = yield all([
|
] = yield all([
|
||||||
call(apiGetNodeComments, { id, take: COMMENTS_DISPLAY, skip: 0 }),
|
call(apiGetNodeComments, { id, take: COMMENTS_DISPLAY, skip: 0 }),
|
||||||
call(apiGetNodeRelated, { id }),
|
call(apiGetNodeRelated, id),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
yield put(
|
yield put(
|
||||||
|
|
|
@ -2,7 +2,7 @@ import useSWR from 'swr';
|
||||||
import { INode } from '~/redux/types';
|
import { INode } from '~/redux/types';
|
||||||
import { apiGetNode } from '~/redux/node/api';
|
import { apiGetNode } from '~/redux/node/api';
|
||||||
|
|
||||||
export const useNodeFetcher = (id: INode['id']) => {
|
export const useNode = (id: INode['id']) => {
|
||||||
const { data, error, isValidating } = useSWR(`${id}`, apiGetNode);
|
const { data, error, isValidating } = useSWR(`${id}`, apiGetNode);
|
||||||
const node = data?.node;
|
const node = data?.node;
|
||||||
const isLoading = !data && !isValidating;
|
const isLoading = !data && !isValidating;
|
12
src/utils/hooks/node/useNodeRelated.ts
Normal file
12
src/utils/hooks/node/useNodeRelated.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { INode } from '~/redux/types';
|
||||||
|
import useSWR from 'swr';
|
||||||
|
import { apiGetNodeRelated } from '~/redux/node/api';
|
||||||
|
import { API } from '~/constants/api';
|
||||||
|
|
||||||
|
export const useNodeRelated = (id?: INode['id']) => {
|
||||||
|
const { data, error, isValidating } = useSWR(API.NODE.RELATED(id), apiGetNodeRelated);
|
||||||
|
const isLoading = !data && !isValidating;
|
||||||
|
const related = data?.related;
|
||||||
|
|
||||||
|
return { related, error, isLoading };
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue