mirror of
https://github.com/Radiquum/AniX.git
synced 2025-04-07 00:34:41 +00:00
feat: add viewing of all comments for a release
This commit is contained in:
parent
fb21744536
commit
a4618124ea
3 changed files with 177 additions and 43 deletions
3
TODO.md
3
TODO.md
|
@ -31,7 +31,7 @@
|
||||||
### Страница аниме тайтла
|
### Страница аниме тайтла
|
||||||
|
|
||||||
- [ ] Просмотр комментариев и комментирование
|
- [ ] Просмотр комментариев и комментирование
|
||||||
- [ ] Просмотр всех комментариев (как Modal)
|
- [X] Просмотр всех комментариев (как Modal)
|
||||||
- [ ] Отправление комментариев
|
- [ ] Отправление комментариев
|
||||||
- [ ] Отправление ответов
|
- [ ] Отправление ответов
|
||||||
- [ ] Метка комментариев как спойлер
|
- [ ] Метка комментариев как спойлер
|
||||||
|
@ -51,6 +51,7 @@
|
||||||
|
|
||||||
- в статусе профиля нет переноса на новые линии
|
- в статусе профиля нет переноса на новые линии
|
||||||
- лишний отступ на последнем ответе на комментарий
|
- лишний отступ на последнем ответе на комментарий
|
||||||
|
- оценка комментариев не работает ?
|
||||||
|
|
||||||
## Другое
|
## Другое
|
||||||
|
|
||||||
|
|
|
@ -118,9 +118,9 @@ export const CommentsComment = (props: {
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
stroke-linecap="round"
|
strokeLinecap="round"
|
||||||
stroke-linejoin="round"
|
strokeLinejoin="round"
|
||||||
stroke-width="2"
|
strokeWidth="2"
|
||||||
d="M5 5h5M5 8h2m6-3h2m-5 3h6m2-7H2a1 1 0 0 0-1 1v9a1 1 0 0 0 1 1h3v5l5-5h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1Z"
|
d="M5 5h5M5 8h2m6-3h2m-5 3h6m2-7H2a1 1 0 0 0-1 1v9a1 1 0 0 0 1 1h3v5l5-5h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1Z"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
|
@ -1,48 +1,176 @@
|
||||||
import { Card, Button } from "flowbite-react";
|
import { Card, Button, Modal, Spinner } from "flowbite-react";
|
||||||
import { CommentsComment } from "./Comments.Comment";
|
import { CommentsComment } from "./Comments.Comment";
|
||||||
|
import { useState, useEffect, useCallback } from "react";
|
||||||
|
import { ENDPOINTS } from "#/api/config";
|
||||||
|
import useSWRInfinite from "swr/infinite";
|
||||||
|
|
||||||
export const CommentsMain = (props: {
|
export const CommentsMain = (props: {
|
||||||
release_id: number;
|
release_id: number;
|
||||||
token: string | null;
|
token: string | null;
|
||||||
comments: any;
|
comments: any;
|
||||||
}) => {
|
}) => {
|
||||||
|
const [isAllCommentsOpen, setIsAllCommentsOpen] = useState(false);
|
||||||
return (
|
return (
|
||||||
<Card className="antialiased">
|
<>
|
||||||
<div className="w-full">
|
<Card className="antialiased">
|
||||||
<div className="flex items-center justify-between mb-6">
|
<div className="w-full">
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col justify-start gap-2 mb-6 sm:flex-row sm:items-center sm:justify-between">
|
||||||
<h2 className="text-lg font-bold text-gray-900 lg:text-2xl dark:text-white">
|
<div className="flex flex-col gap-1">
|
||||||
Комментарии
|
<h2 className="text-lg font-bold text-gray-900 lg:text-2xl dark:text-white">
|
||||||
</h2>
|
Комментарии
|
||||||
<p className="text-sm font-bold text-gray-600 dark:text-gray-300">
|
</h2>
|
||||||
Популярные и актуальные
|
<p className="text-sm font-bold text-gray-600 dark:text-gray-300">
|
||||||
</p>
|
Популярные и актуальные
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
onClick={() => setIsAllCommentsOpen(true)}
|
||||||
|
color="light"
|
||||||
|
pill={true}
|
||||||
|
size={"sm"}
|
||||||
|
>
|
||||||
|
Показать все
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<form className="mb-6">
|
||||||
|
<div className="px-4 py-2 mb-4 bg-white border border-gray-200 rounded-lg rounded-t-lg dark:bg-gray-800 dark:border-gray-700">
|
||||||
|
<label htmlFor="comment" className="sr-only">
|
||||||
|
Ваш комментарий
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
id="comment"
|
||||||
|
rows={4}
|
||||||
|
className="w-full px-0 text-sm text-gray-900 border-0 focus:ring-0 focus:outline-none dark:text-white dark:placeholder-gray-400 dark:bg-gray-800"
|
||||||
|
placeholder="Написать комментарий..."
|
||||||
|
required
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
<Button type="submit" color="blue">
|
||||||
|
Оставить комментарий
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
{props.comments.map((comment: any) => (
|
||||||
|
<CommentsComment
|
||||||
|
key={comment.id}
|
||||||
|
profile={comment.profile}
|
||||||
|
comment={{
|
||||||
|
id: comment.id,
|
||||||
|
timestamp: comment.timestamp,
|
||||||
|
message: comment.message,
|
||||||
|
reply_count: comment.reply_count,
|
||||||
|
likes_count: comment.likes_count,
|
||||||
|
vote: comment.vote,
|
||||||
|
}}
|
||||||
|
token={props.token}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
<Button
|
|
||||||
className="px-2 py-1 text-xs text-gray-500 border border-gray-600 rounded-full hover:bg-black hover:text-white hover:border-black dark:text-gray-400 dark:border-gray-500"
|
|
||||||
color="inline"
|
|
||||||
>
|
|
||||||
Показать все
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<form className="mb-6">
|
</Card>
|
||||||
<div className="px-4 py-2 mb-4 bg-white border border-gray-200 rounded-lg rounded-t-lg dark:bg-gray-800 dark:border-gray-700">
|
<CommentsAllModal
|
||||||
<label htmlFor="comment" className="sr-only">
|
isOpen={isAllCommentsOpen}
|
||||||
Ваш комментарий
|
setIsOpen={setIsAllCommentsOpen}
|
||||||
</label>
|
release_id={props.release_id}
|
||||||
<textarea
|
token={props.token}
|
||||||
id="comment"
|
/>
|
||||||
rows={4}
|
</>
|
||||||
className="w-full px-0 text-sm text-gray-900 border-0 focus:ring-0 focus:outline-none dark:text-white dark:placeholder-gray-400 dark:bg-gray-800"
|
);
|
||||||
placeholder="Написать комментарий..."
|
};
|
||||||
required
|
|
||||||
></textarea>
|
const fetcher = async (url: string) => {
|
||||||
</div>
|
const res = await fetch(url);
|
||||||
<Button type="submit" color="blue">
|
|
||||||
Оставить комментарий
|
if (!res.ok) {
|
||||||
</Button>
|
const error = new Error(
|
||||||
</form>
|
`An error occurred while fetching the data. status: ${res.status}`
|
||||||
<div className="flex flex-col gap-2">
|
);
|
||||||
{props.comments.map((comment: any) => (
|
error.message = await res.json();
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
const CommentsAllModal = (props: {
|
||||||
|
isOpen: boolean;
|
||||||
|
setIsOpen: any;
|
||||||
|
release_id: number;
|
||||||
|
token: string | null;
|
||||||
|
}) => {
|
||||||
|
const [isLoadingEnd, setIsLoadingEnd] = useState(false);
|
||||||
|
const [currentRef, setCurrentRef] = useState<any>(null);
|
||||||
|
const modalRef = useCallback((ref) => {
|
||||||
|
setCurrentRef(ref);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getKey = (pageIndex: number, previousPageData: any) => {
|
||||||
|
if (previousPageData && !previousPageData.content.length) return null;
|
||||||
|
let url = `${ENDPOINTS.release.info}/comment/all/${props.release_id}/${pageIndex}?sort=1`;
|
||||||
|
if (props.token) {
|
||||||
|
url += `&token=${props.token}`;
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data, error, isLoading, size, setSize } = useSWRInfinite(
|
||||||
|
getKey,
|
||||||
|
fetcher,
|
||||||
|
{ initialSize: 2 }
|
||||||
|
);
|
||||||
|
|
||||||
|
const [content, setContent] = useState(null);
|
||||||
|
useEffect(() => {
|
||||||
|
if (data) {
|
||||||
|
let allReleases = [];
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
allReleases.push(...data[i].content);
|
||||||
|
}
|
||||||
|
setContent(allReleases);
|
||||||
|
setIsLoadingEnd(true);
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
const [scrollPosition, setScrollPosition] = useState(0);
|
||||||
|
function handleScroll() {
|
||||||
|
const height = currentRef.scrollHeight - currentRef.clientHeight;
|
||||||
|
const windowScroll = currentRef.scrollTop;
|
||||||
|
const scrolled = (windowScroll / height) * 100;
|
||||||
|
setScrollPosition(Math.floor(scrolled));
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log(scrollPosition);
|
||||||
|
if (scrollPosition >= 95 && scrollPosition <= 96) {
|
||||||
|
setSize(size + 1);
|
||||||
|
}
|
||||||
|
}, [scrollPosition]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
dismissible
|
||||||
|
show={props.isOpen}
|
||||||
|
onClose={() => props.setIsOpen(false)}
|
||||||
|
>
|
||||||
|
<Modal.Header>
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<h2 className="text-lg font-bold text-gray-900 lg:text-2xl dark:text-white">
|
||||||
|
Все комментарии
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm font-bold text-gray-600 dark:text-gray-300">
|
||||||
|
всего: {!isLoadingEnd ? "загрузка..." : data[0].total_count}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Modal.Header>
|
||||||
|
<div
|
||||||
|
className="flex flex-col gap-2 p-4 overflow-y-auto"
|
||||||
|
onScroll={handleScroll}
|
||||||
|
ref={modalRef}
|
||||||
|
>
|
||||||
|
{!isLoadingEnd ? (
|
||||||
|
<Spinner />
|
||||||
|
) : content ? (
|
||||||
|
content.map((comment: any) => (
|
||||||
<CommentsComment
|
<CommentsComment
|
||||||
key={comment.id}
|
key={comment.id}
|
||||||
profile={comment.profile}
|
profile={comment.profile}
|
||||||
|
@ -56,9 +184,14 @@ export const CommentsMain = (props: {
|
||||||
}}
|
}}
|
||||||
token={props.token}
|
token={props.token}
|
||||||
/>
|
/>
|
||||||
))}
|
))
|
||||||
</div>
|
) : (
|
||||||
|
<p className="text-sm font-bold text-gray-600 dark:text-gray-300">
|
||||||
|
Комментариев нет
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
{/* <Modal.Footer>TEXT</Modal.Footer> */}
|
||||||
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue