/**
* WordPress dependencies
*/
import { TextareaControl } from '@safe-wordpress/components';
import { useDispatch, useSelect } from '@safe-wordpress/data';
import {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from '@safe-wordpress/element';
import { _x } from '@safe-wordpress/i18n';
/**
* External dependencies
*/
import clsx from 'clsx';
import { trim } from 'lodash';
import {
store as NC_DATA,
useAuthorName,
withSubscriptionCheck,
} from '@nelio-content/data';
import { DeleteButton } from '@nelio-content/components';
import { dateI18n, getSettings } from '@nelio-content/date';
import { createComment } from '@nelio-content/utils';
import type {
EditorialComment,
PostId,
PostTypeName,
UserId,
} from '@nelio-content/types';
/**
* Internal dependencies
*/
import { useIsSaving } from '../../hooks';
import { store as NC_POST_EDITOR } from '../../store';
export const Comments = (): JSX.Element => ;
const InternalComments = withSubscriptionCheck(
'raw/editorial-comments',
() => (
)
);
// =======
// HELPERS
// =======
const CommentList = (): JSX.Element | null => {
const ref = useRef< HTMLUListElement >( null );
const { comments, newComments } = useComments();
const deleteComment = useDeleteComment();
const currentCount = newComments.length;
const [ count, setCount ] = useState( -1 );
useEffect( () => {
if ( count === currentCount ) {
return;
}
if ( count < currentCount ) {
ref.current?.scrollTo( {
top: 999_999,
behavior: count === -1 ? undefined : 'smooth',
} );
}
setCount( currentCount );
}, [ count, currentCount, setCount ] );
return (
{ comments.map( ( comment ) => (
) ) }
{ newComments.map( ( comment ) => (
deleteComment( comment.id ) }
/>
) ) }
);
};
const CommentForm = (): JSX.Element => {
const [ value, setValue ] = useState( '' );
const isSaving = useIsSaving();
const addComment = useAddComment();
return (
{
if ( 'Enter' !== ev.key ) {
return;
}
ev.preventDefault();
addComment( value );
setValue( '' );
} }
/>
);
};
type CommentProps = {
readonly comment: EditorialComment;
readonly onDelete?: () => void;
};
const Comment = ( { comment, onDelete }: CommentProps ) => {
const isSaving = useIsSaving();
const isCurrentUsers = useIsCurrentUsers( comment?.authorId );
const authorName = useAuthorName( comment?.authorId );
return (
{ comment?.comment || '' }
{ ! onDelete ? (
{ ! isCurrentUsers && (
{ authorName }
) }
{ dateI18n(
getSettings().formats.datetime,
comment?.date
) }
) : (
{ isSaving
? _x( 'Saving…', 'text', 'nelio-content' )
: _x(
'New',
'text (editorial comment)',
'nelio-content'
) }
{ ' • ' }
) }
);
};
// =====
// HOOKS
// =====
const useComments = () => {
const postId = useSelect( ( s ) => s( NC_POST_EDITOR ).getId(), [] );
const comments = useSelect(
( s ) => s( NC_DATA ).getCommentsRelatedToPost( postId ),
[ postId ]
);
const newComments = useSelect(
( s ) => s( NC_POST_EDITOR ).getNewComments(),
[]
);
return useMemo(
() => ( { comments, newComments } ),
[ comments, newComments ]
);
};
const useDeleteComment = () => {
const { setNewComments } = useDispatch( NC_POST_EDITOR );
const newComments = useSelect(
( select ) => select( NC_POST_EDITOR ).getNewComments(),
[]
);
return useCallback(
( id: EditorialComment[ 'id' ] ) => {
void setNewComments( newComments.filter( ( c ) => c.id !== id ) );
},
[ setNewComments, newComments ]
);
};
const useAddComment = () => {
const { setNewComments } = useDispatch( NC_POST_EDITOR );
const newComments = useSelect(
( select ) => select( NC_POST_EDITOR ).getNewComments(),
[]
);
return useCallback(
( comment: EditorialComment[ 'comment' ] ) => {
const text = trim( comment );
if ( ! text ) {
return;
}
void setNewComments( [
...newComments,
{
...createComment( 0 as PostId, 'post' as PostTypeName ),
comment: text,
},
] );
},
[ setNewComments, newComments ]
);
};
const useIsCurrentUsers = ( commentAuthor?: UserId ) =>
useSelect(
( select ) => select( NC_DATA ).getCurrentUserId() === commentAuthor,
[ commentAuthor ]
);