AniX/app/components/Comments/Comments.Main.tsx

198 lines
6.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Button, Card, Modal, ModalHeader, Spinner } from "flowbite-react";
import { CommentsComment } from "./Comments.Comment";
import { useState, useEffect, useCallback } from "react";
import { ENDPOINTS } from "#/api/config";
import useSWRInfinite from "swr/infinite";
import { CommentsAddModal } from "./Comments.Add";
import { useSWRfetcher } from "#/api/utils";
export const CommentsMain = (props: {
release_id: number;
token: string | null;
comments: any;
type?: "release" | "collection";
}) => {
const [isAllCommentsOpen, setIsAllCommentsOpen] = useState(false);
const [isAddCommentsOpen, setIsAddCommentsOpen] = useState(false);
const type = props.type || "release";
return (
<>
<Card className="antialiased">
<div className="w-full">
<div className="flex flex-col justify-start gap-2 mb-6 sm:flex-row sm:items-center sm:justify-between">
<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">
Популярные и актуальные
</p>
</div>
<div className="flex items-end gap-2">
{props.token && (
<Button onClick={() => setIsAddCommentsOpen(true)} color="blue">
Оставить комментарий
</Button>
)}
<Button onClick={() => setIsAllCommentsOpen(true)} color="light">
Показать все
</Button>
</div>
</div>
<div className="flex flex-col gap-2">
{props.comments.map((comment: any) => (
<CommentsComment
key={comment.id}
release_id={props.release_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,
isSpoiler: comment.is_spoiler,
isEdited: comment.is_edited,
isDeleted: comment.is_deleted,
}}
token={props.token}
isSubComment={type != "release"}
type={type}
/>
))}
</div>
</div>
</Card>
<CommentsAllModal
isOpen={isAllCommentsOpen}
setIsOpen={setIsAllCommentsOpen}
release_id={props.release_id}
token={props.token}
type={props.type}
/>
<CommentsAddModal
isOpen={isAddCommentsOpen}
setIsOpen={setIsAddCommentsOpen}
release_id={props.release_id}
token={props.token}
type={props.type}
/>
</>
);
};
const CommentsAllModal = (props: {
isOpen: boolean;
setIsOpen: any;
release_id: number;
token: string | null;
type?: "release" | "collection";
}) => {
const [currentRef, setCurrentRef] = useState<any>(null);
const modalRef = useCallback((ref) => {
setCurrentRef(ref);
}, []);
const type = props.type || "release";
const getKey = (pageIndex: number, previousPageData: any) => {
if (previousPageData && !previousPageData.content.length) return null;
let url;
if (type == "release") {
url = `${ENDPOINTS.release.info}/comment/all/${props.release_id}/${pageIndex}?sort=1`;
} else if (type == "collection") {
url = `${ENDPOINTS.collection.base}/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,
useSWRfetcher,
{ 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);
}
}, [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(() => {
if (scrollPosition >= 95 && scrollPosition <= 96) {
setSize(size + 1);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [scrollPosition]);
return (
<Modal
dismissible
show={props.isOpen}
onClose={() => props.setIsOpen(false)}
>
<ModalHeader>
<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-light text-gray-600 dark:text-gray-300">
всего: {isLoading ? "загрузка..." : data[0].total_count}
</p>
</div>
</ModalHeader>
<div
className="flex flex-col gap-2 p-4 overflow-y-auto"
onScroll={handleScroll}
ref={modalRef}
>
{isLoading ? (
<Spinner />
) : content ? (
content.map((comment: any) => (
<CommentsComment
release_id={props.release_id}
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,
isSpoiler: comment.is_spoiler,
isEdited: comment.is_edited,
isDeleted: comment.is_deleted,
}}
token={props.token}
type={type}
/>
))
) : (
<p className="text-sm font-bold text-gray-600 dark:text-gray-300">
Комментариев нет
</p>
)}
</div>
</Modal>
);
};