Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 7x 19x 101x 101x 101x 101x 101x 101x 3x 2x 2x 2x 2x 2x 101x 3x 7x 100x | import { Collapse } from "@mui/material";
import { visuallyHidden } from "@mui/utils";
import Alert from "components/Alert";
import Button from "components/Button";
import MarkdownInput, { MarkdownInputProps } from "components/MarkdownInput";
import { threadKey } from "features/queryKeys";
import { RpcError } from "grpc-web";
import { useTranslation } from "i18n";
import { COMMUNITIES, GLOBAL } from "i18n/namespaces";
import { PostReplyRes } from "proto/threads_pb";
import React, { useRef } from "react";
import { useForm } from "react-hook-form";
import { useMutation, useQueryClient } from "react-query";
import { service } from "service";
import makeStyles from "utils/makeStyles";
const useStyles = makeStyles((theme) => ({
commentForm: {
display: "flex",
flexDirection: "column",
"& > :not(:last-child)": {
marginBlockEnd: theme.spacing(1),
},
},
buttonsContainer: {
display: "flex",
justifyContent: "flex-end",
"& > * + *": {
marginInlineStart: theme.spacing(2),
},
},
}));
interface CommentFormProps {
hideable?: boolean;
onClose?(): void;
shown?: boolean;
threadId: number;
}
interface CommentData {
content: string;
}
function InternalCommentForm(
{ hideable = false, onClose, shown = false, threadId }: CommentFormProps,
ref: React.ForwardedRef<HTMLFormElement>
) {
const { t } = useTranslation([GLOBAL, COMMUNITIES]);
const classes = useStyles();
const {
control,
handleSubmit,
reset: resetForm,
} = useForm<CommentData>({
mode: "onBlur",
});
const resetInputRef: MarkdownInputProps["resetInputRef"] = useRef(null);
const queryClient = useQueryClient();
const {
error,
isLoading,
mutate: postComment,
reset: resetMutation,
} = useMutation<PostReplyRes.AsObject, RpcError, CommentData>(
({ content }) => service.threads.postReply(threadId, content),
{
onSuccess() {
queryClient.invalidateQueries(threadKey(threadId));
resetForm();
resetInputRef.current?.();
resetMutation();
onClose?.();
},
}
);
const onSubmit = handleSubmit((data) => {
postComment(data);
});
return (
<Collapse data-testid={`comment-${threadId}-comment-form`} in={shown}>
<form className={classes.commentForm} onSubmit={onSubmit} ref={ref}>
{error && <Alert severity="error">{error.message}</Alert>}
<span style={visuallyHidden} id={`comment-${threadId}-reply-label`}>
{t("communities:write_comment_a11y_label")}
</span>
<MarkdownInput
control={control}
id={`comment-${threadId}-reply`}
resetInputRef={resetInputRef}
labelId={`comment-${threadId}-reply-label`}
name="content"
/>
<div className={classes.buttonsContainer}>
{hideable && <Button onClick={onClose}>{t("global:close")}</Button>}
<Button loading={isLoading} type="submit">
{t("communities:comment")}
</Button>
</div>
</form>
</Collapse>
);
}
const CommentForm = React.forwardRef(InternalCommentForm);
export default CommentForm;
|