-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
057dc72
commit e84ff81
Showing
13 changed files
with
597 additions
and
235 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import { gql, useMutation } from '@apollo/client'; | ||
import { useState, useRef, useEffect } from 'react'; | ||
import { Spinner, PaperPlaneTilt } from '@phosphor-icons/react'; | ||
import styled, { withTheme } from 'styled-components'; | ||
import { themeGet } from '@styled-system/theme-get'; | ||
import Color from 'color'; | ||
import { TypeStyles } from '../../ui-kit/Typography'; | ||
import { system } from '../../ui-kit/_lib/system'; | ||
import { Avatar, Box, Button, H5 } from '../../ui-kit'; | ||
import { useCurrentUser } from '../../hooks'; | ||
|
||
const ADD_COMMENT = gql` | ||
mutation addComment($parentId: ID!, $text: String!) { | ||
addComment(parentId: $parentId, text: $text) { | ||
id | ||
isLiked | ||
text | ||
person { | ||
id | ||
firstName | ||
lastName | ||
photo { | ||
uri | ||
} | ||
} | ||
} | ||
} | ||
`; | ||
|
||
const TextArea = withTheme(styled.textarea` | ||
${TypeStyles.BodyText} | ||
padding: 0; | ||
padding-right: 8px; | ||
outline: none; | ||
flex-grow: 1; | ||
max-height: 200px; | ||
transition: all ${themeGet('timing.xl')} ease-out; | ||
placeholder-text-color: ${({ theme }) => Color(theme.colors.text.secondary).alpha(0)}; | ||
caret-color: ${themeGet('colors.base.primary')}; | ||
border: none; | ||
resize: none; | ||
${system}; | ||
`); | ||
|
||
const AddComment = ({ parent, onAdd }) => { | ||
const { currentUser } = useCurrentUser(); | ||
const [comment, setComment] = useState(''); | ||
const textAreaRef = useRef(null); | ||
|
||
const [addComment, { data, loading, error }] = useMutation(ADD_COMMENT, { | ||
update(cache, { data: { addComment } }) { | ||
cache.modify({ | ||
id: cache.identify(parent), | ||
fields: { | ||
comments(existingComments = []) { | ||
const newCommentRef = cache.writeFragment({ | ||
data: addComment, | ||
fragment: gql` | ||
fragment NewComment on Comment { | ||
id | ||
isLiked | ||
text | ||
person { | ||
id | ||
firstName | ||
lastName | ||
photo { | ||
uri | ||
} | ||
} | ||
} | ||
`, | ||
}); | ||
return [...existingComments, newCommentRef]; | ||
}, | ||
}, | ||
}); | ||
}, | ||
}); | ||
|
||
const handleInputChange = (e) => { | ||
setComment(e.target.value); | ||
}; | ||
|
||
const handleAddComment = async () => { | ||
await addComment({ variables: { parentId: parent.id, text: comment } }); | ||
setComment(''); | ||
textAreaRef.current.style.height = 'auto'; | ||
if (onAdd) onAdd(data); | ||
}; | ||
|
||
useEffect(() => { | ||
if (textAreaRef.current) { | ||
// We need to reset the height momentarily to get the correct scrollHeight for the textarea | ||
textAreaRef.current.style.height = '0px'; | ||
const scrollHeight = textAreaRef.current.scrollHeight; | ||
|
||
// We then set the height directly, outside of the render loop | ||
// Trying to set this with state or a ref will product an incorrect value. | ||
textAreaRef.current.style.height = scrollHeight + 'px'; | ||
} | ||
}, [textAreaRef, comment]); | ||
|
||
return ( | ||
<Box p="xs" borderTop="1px solid" borderColor="text.quaternary"> | ||
<Box display="flex" flexDirection="row" alignItems="center" gridGap={8} pb="xs"> | ||
<Avatar | ||
src={currentUser?.profile?.photo?.uri} | ||
firstName={currentUser?.profile?.firstName} | ||
lastName={currentUser?.profile?.lastName} | ||
width={48} | ||
/> | ||
<H5> | ||
{currentUser?.profile.firstName} {currentUser?.profile?.lastName} | ||
</H5> | ||
</Box> | ||
<Box display="flex" flexDirection="row" justifyContent="space-between" alignItems="center"> | ||
<TextArea | ||
value={comment} | ||
onChange={handleInputChange} | ||
placeholder="Add a response" | ||
ref={textAreaRef} | ||
/> | ||
<Button | ||
disabled={!comment} | ||
onClick={comment ? handleAddComment : undefined} | ||
icon={loading ? <Spinner /> : <PaperPlaneTilt weight="fill" />} | ||
padding={6} | ||
/> | ||
</Box> | ||
</Box> | ||
); | ||
}; | ||
|
||
export default AddComment; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { Box, H5, Avatar } from '../../ui-kit'; | ||
|
||
// turn line breaks into <br> tags and strip out any other html | ||
function formatText(text) { | ||
return text.split('\n').map((line, i) => ( | ||
<span key={i}> | ||
{line} | ||
<br /> | ||
</span> | ||
)); | ||
} | ||
const Comment = ({ text, person }) => ( | ||
<Box p="xs" borderBottom="1px solid" borderColor="text.quaternary"> | ||
<Box display="flex" flexDirection="row" alignItems="center" gridGap={8} pb="xs"> | ||
<Avatar | ||
src={person?.photo?.uri} | ||
firstName={person.firstName} | ||
lastName={person.lastName} | ||
width={48} | ||
/> | ||
<H5> | ||
{person.firstName} {person.lastName} | ||
</H5> | ||
</Box> | ||
<p>{formatText(text)}</p> | ||
</Box> | ||
); | ||
|
||
export default Comment; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { useRef, useState } from 'react'; | ||
import { Box, H4, Button } from '../../ui-kit'; | ||
import { X, ArrowRight, ChatsCircle } from '@phosphor-icons/react'; | ||
import { useCurrentUser } from '../../hooks'; | ||
import { AuthManager } from '../../components'; | ||
|
||
import { useAuth } from '../../providers/AuthProvider'; | ||
import authSteps from '../Auth/authSteps'; | ||
|
||
import Comment from './Comment'; | ||
import AddComment from './AddComment'; | ||
|
||
export const SIDEBAR_WITH = 400; | ||
|
||
const Comments = ({ visible, parent, comments, onClose }) => { | ||
const { currentUser } = useCurrentUser(); | ||
const [state] = useAuth(); | ||
const scrollRef = useRef(null); | ||
const [showAuth, setShowAuth] = useState(false); | ||
|
||
const scrollToBottom = () => { | ||
requestAnimationFrame(() => scrollRef.current.scrollIntoView(false)); | ||
}; | ||
|
||
return ( | ||
<Box | ||
width={{ md: SIDEBAR_WITH }} | ||
position="fixed" | ||
top={58} | ||
right={0} | ||
bottom={0} | ||
left={{ _: 0, md: 'auto' }} | ||
backgroundColor="fill.paper" | ||
borderLeftStyle={{ _: 'none', md: 'solid' }} | ||
borderLeftWidth={{ _: '0', md: '1px' }} | ||
borderLeftColor="text.quaternary" | ||
display="flex" | ||
flexDirection="column" | ||
> | ||
<Box | ||
p="xs" | ||
borderBottom="1px solid" | ||
borderColor="text.quaternary" | ||
display="flex" | ||
flexDirection="row" | ||
justifyContent="space-between" | ||
alignItems="center" | ||
> | ||
<H4>Responses</H4> | ||
<Box cursor="pointer" display="flex" color="text.secondary" onClick={onClose}> | ||
<X /> | ||
</Box> | ||
</Box> | ||
{currentUser ? ( | ||
<> | ||
<Box style={{ overflowY: 'scroll' }}> | ||
{comments.map((comment) => ( | ||
<Comment key={comment.id} {...comment} /> | ||
))} | ||
<div ref={scrollRef} style={{ height: 1 }} /> | ||
</Box> | ||
<AddComment parent={parent} onAdd={scrollToBottom} /> | ||
</> | ||
) : ( | ||
<Box | ||
p="md" | ||
flexGrow="1" | ||
display="flex" | ||
flexDirection="column" | ||
alignItems="center" | ||
justifyContent="center" | ||
> | ||
<Box color="base.primary"> | ||
<ChatsCircle size={90} weight="fill" /> | ||
</Box> | ||
<H4>Join the conversation</H4> | ||
<Button | ||
variant="secondary" | ||
title="Sign up or Login" | ||
onClick={() => setShowAuth(true)} | ||
color="base.primary" | ||
icon={<ArrowRight size={24} />} | ||
mt="base" | ||
/> | ||
</Box> | ||
)} | ||
{showAuth && state.step !== authSteps.Success ? ( | ||
<AuthManager onClose={() => setShowAuth(false)} /> | ||
) : null} | ||
</Box> | ||
); | ||
}; | ||
|
||
export default Comments; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import Comments, { SIDEBAR_WITH } from './Comments'; | ||
|
||
export { SIDEBAR_WITH }; | ||
|
||
export default Comments; |
Oops, something went wrong.