This commit is contained in:
Luke Vella 2022-05-09 08:21:53 +01:00 committed by GitHub
parent 1d7bcddf1b
commit 5c991d7011
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
83 changed files with 2463 additions and 1178 deletions

View file

@ -13,6 +13,7 @@ import {
CreateCommentPayload,
} from "../../api-client/create-comment";
import { requiredString } from "../../utils/form-validation";
import Badge from "../badge";
import Button from "../button";
import CompactButton from "../compact-button";
import Dropdown, { DropdownItem } from "../dropdown";
@ -20,13 +21,13 @@ import DotsHorizontal from "../icons/dots-horizontal.svg";
import Trash from "../icons/trash.svg";
import NameInput from "../name-input";
import TruncatedLinkify from "../poll/truncated-linkify";
import UserAvater from "../poll/user-avatar";
import UserAvatar from "../poll/user-avatar";
import { usePoll } from "../poll-context";
import { usePreferences } from "../preferences/use-preferences";
import { useUserName } from "../user-name-context";
import { useSession } from "../session";
export interface DiscussionProps {
pollId: string;
canDelete?: boolean;
}
interface CommentForm {
@ -36,11 +37,9 @@ interface CommentForm {
const Discussion: React.VoidFunctionComponent<DiscussionProps> = ({
pollId,
canDelete,
}) => {
const { locale } = usePreferences();
const getCommentsQueryKey = ["poll", pollId, "comments"];
const [userName, setUserName] = useUserName();
const queryClient = useQueryClient();
const { data: comments } = useQuery(
getCommentsQueryKey,
@ -64,6 +63,7 @@ const Discussion: React.VoidFunctionComponent<DiscussionProps> = ({
},
{
onSuccess: (newComment) => {
session.refresh();
queryClient.setQueryData(getCommentsQueryKey, (comments) => {
if (Array.isArray(comments)) {
return [...comments, newComment];
@ -75,6 +75,8 @@ const Discussion: React.VoidFunctionComponent<DiscussionProps> = ({
},
);
const { poll } = usePoll();
const { mutate: deleteCommentMutation } = useMutation(
async (payload: { pollId: string; commentId: string }) => {
await axios.delete(`/api/poll/${pollId}/comments/${payload.commentId}`);
@ -89,18 +91,16 @@ const Discussion: React.VoidFunctionComponent<DiscussionProps> = ({
},
);
const session = useSession();
const { register, setValue, control, handleSubmit, formState } =
useForm<CommentForm>({
defaultValues: {
authorName: userName,
authorName: "",
content: "",
},
});
React.useEffect(() => {
setValue("authorName", userName);
}, [setValue, userName]);
const handleDelete = React.useCallback(
(commentId: string) => {
deleteCommentMutation({ pollId, commentId });
@ -124,6 +124,9 @@ const Discussion: React.VoidFunctionComponent<DiscussionProps> = ({
>
<AnimatePresence initial={false}>
{comments.map((comment) => {
const canDelete =
poll.role === "admin" || session.ownsObject(comment);
return (
<motion.div
transition={{ duration: 0.2 }}
@ -137,12 +140,16 @@ const Discussion: React.VoidFunctionComponent<DiscussionProps> = ({
initial={{ scale: 0.8, y: 10 }}
animate={{ scale: 1, y: 0 }}
exit={{ scale: 0.8 }}
data-testid="comment"
className="w-fit rounded-xl border bg-white px-3 py-2 shadow-sm"
>
<div className="flex items-center space-x-2">
<UserAvater name={comment.authorName} />
<UserAvatar
name={comment.authorName}
showName={true}
isYou={session.ownsObject(comment)}
/>
<div className="mb-1">
<span className="mr-1">{comment.authorName}</span>
<span className="mr-1 text-slate-400">&bull;</span>
<span className="text-sm text-slate-500">
{formatRelative(
@ -189,7 +196,6 @@ const Discussion: React.VoidFunctionComponent<DiscussionProps> = ({
},
{
onSuccess: () => {
setUserName(data.authorName);
setValue("content", "");
resolve(data);
},
@ -201,23 +207,28 @@ const Discussion: React.VoidFunctionComponent<DiscussionProps> = ({
>
<textarea
id="comment"
placeholder="Add your comment…"
placeholder="Thanks for the invite!"
className="input w-full py-2 pl-3 pr-4"
{...register("content", { validate: requiredString })}
/>
<div className="mt-1 flex space-x-3">
<Controller
name="authorName"
control={control}
rules={{ validate: requiredString }}
render={({ field }) => <NameInput className="w-full" {...field} />}
/>
<div>
<Controller
name="authorName"
key={session.user?.id}
control={control}
rules={{ validate: requiredString }}
render={({ field }) => (
<NameInput {...field} className="w-full" />
)}
/>
</div>
<Button
htmlType="submit"
loading={formState.isSubmitting}
type="primary"
>
Send
Comment
</Button>
</div>
</form>