forked from Transparency/kgroad-frontend2
added dynamic pagination in reviews-section
This commit is contained in:
parent
0a7513dd89
commit
65a700dad7
@ -33,7 +33,7 @@ const ReportDetails = async ({
|
||||
|
||||
return res.json();
|
||||
};
|
||||
const report: IReport = await getReportDetails();
|
||||
const report: IReport = (await getReportDetails()) || {};
|
||||
|
||||
return (
|
||||
<div className="report-details page-padding">
|
||||
|
@ -1,5 +1,5 @@
|
||||
export interface IList {
|
||||
count: number | null;
|
||||
count: number;
|
||||
previous: string | null;
|
||||
next: string | null;
|
||||
}
|
||||
|
@ -1,7 +1,16 @@
|
||||
import "./Loader.scss";
|
||||
|
||||
const Loader = () => {
|
||||
return <span className="loader"></span>;
|
||||
interface ILoader {
|
||||
color?: string;
|
||||
}
|
||||
|
||||
const Loader: React.FC<ILoader> = ({ color }: ILoader) => {
|
||||
return (
|
||||
<span
|
||||
className="loader"
|
||||
style={{ borderTop: `3px solid ${color}` }}
|
||||
></span>
|
||||
);
|
||||
};
|
||||
|
||||
export default Loader;
|
||||
|
@ -46,6 +46,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
&__loader {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
form {
|
||||
margin-bottom: 70px;
|
||||
display: flex;
|
||||
|
@ -4,7 +4,7 @@ import "./ReviewSection.scss";
|
||||
import { apiInstance } from "@/shared/config/apiConfig";
|
||||
import { IReviewList } from "@/shared/types/review-type";
|
||||
import { signIn, useSession } from "next-auth/react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import calendar from "./icons/calendar.svg";
|
||||
import Image from "next/image";
|
||||
import {
|
||||
@ -12,6 +12,7 @@ import {
|
||||
usePathname,
|
||||
useRouter,
|
||||
} from "@/shared/config/navigation";
|
||||
import Loader from "@/shared/ui/components/Loader/Loader";
|
||||
|
||||
interface IReviewsSectionProps {
|
||||
endpoint: string;
|
||||
@ -22,7 +23,30 @@ const ReviewSection: React.FC<IReviewsSectionProps> = ({
|
||||
endpoint,
|
||||
id,
|
||||
}: IReviewsSectionProps) => {
|
||||
const [reviews, setReviews] = useState<IReviewList>();
|
||||
const lastElement = useRef<HTMLDivElement | null>(null);
|
||||
const observer = useRef<IntersectionObserver | null>(null);
|
||||
const [reviews, setReviews] = useState<IReviewList>({
|
||||
count: 0,
|
||||
next: null,
|
||||
previous: null,
|
||||
results: [
|
||||
{
|
||||
id: 0,
|
||||
author: {
|
||||
image: "",
|
||||
id: 0,
|
||||
first_name: "",
|
||||
last_name: "",
|
||||
govern_status: null,
|
||||
},
|
||||
review: "",
|
||||
created_at: "",
|
||||
},
|
||||
],
|
||||
});
|
||||
const [pageSize, setPageSize] = useState<number>(8);
|
||||
const [reviewCount, setReviewCount] = useState<number>(0);
|
||||
const [loader, setLoader] = useState<boolean>(false);
|
||||
const pathname = usePathname();
|
||||
const session = useSession();
|
||||
const handleSubmit: React.MouseEventHandler<
|
||||
@ -55,6 +79,7 @@ const ReviewSection: React.FC<IReviewsSectionProps> = ({
|
||||
formData,
|
||||
config
|
||||
);
|
||||
|
||||
getReviews();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
@ -62,15 +87,45 @@ const ReviewSection: React.FC<IReviewsSectionProps> = ({
|
||||
};
|
||||
|
||||
const getReviews = async () => {
|
||||
setLoader(true);
|
||||
const response = await apiInstance.get<IReviewList>(
|
||||
`/${endpoint}/${id}/reviews/?page_size=8`
|
||||
`/${endpoint}/${id}/reviews/?page_size=${pageSize}`
|
||||
);
|
||||
|
||||
setReviewCount(response.data.count);
|
||||
setLoader(false);
|
||||
setReviews({
|
||||
count: response.data.count,
|
||||
next: response.data.next,
|
||||
previous: response.data.previous,
|
||||
results: [...reviews?.results, ...response.data.results],
|
||||
});
|
||||
setReviews(response?.data);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (loader) return;
|
||||
if (observer.current) observer.current.disconnect();
|
||||
const callback = function (entries: any) {
|
||||
console.log(reviewCount, pageSize);
|
||||
if (
|
||||
entries[0].isIntersecting &&
|
||||
(reviews?.results.length as number) <= reviewCount
|
||||
) {
|
||||
if (pageSize < reviewCount) {
|
||||
setPageSize((prev) => prev + 8);
|
||||
} else {
|
||||
setPageSize(reviewCount);
|
||||
}
|
||||
}
|
||||
};
|
||||
observer.current = new IntersectionObserver(callback);
|
||||
observer.current.observe(lastElement.current as HTMLDivElement);
|
||||
}, [loader]);
|
||||
|
||||
useEffect(() => {
|
||||
getReviews();
|
||||
}, []);
|
||||
}, [pageSize]);
|
||||
|
||||
const months: Record<string, string> = {
|
||||
"01": "Январь",
|
||||
@ -86,6 +141,7 @@ const ReviewSection: React.FC<IReviewsSectionProps> = ({
|
||||
"11": "Ноябрь",
|
||||
"12": "Декабрь",
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="review-section">
|
||||
<h3>
|
||||
@ -116,7 +172,7 @@ const ReviewSection: React.FC<IReviewsSectionProps> = ({
|
||||
</h3>
|
||||
|
||||
{reviews?.results.length !== 0 ? (
|
||||
<ul>
|
||||
<ul key="unuqie key">
|
||||
{reviews?.results.map((review) => (
|
||||
<li key={review.id} className="review">
|
||||
<div className="review__author">
|
||||
@ -152,6 +208,15 @@ const ReviewSection: React.FC<IReviewsSectionProps> = ({
|
||||
Оставьте комментарий первым :)
|
||||
</p>
|
||||
)}
|
||||
{loader ? (
|
||||
<div className="review-section__loader">
|
||||
<Loader color="#000" />
|
||||
</div>
|
||||
) : null}
|
||||
<div
|
||||
ref={lastElement}
|
||||
className="review-section__list_bottom"
|
||||
></div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user