import { A } from '@solidjs/router'
import { clsx } from 'clsx'
import { For, Show, Suspense, createMemo, createSignal, lazy } from 'solid-js'
import { Icon } from '~/components/_shared/Icon'
import { ShowIfAuthenticated } from '~/components/_shared/ShowIfAuthenticated'
import { useLocalize } from '~/context/localize'
import { useReactions } from '~/context/reactions'
import { useSession } from '~/context/session'
import { useSnackbar, useUI } from '~/context/ui'
import deleteReactionMutation from '~/graphql/mutation/core/reaction-destroy'
import {
Author,
MutationCreate_ReactionArgs,
MutationUpdate_ReactionArgs,
Reaction,
ReactionKind
} from '~/graphql/schema/core.gen'
import { AuthorLink } from '../../Author/AuthorLink'
import { Userpic } from '../../Author/Userpic'
import { CommentDate } from '../CommentDate'
import { CommentRatingControl } from '../CommentRatingControl'
import styles from './Comment.module.scss'
const SimplifiedEditor = lazy(() => import('../../Editor/SimplifiedEditor'))
type Props = {
comment: Reaction
compact?: boolean
isArticleAuthor?: boolean
sortedComments?: Reaction[]
lastSeen?: number
class?: string
showArticleLink?: boolean
clickedReply?: (id: number) => void
clickedReplyId?: number
onDelete?: (id: number) => void
}
export const Comment = (props: Props) => {
const { t } = useLocalize()
const [isReplyVisible, setIsReplyVisible] = createSignal(false)
const [loading, setLoading] = createSignal(false)
const [editMode, setEditMode] = createSignal(false)
const [clearEditor, setClearEditor] = createSignal(false)
const [editedBody, setEditedBody] = createSignal()
const { session, client } = useSession()
const author = createMemo(() => session()?.user?.app_data?.profile as Author)
const { createShoutReaction, updateShoutReaction } = useReactions()
const { showConfirm } = useUI()
const { showSnackbar } = useSnackbar()
const canEdit = createMemo(
() =>
Boolean(author()?.id) &&
(props.comment?.created_by?.slug === author()?.slug || session()?.user?.roles?.includes('editor'))
)
const body = createMemo(() => (editedBody() ? editedBody()?.trim() : props.comment.body?.trim() || ''))
const remove = async () => {
if (props.comment?.id) {
try {
const isConfirmed = await showConfirm({
confirmBody: t('Are you sure you want to delete this comment?'),
confirmButtonLabel: t('Delete'),
confirmButtonVariant: 'danger',
declineButtonVariant: 'primary'
})
if (isConfirmed) {
const resp = await client()
?.mutation(deleteReactionMutation, { id: props.comment.id })
.toPromise()
const result = resp?.data?.delete_reaction
const { error } = result
const notificationType = error ? 'error' : 'success'
const notificationMessage = error
? t('Failed to delete comment')
: t('Comment successfully deleted')
await showSnackbar({
type: notificationType,
body: notificationMessage,
duration: 3
})
if (!error && props.onDelete) {
props.onDelete(props.comment.id)
}
}
} catch (error) {
await showSnackbar({ body: 'error' })
console.error('[deleteReaction]', error)
}
}
}
const handleCreate = async (value: string) => {
try {
setLoading(true)
await createShoutReaction({
reaction: {
kind: ReactionKind.Comment,
reply_to: props.comment.id,
body: value,
shout: props.comment.shout.id
}
} as MutationCreate_ReactionArgs)
setClearEditor(true)
setIsReplyVisible(false)
setLoading(false)
} catch (error) {
console.error('[handleCreate reaction]:', error)
}
setClearEditor(false)
}
const toggleEditMode = () => {
setEditMode((oldEditMode) => !oldEditMode)
}
const handleUpdate = async (value: string) => {
setLoading(true)
try {
const reaction = await updateShoutReaction({
reaction: {
id: props.comment.id || 0,
kind: ReactionKind.Comment,
body: value,
shout: props.comment.shout.id
}
} as MutationUpdate_ReactionArgs)
if (reaction) {
setEditedBody(value)
}
setEditMode(false)
setLoading(false)
} catch (error) {
console.error('[handleCreate reaction]:', error)
}
}
return (
}>
handleCreate(value)}
submitByCtrlEnter={true}
/>
r.reply_to === props.comment.id)}>
{(c) => (
)}
)
}