mirror of
https://github.com/Radiquum/AniX.git
synced 2025-04-06 00:04:39 +00:00
feat: add user owned comment editing and deleting
This commit is contained in:
parent
6f4e6e2fa6
commit
5b3fc6de4d
3 changed files with 144 additions and 7 deletions
4
TODO.md
4
TODO.md
|
@ -29,10 +29,6 @@
|
||||||
|
|
||||||
### Страница аниме тайтла
|
### Страница аниме тайтла
|
||||||
|
|
||||||
- [ ] Просмотр комментариев и комментирование
|
|
||||||
- [ ] Удаление
|
|
||||||
- [ ] Редактирование
|
|
||||||
|
|
||||||
- [ ] Видео тайтла [трейлеры, опенинги] (?)
|
- [ ] Видео тайтла [трейлеры, опенинги] (?)
|
||||||
|
|
||||||
### Профиль
|
### Профиль
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import { unixToDate, sinceUnixDate } from "#/api/utils";
|
import { unixToDate, sinceUnixDate } from "#/api/utils";
|
||||||
import { useEffect, useState, useCallback } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { ENDPOINTS } from "#/api/config";
|
import { ENDPOINTS } from "#/api/config";
|
||||||
import { Button } from "flowbite-react";
|
import { Button, Dropdown } from "flowbite-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { CommentsAddModal } from "./Comments.Add";
|
import { CommentsAddModal } from "./Comments.Add";
|
||||||
|
import { CommentsEditModal } from "./Comments.Edit";
|
||||||
|
import { useUserStore } from "#/store/auth";
|
||||||
|
|
||||||
export const CommentsComment = (props: {
|
export const CommentsComment = (props: {
|
||||||
release_id: number;
|
release_id: number;
|
||||||
|
@ -30,10 +32,12 @@ export const CommentsComment = (props: {
|
||||||
const [likes, setLikes] = useState(props.comment.likes_count);
|
const [likes, setLikes] = useState(props.comment.likes_count);
|
||||||
const [vote, setVote] = useState(props.comment.vote);
|
const [vote, setVote] = useState(props.comment.vote);
|
||||||
const [isAddCommentsOpen, setIsAddCommentsOpen] = useState(false);
|
const [isAddCommentsOpen, setIsAddCommentsOpen] = useState(false);
|
||||||
|
const [isEditCommentsOpen, setIsEditCommentsOpen] = useState(false);
|
||||||
const [isHidden, setIsHidden] = useState(
|
const [isHidden, setIsHidden] = useState(
|
||||||
!props.isReplying &&
|
!props.isReplying &&
|
||||||
(props.comment.isSpoiler || props.comment.likes_count < -5)
|
(props.comment.isSpoiler || props.comment.likes_count < -5)
|
||||||
);
|
);
|
||||||
|
const user: any = useUserStore((state) => state.user);
|
||||||
|
|
||||||
const [shouldRender, setShouldRender] = useState(true);
|
const [shouldRender, setShouldRender] = useState(true);
|
||||||
const [commentSend, setCommentSend] = useState(false);
|
const [commentSend, setCommentSend] = useState(false);
|
||||||
|
@ -43,6 +47,18 @@ export const CommentsComment = (props: {
|
||||||
parentCommentId = props.parentComment.id;
|
parentCommentId = props.parentComment.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function _deleteComment() {
|
||||||
|
if (props.token) {
|
||||||
|
let url = `${ENDPOINTS.release.info}/comment/delete/${props.comment.id}?token=${props.token}`;
|
||||||
|
await fetch(url);
|
||||||
|
|
||||||
|
if (props.setShouldRender && props.setCommentSend) {
|
||||||
|
props.setShouldRender(true);
|
||||||
|
props.setCommentSend(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function _fetchReplies() {
|
async function _fetchReplies() {
|
||||||
setReplies([]);
|
setReplies([]);
|
||||||
|
@ -135,6 +151,20 @@ export const CommentsComment = (props: {
|
||||||
</time>
|
</time>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
{user && props.profile.id == user.id && (
|
||||||
|
<Dropdown
|
||||||
|
label=""
|
||||||
|
dismissOnClick={false}
|
||||||
|
renderTrigger={() => (
|
||||||
|
<span className="w-6 h-6 bg-gray-400 iconify mdi--more-horiz hover:bg-gray-800 active:bg-gray-800"></span>
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Dropdown.Item onClick={() => setIsEditCommentsOpen(true)}>
|
||||||
|
Редактировать
|
||||||
|
</Dropdown.Item>
|
||||||
|
<Dropdown.Item onClick={() => _deleteComment()}>Удалить</Dropdown.Item>
|
||||||
|
</Dropdown>
|
||||||
|
)}
|
||||||
</footer>
|
</footer>
|
||||||
<div className="relative flex items-center py-2">
|
<div className="relative flex items-center py-2">
|
||||||
<p className="text-gray-800 whitespace-pre-wrap dark:text-gray-400">
|
<p className="text-gray-800 whitespace-pre-wrap dark:text-gray-400">
|
||||||
|
@ -266,11 +296,21 @@ export const CommentsComment = (props: {
|
||||||
release_id={props.release_id}
|
release_id={props.release_id}
|
||||||
token={props.token}
|
token={props.token}
|
||||||
isReply={true}
|
isReply={true}
|
||||||
parentComment={props.comment}
|
parentComment={props.parentComment || props.comment}
|
||||||
parentProfile={props.profile}
|
parentProfile={props.profile}
|
||||||
setShouldRender={props.setShouldRender || setShouldRender}
|
setShouldRender={props.setShouldRender || setShouldRender}
|
||||||
setCommentSend={props.setCommentSend || setCommentSend}
|
setCommentSend={props.setCommentSend || setCommentSend}
|
||||||
/>
|
/>
|
||||||
|
{props.token && (
|
||||||
|
<CommentsEditModal
|
||||||
|
isOpen={isEditCommentsOpen}
|
||||||
|
setIsOpen={setIsEditCommentsOpen}
|
||||||
|
token={props.token}
|
||||||
|
parentComment={props.comment}
|
||||||
|
setShouldRender={props.setShouldRender || setShouldRender}
|
||||||
|
setCommentSend={props.setCommentSend || setCommentSend}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
101
app/components/Comments/Comments.Edit.tsx
Normal file
101
app/components/Comments/Comments.Edit.tsx
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
import { Button, Modal, ToggleSwitch, Label, Textarea } from "flowbite-react";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { ENDPOINTS } from "#/api/config";
|
||||||
|
|
||||||
|
export const CommentsEditModal = (props: {
|
||||||
|
isOpen: boolean;
|
||||||
|
setIsOpen: any;
|
||||||
|
parentComment?: any;
|
||||||
|
token: string;
|
||||||
|
setShouldRender?: any;
|
||||||
|
setCommentSend?: any;
|
||||||
|
}) => {
|
||||||
|
const [message, setMessage] = useState(props.parentComment.message);
|
||||||
|
const [isSpoiler, setIsSpoiler] = useState(props.parentComment.isSpoiler);
|
||||||
|
const [isSending, setIsSending] = useState(false);
|
||||||
|
|
||||||
|
function _sendComment(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const re = /\n/gi;
|
||||||
|
const data = {
|
||||||
|
message: message.replace(re, "\r\n").trim(),
|
||||||
|
spoiler: isSpoiler,
|
||||||
|
};
|
||||||
|
|
||||||
|
async function _send() {
|
||||||
|
const res = await fetch(
|
||||||
|
`${ENDPOINTS.release.info}/comment/edit/${props.parentComment.id}?token=${props.token}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (props.setShouldRender && props.setCommentSend) {
|
||||||
|
props.setShouldRender(true);
|
||||||
|
props.setCommentSend(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
props.setIsOpen(false);
|
||||||
|
setIsSending(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.token && message.trim() != "") {
|
||||||
|
setIsSending(true);
|
||||||
|
_send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
dismissible
|
||||||
|
show={props.isOpen}
|
||||||
|
onClose={() => props.setIsOpen(false)}
|
||||||
|
>
|
||||||
|
<Modal.Header>
|
||||||
|
<p className="text-lg font-bold text-gray-900 lg:text-2xl dark:text-white">
|
||||||
|
Редактировать комментарий
|
||||||
|
</p>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
<form className="flex flex-col gap-4" onSubmit={(e) => _sendComment(e)}>
|
||||||
|
<div>
|
||||||
|
<div className="block mb-2 sr-only">
|
||||||
|
<Label htmlFor="comment" value="Редактировать ваш комментарий." />
|
||||||
|
</div>
|
||||||
|
<Textarea
|
||||||
|
id="comment"
|
||||||
|
value={message}
|
||||||
|
onChange={(e) => setMessage(e.target.value)}
|
||||||
|
placeholder="Редактировать комментарий..."
|
||||||
|
required={true}
|
||||||
|
rows={4}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-wrap items-center justify-between gap-2">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<ToggleSwitch
|
||||||
|
color="blue"
|
||||||
|
theme={{
|
||||||
|
toggle: {
|
||||||
|
checked: {
|
||||||
|
color: {
|
||||||
|
blue: "border-blue-700 bg-blue-700",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
checked={isSpoiler}
|
||||||
|
onChange={() => setIsSpoiler(!isSpoiler)}
|
||||||
|
label="Спойлер"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button type="submit" color={"blue"} disabled={isSending}>
|
||||||
|
Изменить
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Modal.Body>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
Loading…
Add table
Reference in a new issue