mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
add comments for guests
This commit is contained in:
parent
cbf7b1f616
commit
8abf6177b5
16 changed files with 278 additions and 194 deletions
|
@ -21,7 +21,7 @@ type IProps = HTMLAttributes<HTMLDivElement> & {
|
|||
isSame?: boolean;
|
||||
canEdit?: boolean;
|
||||
highlighted?: boolean;
|
||||
saveComment: (data: IComment) => Promise<unknown>;
|
||||
saveComment: (data: IComment) => Promise<IComment | undefined>;
|
||||
onDelete: (id: IComment['id'], isLocked: boolean) => void;
|
||||
onShowImageModal: (images: IFile[], index: number) => void;
|
||||
};
|
||||
|
|
|
@ -7,11 +7,15 @@ import { IUser } from '~/types/auth';
|
|||
import { path } from '~/utils/ramda';
|
||||
|
||||
interface Props {
|
||||
user: IUser;
|
||||
user?: IUser;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const CommentAvatar: FC<Props> = ({ user, className }) => {
|
||||
if (!user) {
|
||||
return <Avatar className={className} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<MenuButton
|
||||
position="auto"
|
||||
|
|
|
@ -22,6 +22,7 @@ import { IComment, IFile } from '~/types';
|
|||
import { formatCommentText, getPrettyDate, getURL } from '~/utils/dom';
|
||||
import { append, assocPath, path, reduce } from '~/utils/ramda';
|
||||
|
||||
import { CommentEditingForm } from '../CommentEditingForm';
|
||||
import { CommentImageGrid } from '../CommentImageGrid';
|
||||
import { CommentMenu } from '../CommentMenu';
|
||||
|
||||
|
@ -32,7 +33,7 @@ interface IProps {
|
|||
nodeId: number;
|
||||
comment: IComment;
|
||||
canEdit: boolean;
|
||||
saveComment: (data: IComment) => Promise<unknown>;
|
||||
saveComment: (data: IComment) => Promise<IComment | undefined>;
|
||||
onDelete: (id: IComment['id'], isLocked: boolean) => void;
|
||||
onShowImageModal: (images: IFile[], index: number) => void;
|
||||
}
|
||||
|
@ -98,7 +99,7 @@ const CommentContent: FC<IProps> = memo(
|
|||
|
||||
if (isEditing) {
|
||||
return (
|
||||
<CommentForm
|
||||
<CommentEditingForm
|
||||
saveComment={saveComment}
|
||||
nodeId={nodeId}
|
||||
comment={comment}
|
||||
|
|
38
src/components/comment/CommentEditingForm/index.tsx
Normal file
38
src/components/comment/CommentEditingForm/index.tsx
Normal file
|
@ -0,0 +1,38 @@
|
|||
import { FC } from 'react';
|
||||
|
||||
import { CommentForm } from '~/components/comment/CommentForm';
|
||||
import { UploadDropzone } from '~/components/upload/UploadDropzone';
|
||||
import { UploadSubject, UploadTarget } from '~/constants/uploads';
|
||||
import { useUploader } from '~/hooks/data/useUploader';
|
||||
import { IComment, INode } from '~/types';
|
||||
import { UploaderContextProvider } from '~/utils/context/UploaderContextProvider';
|
||||
|
||||
interface CommentEditingFormProps {
|
||||
comment: IComment;
|
||||
nodeId: INode['id'];
|
||||
saveComment: (data: IComment) => Promise<IComment | undefined>;
|
||||
onCancelEdit?: () => void;
|
||||
}
|
||||
|
||||
const CommentEditingForm: FC<CommentEditingFormProps> = ({
|
||||
saveComment,
|
||||
comment,
|
||||
onCancelEdit,
|
||||
}) => {
|
||||
const uploader = useUploader(UploadSubject.Comment, UploadTarget.Comments);
|
||||
|
||||
return (
|
||||
<UploadDropzone onUpload={uploader.uploadFiles}>
|
||||
<UploaderContextProvider value={uploader}>
|
||||
<CommentForm
|
||||
saveComment={saveComment}
|
||||
comment={comment}
|
||||
onCancelEdit={onCancelEdit}
|
||||
allowUploads
|
||||
/>
|
||||
</UploaderContextProvider>
|
||||
</UploadDropzone>
|
||||
);
|
||||
};
|
||||
|
||||
export { CommentEditingForm };
|
|
@ -1,4 +1,4 @@
|
|||
import React, { FC, useCallback, useState } from 'react';
|
||||
import { FC, useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import { FormikProvider } from 'formik';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
@ -12,31 +12,35 @@ import { Button } from '~/components/input/Button';
|
|||
import { UploadDropzone } from '~/components/upload/UploadDropzone';
|
||||
import { ERROR_LITERAL } from '~/constants/errors';
|
||||
import { EMPTY_COMMENT } from '~/constants/node';
|
||||
import { UploadSubject, UploadTarget } from '~/constants/uploads';
|
||||
import { useCommentFormFormik } from '~/hooks/comments/useCommentFormFormik';
|
||||
import { useUploader } from '~/hooks/data/useUploader';
|
||||
import { useInputPasteUpload } from '~/hooks/dom/useInputPasteUpload';
|
||||
import { IComment, INode } from '~/types';
|
||||
import { UploaderContextProvider } from '~/utils/context/UploaderContextProvider';
|
||||
import {
|
||||
UploaderContextProvider,
|
||||
useUploaderContext,
|
||||
} from '~/utils/context/UploaderContextProvider';
|
||||
|
||||
import styles from './styles.module.scss';
|
||||
|
||||
interface IProps {
|
||||
comment?: IComment;
|
||||
nodeId: INode['id'];
|
||||
saveComment: (data: IComment) => Promise<unknown>;
|
||||
allowUploads?: boolean;
|
||||
|
||||
saveComment: (data: IComment) => Promise<IComment | undefined>;
|
||||
onCancelEdit?: () => void;
|
||||
}
|
||||
|
||||
const CommentForm: FC<IProps> = observer(({ comment, nodeId, saveComment, onCancelEdit }) => {
|
||||
const CommentForm: FC<IProps> = observer(
|
||||
({ comment, allowUploads, saveComment, onCancelEdit }) => {
|
||||
const [textarea, setTextArea] = useState<HTMLTextAreaElement | null>(null);
|
||||
const uploader = useUploader(UploadSubject.Comment, UploadTarget.Comments, comment?.files);
|
||||
const uploader = useUploaderContext();
|
||||
|
||||
const formik = useCommentFormFormik(
|
||||
comment || EMPTY_COMMENT,
|
||||
nodeId,
|
||||
uploader,
|
||||
uploader.files,
|
||||
uploader.setFiles,
|
||||
saveComment,
|
||||
onCancelEdit
|
||||
onCancelEdit,
|
||||
);
|
||||
const isLoading = formik.isSubmitting || uploader.isUploading;
|
||||
const isEditing = !!comment?.id;
|
||||
|
@ -58,10 +62,8 @@ const CommentForm: FC<IProps> = observer(({ comment, nodeId, saveComment, onCanc
|
|||
const onPaste = useInputPasteUpload(uploader.uploadFiles);
|
||||
|
||||
return (
|
||||
<UploadDropzone onUpload={uploader.uploadFiles}>
|
||||
<form onSubmit={formik.handleSubmit} className={styles.wrap}>
|
||||
<FormikProvider value={formik}>
|
||||
<UploaderContextProvider value={uploader}>
|
||||
<div className={styles.input}>
|
||||
<LocalCommentFormTextarea onPaste={onPaste} ref={setTextArea} />
|
||||
|
||||
|
@ -72,12 +74,14 @@ const CommentForm: FC<IProps> = observer(({ comment, nodeId, saveComment, onCanc
|
|||
)}
|
||||
</div>
|
||||
|
||||
<CommentFormAttaches />
|
||||
{allowUploads && <CommentFormAttaches />}
|
||||
|
||||
<div className={styles.buttons}>
|
||||
{allowUploads && (
|
||||
<div className={styles.button_column}>
|
||||
<CommentFormAttachButtons onUpload={uploader.uploadFiles} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={styles.button_column}>
|
||||
{!!textarea && (
|
||||
|
@ -92,7 +96,12 @@ const CommentForm: FC<IProps> = observer(({ comment, nodeId, saveComment, onCanc
|
|||
|
||||
<div className={styles.button_column}>
|
||||
{isEditing && (
|
||||
<Button size="small" color="link" type="button" onClick={onCancelEdit}>
|
||||
<Button
|
||||
size="small"
|
||||
color="link"
|
||||
type="button"
|
||||
onClick={onCancelEdit}
|
||||
>
|
||||
Отмена
|
||||
</Button>
|
||||
)}
|
||||
|
@ -109,11 +118,10 @@ const CommentForm: FC<IProps> = observer(({ comment, nodeId, saveComment, onCanc
|
|||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</UploaderContextProvider>
|
||||
</FormikProvider>
|
||||
</form>
|
||||
</UploadDropzone>
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
export { CommentForm };
|
||||
|
|
|
@ -10,7 +10,7 @@ import { DivProps } from '~/utils/types';
|
|||
import styles from './styles.module.scss';
|
||||
|
||||
type IProps = DivProps & {
|
||||
user: IUser;
|
||||
user?: IUser;
|
||||
isEmpty?: boolean;
|
||||
isLoading?: boolean;
|
||||
isForm?: boolean;
|
||||
|
@ -36,7 +36,10 @@ const CommentWrapper: FC<IProps> = ({
|
|||
{...props}
|
||||
>
|
||||
<div className={styles.thumb}>
|
||||
<CommentAvatar user={user} className={styles.thumb_image} />
|
||||
<CommentAvatar
|
||||
user={user}
|
||||
className={classNames(styles.thumb_image, { [styles.pointer]: user })}
|
||||
/>
|
||||
<div className={styles.thumb_user}>~{path(['username'], user)}</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ div.thumb_image {
|
|||
background-size: cover;
|
||||
flex: 0 0 $comment_height;
|
||||
will-change: transform;
|
||||
cursor: pointer;
|
||||
cursor: default;
|
||||
|
||||
@include tablet {
|
||||
height: 32px;
|
||||
|
@ -105,6 +105,10 @@ div.thumb_image {
|
|||
}
|
||||
}
|
||||
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.thumb_user {
|
||||
display: none;
|
||||
flex: 1;
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
import React, { FC } from 'react';
|
||||
|
||||
import { CommentForm } from '~/components/comment/CommentForm';
|
||||
import { CommentWrapper } from '~/components/containers/CommentWrapper';
|
||||
import { IComment } from '~/types';
|
||||
import { IUser } from '~/types/auth';
|
||||
|
||||
export interface NodeCommentFormProps {
|
||||
user: IUser;
|
||||
nodeId?: number;
|
||||
saveComment: (comment: IComment) => Promise<unknown>;
|
||||
}
|
||||
|
||||
const NodeCommentForm: FC<NodeCommentFormProps> = ({ user, nodeId, saveComment }) => {
|
||||
return (
|
||||
<CommentWrapper user={user} isForm>
|
||||
<CommentForm nodeId={nodeId} saveComment={saveComment} />
|
||||
</CommentWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export { NodeCommentForm };
|
|
@ -1,8 +0,0 @@
|
|||
import dynamic from 'next/dynamic';
|
||||
|
||||
import type { NodeCommentFormProps } from './index';
|
||||
|
||||
export const NodeCommentFormSSR = dynamic<NodeCommentFormProps>(
|
||||
() => import('./index').then(it => it.NodeCommentForm),
|
||||
{ ssr: false }
|
||||
);
|
|
@ -1,34 +1,20 @@
|
|||
import React, { FC } from 'react';
|
||||
import { FC } from 'react';
|
||||
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { Footer } from '~/components/main/Footer';
|
||||
import { NodeCommentFormSSR } from '~/components/node/NodeCommentForm/ssr';
|
||||
import { NodeNoComments } from '~/components/node/NodeNoComments';
|
||||
import { isSSR } from '~/constants/ssr';
|
||||
import { NodeCommentFormSSR } from '~/containers/node/NodeCommentForm/ssr';
|
||||
import { NodeComments } from '~/containers/node/NodeComments';
|
||||
import { useAuth } from '~/hooks/auth/useAuth';
|
||||
import { useCommentContext } from '~/utils/context/CommentContextProvider';
|
||||
import { useNodeContext } from '~/utils/context/NodeContextProvider';
|
||||
import { useUserContext } from '~/utils/context/UserContextProvider';
|
||||
|
||||
interface IProps {}
|
||||
|
||||
const BorisComments: FC<IProps> = () => {
|
||||
const user = useUserContext();
|
||||
const { isUser } = useAuth();
|
||||
interface Props {}
|
||||
|
||||
const BorisComments: FC<Props> = () => {
|
||||
const { isLoading, comments, onSaveComment } = useCommentContext();
|
||||
const { node } = useNodeContext();
|
||||
|
||||
return (
|
||||
<Group>
|
||||
{(isUser || isSSR) && (
|
||||
<NodeCommentFormSSR
|
||||
user={user}
|
||||
nodeId={node.id}
|
||||
saveComment={onSaveComment}
|
||||
/>
|
||||
)}
|
||||
<NodeCommentFormSSR saveComment={onSaveComment} />
|
||||
|
||||
{isLoading || !comments?.length ? (
|
||||
<NodeNoComments loading count={7} />
|
||||
|
|
|
@ -1,24 +1,21 @@
|
|||
import React, { FC } from 'react';
|
||||
import { FC } from 'react';
|
||||
|
||||
import { Card } from '~/components/containers/Card';
|
||||
import { Filler } from '~/components/containers/Filler';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { Padder } from '~/components/containers/Padder';
|
||||
import { Sticky } from '~/components/containers/Sticky';
|
||||
import { NodeAuthorBlock } from '~/components/node/NodeAuthorBlock';
|
||||
import { NodeCommentFormSSR } from '~/components/node/NodeCommentForm/ssr';
|
||||
import { NodeDeletedBadge } from '~/components/node/NodeDeletedBadge';
|
||||
import { NodeNoComments } from '~/components/node/NodeNoComments';
|
||||
import { NodeRelatedBlock } from '~/components/node/NodeRelatedBlock';
|
||||
import { NodeTagsBlock } from '~/components/node/NodeTagsBlock';
|
||||
import { NodeBacklinks } from '~/containers/node/NodeBacklinks';
|
||||
import { NodeCommentFormSSR } from '~/containers/node/NodeCommentForm/ssr';
|
||||
import { NodeComments } from '~/containers/node/NodeComments';
|
||||
import { useNodeBlocks } from '~/hooks/node/useNodeBlocks';
|
||||
import { useCommentContext } from '~/utils/context/CommentContextProvider';
|
||||
import { useNodeContext } from '~/utils/context/NodeContextProvider';
|
||||
import { useNodeRelatedContext } from '~/utils/context/NodeRelatedContextProvider';
|
||||
import { useUserContext } from '~/utils/context/UserContextProvider';
|
||||
import { useAuthProvider } from '~/utils/providers/AuthProvider';
|
||||
|
||||
import styles from './styles.module.scss';
|
||||
|
||||
|
@ -27,7 +24,6 @@ interface IProps {
|
|||
}
|
||||
|
||||
const NodeBottomBlock: FC<IProps> = ({ commentsOrder }) => {
|
||||
const user = useUserContext();
|
||||
const { node, isLoading, backlinks } = useNodeContext();
|
||||
const {
|
||||
comments,
|
||||
|
@ -36,7 +32,6 @@ const NodeBottomBlock: FC<IProps> = ({ commentsOrder }) => {
|
|||
} = useCommentContext();
|
||||
const { related, isLoading: isLoadingRelated } = useNodeRelatedContext();
|
||||
const { inline } = useNodeBlocks(node, isLoading);
|
||||
const { isUser } = useAuthProvider();
|
||||
|
||||
if (node.deleted_at) {
|
||||
return <NodeDeletedBadge />;
|
||||
|
@ -59,13 +54,7 @@ const NodeBottomBlock: FC<IProps> = ({ commentsOrder }) => {
|
|||
)}
|
||||
</article>
|
||||
|
||||
{isUser && !isLoading && (
|
||||
<NodeCommentFormSSR
|
||||
nodeId={node.id}
|
||||
saveComment={onSaveComment}
|
||||
user={user}
|
||||
/>
|
||||
)}
|
||||
<NodeCommentFormSSR saveComment={onSaveComment} />
|
||||
|
||||
<div className={styles.subheader}>
|
||||
<Filler className={styles.backlinks}>
|
||||
|
|
47
src/containers/node/NodeCommentForm/index.tsx
Normal file
47
src/containers/node/NodeCommentForm/index.tsx
Normal file
|
@ -0,0 +1,47 @@
|
|||
import { FC, useCallback } from 'react';
|
||||
|
||||
import { CommentForm } from '~/components/comment/CommentForm';
|
||||
import { CommentWrapper } from '~/components/containers/CommentWrapper';
|
||||
import { UploadDropzone } from '~/components/upload/UploadDropzone';
|
||||
import { EMPTY_USER } from '~/constants/auth';
|
||||
import { Dialog } from '~/constants/modal';
|
||||
import { UploadSubject, UploadTarget } from '~/constants/uploads';
|
||||
import { useAuth } from '~/hooks/auth/useAuth';
|
||||
import { useUploader } from '~/hooks/data/useUploader';
|
||||
import { useShowModal } from '~/hooks/modal/useShowModal';
|
||||
import { IComment } from '~/types';
|
||||
import { UploaderContextProvider } from '~/utils/context/UploaderContextProvider';
|
||||
|
||||
export interface Props {
|
||||
saveComment: (comment: IComment) => Promise<IComment | undefined>;
|
||||
}
|
||||
|
||||
const NodeCommentForm: FC<Props> = ({ saveComment }) => {
|
||||
const { user, isUser } = useAuth();
|
||||
const showLoginDialog = useShowModal(Dialog.Login);
|
||||
|
||||
const uploader = useUploader(UploadSubject.Comment, UploadTarget.Comments);
|
||||
const onCommentSave = useCallback(
|
||||
async (comment: IComment) => {
|
||||
if (!isUser) {
|
||||
showLoginDialog({});
|
||||
return;
|
||||
}
|
||||
|
||||
return saveComment(comment);
|
||||
},
|
||||
[isUser, showLoginDialog, saveComment],
|
||||
);
|
||||
|
||||
return (
|
||||
<UploadDropzone onUpload={uploader.uploadFiles}>
|
||||
<UploaderContextProvider value={uploader}>
|
||||
<CommentWrapper user={isUser ? user : undefined} isForm>
|
||||
<CommentForm saveComment={onCommentSave} allowUploads={isUser} />
|
||||
</CommentWrapper>
|
||||
</UploaderContextProvider>
|
||||
</UploadDropzone>
|
||||
);
|
||||
};
|
||||
|
||||
export { NodeCommentForm };
|
8
src/containers/node/NodeCommentForm/ssr.ts
Normal file
8
src/containers/node/NodeCommentForm/ssr.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import dynamic from 'next/dynamic';
|
||||
|
||||
import type { Props } from './index';
|
||||
|
||||
export const NodeCommentFormSSR = dynamic<Props>(
|
||||
() => import('./index').then((it) => it.NodeCommentForm),
|
||||
{ ssr: false },
|
||||
);
|
|
@ -3,23 +3,22 @@ import { useCallback, useEffect, useRef } from 'react';
|
|||
import { FormikHelpers, useFormik, useFormikContext } from 'formik';
|
||||
import { array, object, string } from 'yup';
|
||||
|
||||
import { IComment, INode } from '~/types';
|
||||
import { Uploader } from '~/utils/context/UploaderContextProvider';
|
||||
import { IComment, IFile } from '~/types';
|
||||
import { getErrorMessage } from '~/utils/errors/getErrorMessage';
|
||||
import { showErrorToast } from '~/utils/errors/showToast';
|
||||
import { hasPath, path } from '~/utils/ramda';
|
||||
|
||||
const validationSchema = object().shape({
|
||||
text: string(),
|
||||
files: array(),
|
||||
});
|
||||
|
||||
const onSuccess = ({ resetForm, setSubmitting, setErrors }: FormikHelpers<IComment>) => (
|
||||
error?: unknown
|
||||
) => {
|
||||
const onSuccess =
|
||||
({ resetForm, setSubmitting, setErrors }: FormikHelpers<IComment>) =>
|
||||
(error?: unknown) => {
|
||||
setSubmitting(false);
|
||||
const message = getErrorMessage(error);
|
||||
|
||||
if (hasPath(['response', 'data', 'error'], error)) {
|
||||
const message = path(['response', 'data', 'error'], error) as string;
|
||||
if (message) {
|
||||
setErrors({ text: message });
|
||||
showErrorToast(error);
|
||||
return;
|
||||
|
@ -31,31 +30,35 @@ const onSuccess = ({ resetForm, setSubmitting, setErrors }: FormikHelpers<IComme
|
|||
};
|
||||
|
||||
export const useCommentFormFormik = (
|
||||
values: IComment,
|
||||
nodeId: INode['id'],
|
||||
uploader: Uploader,
|
||||
sendData: (data: IComment) => Promise<unknown>,
|
||||
stopEditing?: () => void
|
||||
comment: IComment,
|
||||
files: IFile[],
|
||||
setFiles: (file: IFile[]) => void,
|
||||
sendData: (data: IComment) => Promise<IComment | undefined>,
|
||||
stopEditing?: () => void,
|
||||
) => {
|
||||
const { current: initialValues } = useRef(values);
|
||||
const { current: initialValues } = useRef(comment);
|
||||
|
||||
const onSubmit = useCallback(
|
||||
async (values: IComment, helpers: FormikHelpers<IComment>) => {
|
||||
try {
|
||||
helpers.setSubmitting(true);
|
||||
await sendData({ ...values, files: uploader.files });
|
||||
|
||||
const comment = await sendData({ ...values, files });
|
||||
|
||||
if (comment) {
|
||||
onSuccess(helpers)();
|
||||
}
|
||||
} catch (error) {
|
||||
onSuccess(helpers)(error);
|
||||
}
|
||||
},
|
||||
[sendData, uploader.files]
|
||||
[sendData, files],
|
||||
);
|
||||
|
||||
const onReset = useCallback(() => {
|
||||
uploader.setFiles([]);
|
||||
setFiles([]);
|
||||
if (stopEditing) stopEditing();
|
||||
}, [stopEditing, uploader]);
|
||||
}, [stopEditing, setFiles]);
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues,
|
||||
|
|
|
@ -26,17 +26,19 @@ export const useNodeComments = (nodeId: number, fallbackData?: IComment[]) => {
|
|||
}
|
||||
|
||||
await mutate(
|
||||
prev =>
|
||||
prev?.map(list =>
|
||||
list.map(comment => (comment.id === id ? { ...comment, deleted_at } : comment))
|
||||
(prev) =>
|
||||
prev?.map((list) =>
|
||||
list.map((comment) =>
|
||||
comment.id === id ? { ...comment, deleted_at } : comment,
|
||||
),
|
||||
false
|
||||
),
|
||||
false,
|
||||
);
|
||||
} catch (error) {
|
||||
showErrorToast(error);
|
||||
}
|
||||
},
|
||||
[data, mutate, nodeId]
|
||||
[data, mutate, nodeId],
|
||||
);
|
||||
|
||||
const onEdit = useCallback(
|
||||
|
@ -50,22 +52,37 @@ export const useNodeComments = (nodeId: number, fallbackData?: IComment[]) => {
|
|||
// Comment was created
|
||||
if (!comment.id) {
|
||||
await mutate(
|
||||
data.map((list, index) => (index === 0 ? [result.comment, ...list] : list)),
|
||||
false
|
||||
data.map((list, index) =>
|
||||
index === 0 ? [result.comment, ...list] : list,
|
||||
),
|
||||
false,
|
||||
);
|
||||
return;
|
||||
|
||||
return result.comment;
|
||||
}
|
||||
|
||||
await mutate(
|
||||
prev =>
|
||||
prev?.map(list =>
|
||||
list.map(it => (it.id === result.comment.id ? { ...it, ...result.comment } : it))
|
||||
(prev) =>
|
||||
prev?.map((list) =>
|
||||
list.map((it) =>
|
||||
it.id === result.comment.id ? { ...it, ...result.comment } : it,
|
||||
),
|
||||
false
|
||||
);
|
||||
},
|
||||
[data, mutate, nodeId]
|
||||
),
|
||||
false,
|
||||
);
|
||||
|
||||
return { onLoadMoreComments, onDelete, comments, hasMore, isLoading, onEdit, isLoadingMore };
|
||||
return result.comment;
|
||||
},
|
||||
[data, mutate, nodeId],
|
||||
);
|
||||
|
||||
return {
|
||||
onLoadMoreComments,
|
||||
onDelete,
|
||||
comments,
|
||||
hasMore,
|
||||
isLoading,
|
||||
onEdit,
|
||||
isLoadingMore,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -10,25 +10,31 @@ export interface CommentProviderProps {
|
|||
isLoadingMore: boolean;
|
||||
onShowImageModal: (images: IFile[], index: number) => void;
|
||||
onLoadMoreComments: () => void;
|
||||
onSaveComment: (comment: IComment) => Promise<unknown>;
|
||||
onSaveComment: (comment: IComment) => Promise<IComment | undefined>;
|
||||
onDeleteComment: (id: IComment['id'], isLocked: boolean) => void;
|
||||
}
|
||||
|
||||
const CommentContext = createContext<CommentProviderProps>({
|
||||
// user: EMPTY_USER,
|
||||
comments: [],
|
||||
hasMore: false,
|
||||
lastSeenCurrent: null,
|
||||
isLoading: false,
|
||||
isLoadingMore: false,
|
||||
onSaveComment: async () => {},
|
||||
onSaveComment: async () => undefined,
|
||||
onShowImageModal: () => {},
|
||||
onLoadMoreComments: () => {},
|
||||
onDeleteComment: () => {},
|
||||
});
|
||||
|
||||
export const CommentContextProvider: FC<CommentProviderProps> = ({ children, ...contextValue }) => {
|
||||
return <CommentContext.Provider value={contextValue}>{children}</CommentContext.Provider>;
|
||||
export const CommentContextProvider: FC<CommentProviderProps> = ({
|
||||
children,
|
||||
...contextValue
|
||||
}) => {
|
||||
return (
|
||||
<CommentContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</CommentContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useCommentContext = () => useContext(CommentContext);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue