diff --git a/src/components/Article/Comment.module.scss b/src/components/Article/Comment.module.scss index e1ae44ba..ea01b08b 100644 --- a/src/components/Article/Comment.module.scss +++ b/src/components/Article/Comment.module.scss @@ -1,12 +1,50 @@ .comment { - background-color: #fff; - margin: 0 -2.4rem 1.5em; + margin: 0 -2.4rem 0.5em; padding: 0.8rem 2.4rem; transition: background-color 0.3s; - + position: relative; + &:last-child { + margin-bottom: 0; + } + .comment { + &:before, + &:after { + content: ''; + left: 0; + position: absolute; + } + &:before { + border-bottom: 2px solid #ccc; + border-left: 2px solid #ccc; + border-radius: 0 0 0 1.2rem; + top: -1rem; + height: 2.4rem; + width: 1.2rem; + } + &:after { + background: #ccc; + height: 100%; + top: 0; + width: 2px; + } + &:last-child:after { + display: none; + } + } + .shout-body { + @include font-size(1.5rem); + margin-bottom: 1em; + *:last-child { + margin-bottom: 0; + } + } + .author { + align-items: center; + margin-bottom: 1.4rem; + } +} +.commentContent { &:hover { - background-color: #f6f6f6; - .commentControlReply, .commentControlShare, .commentControlDelete, @@ -15,60 +53,22 @@ opacity: 1; } } - - .shout-body { - @include font-size(1.5rem); - - margin-bottom: 1em; - - *:last-child { - margin-bottom: 0; - } - } - - .author { - align-items: center; - margin-bottom: 1.4rem; - } } - -.commentLevel1 { - margin-left: 3.2rem; -} - -.commentLevel2 { - margin-left: 6.4rem; -} - -.commentLevel3 { - margin-left: 9.6rem; -} - -.commentLevel4 { - margin-left: 12.8rem; -} - -.commentLevel5 { - margin-left: 16rem; -} - .commentControls { @include font-size(1.2rem); margin-bottom: 0.5em; } - .commentControlReply, .commentControlShare, .commentControlDelete, .commentControlEdit, .commentControlComplain { @include media-breakpoint-up(md) { - opacity: 0; + //opacity: 0; transition: opacity 0.3s; } } - .commentControlReply, .commentControlShare, .commentControlDelete, @@ -78,7 +78,6 @@ width: 1.2rem; } } - .commentControl { border: none; color: #696969; @@ -89,116 +88,74 @@ padding: 0.2em 0.3em; transition: opacity 0.2s, color 0.3s, background-color 0.3s; vertical-align: top; - &:hover { background: #000; color: #fff; - .icon { filter: invert(1); opacity: 1; } } - .icon { filter: invert(0); margin-right: 0.3em; opacity: 0.6; transition: filter 0.3s, opacity 0.2s; - img { margin-bottom: -0.1em; } } } - .commentControlReply { .icon { height: 1.2em; width: 1.2em; } } - .commentBody { @include font-size(1.5rem); line-height: 1.47; } - .commentAuthor, .commentDate, .commentRating { @include font-size(1.2rem); } - .commentDate { color: rgb(0 0 0 / 30%); flex: 1; - @include media-breakpoint-down(md) { margin-left: 1rem; } } - .commentDetails { display: flex; margin-bottom: 1.2rem; } - .commentRating { align-items: center; display: flex; font-weight: bold; } - .commentRatingValue { padding: 0 0.3em; } - .commentRatingPositive { color: #2bb452; } - .commentRatingNegative { color: #d00820; } - .commentRatingControl { border-left: 6px solid transparent; border-right: 6px solid transparent; height: 0; width: 0; } - .commentRatingControlUp { border-bottom: 8px solid rgb(0 0 0 / 40%); } - .commentRatingControlDown { border-top: 8px solid rgb(0 0 0 / 40%); } - -.replyForm { - background: #fff; - border: 2px solid rgb(38 56 217 / 50%); - border-radius: 0.8rem; - margin-left: 2.4rem; - position: relative; - - textarea { - border: none; - border-radius: 0.8rem; - padding-top: 1.2rem; - } -} - -.replyFormControls { - padding: 0.5rem 1.6rem 1.6rem; - text-align: right; - - button { - @include font-size(1.6rem); - - margin-left: 1.2rem; - } -} diff --git a/src/components/Article/Comment.tsx b/src/components/Article/Comment.tsx index 0b3e5ee9..b3eef418 100644 --- a/src/components/Article/Comment.tsx +++ b/src/components/Article/Comment.tsx @@ -1,32 +1,67 @@ import styles from './Comment.module.scss' import { Icon } from '../_shared/Icon' import { AuthorCard } from '../Author/Card' -import { Show, createMemo, createSignal } from 'solid-js' +import { Show, createMemo, createSignal, For } from 'solid-js' import { clsx } from 'clsx' -import type { Author, Reaction as Point } from '../../graphql/types.gen' +import type { Author, Reaction } from '../../graphql/types.gen' import { t } from '../../utils/intl' -// import { createReaction, updateReaction, deleteReaction } from '../../stores/zine/reactions' +import { createReaction, deleteReaction } from '../../stores/zine/reactions' import MD from './MD' -import { deleteReaction } from '../../stores/zine/reactions' import { formatDate } from '../../utils' import { SharePopup } from './SharePopup' import stylesHeader from '../Nav/Header.module.scss' import Userpic from '../Author/Userpic' +import { useSession } from '../../context/session' +import { ReactionKind } from '../../graphql/types.gen' +import GrowingTextarea from '../_shared/GrowingTextarea' -export default (props: { - level?: number - comment: Partial - canEdit?: boolean +type Props = { + comment: Reaction compact?: boolean -}) => { + reactions?: Reaction[] +} + +const Comment = (props: Props) => { const [isReplyVisible, setIsReplyVisible] = createSignal(false) + const [loading, setLoading] = createSignal(false) + const [errorMessage, setErrorMessage] = createSignal(null) + const { session } = useSession() + + const canEdit = createMemo(() => props.comment.createdBy?.slug === session()?.user?.slug) const comment = createMemo(() => props.comment) const body = createMemo(() => (comment().body || '').trim()) - const remove = () => { + const remove = async () => { if (comment()?.id) { - console.log('[comment] removing', comment().id) - deleteReaction(comment().id) + try { + await deleteReaction(comment().id) + } catch (error) { + console.error('[deleteReaction]', error) + } + } + } + + const handleCreate = async (value) => { + try { + setLoading(true) + await createReaction( + { + kind: ReactionKind.Comment, + replyTo: props.comment.id, + body: value, + shout: props.comment.shout.id + }, + { + name: session().user.name, + userpic: session().user.userpic, + slug: session().user.slug + } + ) + setIsReplyVisible(false) + setLoading(false) + } catch (error) { + console.error('[handleCreate reaction]:', error) + setErrorMessage(t('Something went wrong, please try again')) } } const formattedDate = createMemo(() => @@ -34,7 +69,7 @@ export default (props: { ) return ( -
+
  • -
    @@ -85,14 +119,15 @@ export default (props: {
    - + {/*FIXME implement edit comment modal*/} {/* -
    -