Skip to content

Commit 76ef9d5

Browse files
author
Roshan Jossy
committed
use text area for comments
1 parent a2e16ca commit 76ef9d5

12 files changed

+845
-53
lines changed

src/components/Container.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { ReactNode } from "react";
1+
import React, { ReactNode } from 'react'
22

3-
export default function Container ({children}: any) {
4-
return (
5-
<div className="p-16">
6-
{children}
7-
</div>
8-
)
9-
}
3+
type ContainerProps = {
4+
children: ReactNode
5+
}
6+
7+
export default function Container({ children }: ContainerProps) {
8+
return <div className="p-16">{children}</div>
9+
}

src/components/ExpandingTextarea.tsx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React from 'react'
2+
3+
const MIN_TEXTAREA_HEIGHT = 32
4+
5+
type ExpandingTextareaProps = {
6+
value: string
7+
setValue: (value: string) => void
8+
className?: string
9+
placeholder?: string
10+
}
11+
12+
export default function ExpandingTextarea({
13+
value,
14+
setValue,
15+
className,
16+
placeholder,
17+
}: ExpandingTextareaProps) {
18+
const textareaRef = React.useRef<null | HTMLTextAreaElement>(null)
19+
const onChange = (event: React.ChangeEvent<HTMLTextAreaElement>) =>
20+
setValue(event.target.value)
21+
22+
React.useLayoutEffect(() => {
23+
if (textareaRef.current) {
24+
textareaRef.current.style.height = 'inherit'
25+
// Set height
26+
textareaRef.current.style.height = `${Math.max(
27+
textareaRef.current.scrollHeight,
28+
MIN_TEXTAREA_HEIGHT
29+
)}px`
30+
}
31+
// Reset height - important to shrink on delete
32+
}, [value])
33+
34+
return (
35+
<textarea
36+
className={className}
37+
onChange={onChange}
38+
placeholder={placeholder}
39+
ref={textareaRef}
40+
style={{
41+
minHeight: MIN_TEXTAREA_HEIGHT,
42+
resize: 'none',
43+
}}
44+
value={value}
45+
/>
46+
)
47+
}

src/components/comment/Comments.tsx

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { graphql, usePaginationFragment } from 'react-relay'
2+
import NewComment from './NewComment'
3+
4+
const Comments = ({ story }: any) => {
5+
const { data, loadNext, hasNext, refetch } = usePaginationFragment(
6+
graphql`
7+
fragment Comments_story on Story
8+
@refetchable(queryName: "Comments_storyQuery")
9+
@argumentDefinitions(
10+
count: { type: "Int", defaultValue: 20 }
11+
cursor: { type: "String" }
12+
) {
13+
comments(first: $count, after: $cursor)
14+
@connection(key: "Comments_story__comments") {
15+
edges {
16+
node {
17+
id
18+
contentJson
19+
}
20+
}
21+
}
22+
}
23+
`,
24+
story
25+
)
26+
27+
if (!data || !data.comments) {
28+
return <></>
29+
}
30+
31+
return (
32+
<div className="space-y-4">
33+
{data.comments.edges.map((comment: any) => (
34+
<div key={comment.id}>{comment.node.contentJson}</div>
35+
))}
36+
{hasNext ? (
37+
<button
38+
className="text-gray-600 dark:text-gray-300"
39+
onClick={() => {
40+
loadNext(2)
41+
}}
42+
>
43+
Load more
44+
</button>
45+
) : null}
46+
<NewComment storyId={story.id} refetch={refetch} />
47+
</div>
48+
)
49+
}
50+
51+
export default Comments

src/components/comment/NewComment.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { useState } from 'react'
2+
import { graphql, RefetchFnDynamic, useMutation } from 'react-relay'
3+
import { Options } from 'react-relay/relay-hooks/useRefetchableFragmentNode'
4+
import { OperationType } from 'relay-runtime'
5+
import Button from '../Button'
6+
import ExpandingTextarea from '../ExpandingTextarea'
7+
8+
type NewCommentProps = {
9+
storyId: string
10+
refetch: RefetchFnDynamic<OperationType, any, Options>
11+
}
12+
13+
export default function NewComment({ storyId, refetch }: NewCommentProps) {
14+
const [comment, setComment] = useState('')
15+
16+
const [commitMutation, isMutationInFlight] = useMutation(
17+
graphql`
18+
mutation NewCommentMutation($input: CommentInput!) {
19+
createComment(comment: $input) {
20+
id
21+
}
22+
}
23+
`
24+
)
25+
26+
const handleCommentPost = () => {
27+
commitMutation({
28+
variables: {
29+
input: { storyID: storyId, contentJson: comment, abstractContent: '' },
30+
},
31+
onCompleted: () => {
32+
refetch({}, { fetchPolicy: 'network-only' })
33+
},
34+
})
35+
}
36+
37+
return (
38+
<div className="w-full dark:text-gray-300 dark:bg-dark-600 flex flex-col items-end">
39+
<div className="textarea-container w-full">
40+
<ExpandingTextarea
41+
value={comment}
42+
setValue={setComment}
43+
placeholder="Write a comment..."
44+
className="w-full dark:text-gray-300 dark:bg-dark-600 focus-visible:outline-none"
45+
/>
46+
</div>
47+
<Button onClick={() => handleCommentPost()}>Post</Button>
48+
</div>
49+
)
50+
}

src/components/feed/StoryPreviewFooter.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export default function StoryPreviewFooter({ story }: StoryPreviewFooterProps) {
4141
input: { storyID: data.id },
4242
},
4343
onCompleted: () => {
44-
refetch({})
44+
refetch({}, { fetchPolicy: 'network-only' })
4545
},
4646
})
4747
}

src/pages/story/[id].tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { NextPageContext } from 'next'
22
import dynamic from 'next/dynamic'
33
import { graphql, usePreloadedQuery } from 'react-relay'
44
import { RelayProps, withRelay } from 'relay-nextjs'
5+
import Comments from '../../components/comment/Comments'
56
import Layout from '../../components/Layout'
67
import UserDetails from '../../components/UserDetails/UserDetails'
78
import { getClientEnvironment } from '../../lib/client_environment'
@@ -20,6 +21,7 @@ const StoryQuery = graphql`
2021
createdBy {
2122
...UserDetails_user
2223
}
24+
...Comments_story
2325
}
2426
}
2527
}
@@ -42,6 +44,7 @@ const Story = ({
4244
}
4345
>
4446
<Editor body={query?.node?.contentJson} editable={false} />
47+
<Comments story={query.node} />
4548
</Layout>
4649
</div>
4750
)

src/queries/__generated__/Comments_story.graphql.ts

Lines changed: 168 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)