Wired up adding replies

This commit is contained in:
Simon Backx 2022-07-07 11:12:00 +02:00
parent 2e58f65b24
commit 6a179b06c4
3 changed files with 108 additions and 79 deletions

View File

@ -28,6 +28,33 @@ async function addComment({state, api, data: comment}) {
};
}
async function addReply({state, api, data: {reply, parent}}) {
let comment = reply;
comment.parent_id = parent.id;
const data = await api.comments.add({comment});
comment = data.comments[0];
// Temporary workaround for missing member relation (bug in API)
comment = {
...comment,
member: state.member
};
// Replace the comment in the state with the new one
return {
comments: state.comments.map((c) => {
if (c.id === parent.id) {
return {
...parent,
replies: [...parent.replies, comment]
};
}
return c;
})
};
}
async function hideComment({state, adminApi, data: comment}) {
await adminApi.hideComment(comment.id);
@ -141,6 +168,7 @@ const Actions = {
showComment,
likeComment,
unlikeComment,
addReply,
loadMoreComments
};

View File

@ -54,7 +54,7 @@ const Comment = (props) => {
</div>
{isInReplyMode &&
<div className={`ml-14 mt-8`}>
<ReplyForm />
<ReplyForm parent={comment} />
</div>
}
{hasReplies &&

View File

@ -1,85 +1,87 @@
import React from 'react';
import React, {useState, useContext} from 'react';
import AppContext from '../AppContext';
import Avatar from './Avatar';
class ReplyForm extends React.Component {
static contextType = AppContext;
const ReplyForm = (props) => {
const [message, setMessage] = useState('');
const [focused, setFocused] = useState(false);
const {member, postId, dispatchAction} = useContext(AppContext);
constructor(props) {
super(props);
this.state = {
message: '',
focused: false
const getHTML = () => {
// Convert newlines to <br> for now (until we add a real editor)
return message.replace('\n', '<br>');
};
this.submitForm = this.submitForm.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleBlur = this.handleBlur.bind(this);
this.handleFocus = this.handleFocus.bind(this);
}
getHTML() {
const text = this.state.message;
// Convert newlines to <br> for now (until we add a real editor)
return text.replace('\n', '<br>');
}
async submitForm(event) {
const submitForm = async (event) => {
event.preventDefault();
// TODO: Add logic to make this work
if (message.length === 0) {
// alert('Please enter a message'); TODO: Check, but don't think we really need this
return;
}
try {
// Send comment to server
await dispatchAction('addReply', {
parent: props.parent,
reply: {
post_id: postId,
status: 'published',
html: getHTML()
}
});
// Clear message on success
this.setState({
message: '',
focused: false
});
setMessage('');
setFocused(false);
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
}
};
handleChange(event) {
this.setState({message: event.target.value});
}
const handleChange = (event) => {
setMessage(event.target.value);
};
handleBlur(event) {
if (this.state.message === '') {
this.setState({focused: false});
}
const handleBlur = (event) => {
if (message === '') {
setFocused(false);
}
};
handleFocus(event) {
this.setState({focused: true});
}
const handleFocus = (event) => {
setFocused(true);
};
render() {
return (
<form onSubmit={this.submitForm} className="comment-form">
<form onSubmit={submitForm} className="comment-form">
<div className="w-full">
<div className="flex mb-4 space-x-4 justify-start items-center">
<Avatar />
<div>
<h4 className="text-lg font-sans font-bold mb-1 tracking-tight dark:text-neutral-300">{this.context.member.name}</h4>
<h4 className="text-lg font-sans font-bold mb-1 tracking-tight dark:text-neutral-300">{member.name}</h4>
<h6 className="text-[13px] text-neutral-400 font-sans">Now</h6>
</div>
</div>
<div className="pr-3 font-sans leading-normal dark:text-neutral-300">
<div className="relative w-full">
<textarea
className={`transition-[height] duration-150 w-full resize-none rounded-md border border-slate-200 p-3 font-sans mb-1 leading-normal focus:outline-0 dark:bg-[rgba(255,255,255,0.08)] dark:border-none dark:text-neutral-300 ${this.state.focused ? 'cursor-text h-40' : 'cursor-pointer overflow-hidden h-12 hover:border-slate-300'}`}
value={this.state.message}
onChange={this.handleChange}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
placeholder={this.state.focused ? '' : 'Reply to this comment'}
className={`transition-[height] duration-150 w-full resize-none rounded-md border border-slate-200 p-3 font-sans mb-1 leading-normal focus:outline-0 dark:bg-[rgba(255,255,255,0.08)] dark:border-none dark:text-neutral-300 ${focused ? 'cursor-text h-40' : 'cursor-pointer overflow-hidden h-12 hover:border-slate-300'}`}
value={message}
onChange={handleChange}
onFocus={handleFocus}
onBlur={handleBlur}
placeholder={focused ? '' : 'Reply to this comment'}
/>
<button
className={`transition-[opacity] duration-150 rounded-md border py-2 px-3 font-sans text-sm text-center bg-black font-semibold text-white dark:bg-[rgba(255,255,255,0.8)] dark:text-neutral-800 ${this.state.focused ? 'opacity-100' : 'opacity-0'}`}
className={`transition-[opacity] duration-150 rounded-md border py-2 px-3 font-sans text-sm text-center bg-black font-semibold text-white dark:bg-[rgba(255,255,255,0.8)] dark:text-neutral-800 ${focused ? 'opacity-100' : 'opacity-0'}`}
type="submit">
Add your reply
</button>
<button
className={`transition-[opacity] duration-100 absolute top-2 right-2 rounded-md border py-1 px-2 font-sans text-sm text-center bg-black font-semibold text-white pointer-events-none dark:bg-[rgba(255,255,255,0.8)] dark:text-neutral-800 ${this.state.focused ? 'opacity-0' : 'opacity-100'}`}
disabled="true">
className={`transition-[opacity] duration-100 absolute top-2 right-2 rounded-md border py-1 px-2 font-sans text-sm text-center bg-black font-semibold text-white pointer-events-none dark:bg-[rgba(255,255,255,0.8)] dark:text-neutral-800 ${focused ? 'opacity-0' : 'opacity-100'}`}
disabled={true}>
Reply
</button>
</div>
@ -87,7 +89,6 @@ class ReplyForm extends React.Component {
</div>
</form>
);
}
}
};
export default ReplyForm;