added dynamic pagination in reviews-section

This commit is contained in:
Alibek 2024-03-01 14:14:32 +06:00
parent 0a7513dd89
commit 65a700dad7
5 changed files with 88 additions and 9 deletions

View File

@ -33,7 +33,7 @@ const ReportDetails = async ({
return res.json(); return res.json();
}; };
const report: IReport = await getReportDetails(); const report: IReport = (await getReportDetails()) || {};
return ( return (
<div className="report-details page-padding"> <div className="report-details page-padding">

View File

@ -1,5 +1,5 @@
export interface IList { export interface IList {
count: number | null; count: number;
previous: string | null; previous: string | null;
next: string | null; next: string | null;
} }

View File

@ -1,7 +1,16 @@
import "./Loader.scss"; import "./Loader.scss";
const Loader = () => { interface ILoader {
return <span className="loader"></span>; color?: string;
}
const Loader: React.FC<ILoader> = ({ color }: ILoader) => {
return (
<span
className="loader"
style={{ borderTop: `3px solid ${color}` }}
></span>
);
}; };
export default Loader; export default Loader;

View File

@ -46,6 +46,11 @@
} }
} }
&__loader {
display: flex;
justify-content: center;
}
form { form {
margin-bottom: 70px; margin-bottom: 70px;
display: flex; display: flex;

View File

@ -4,7 +4,7 @@ import "./ReviewSection.scss";
import { apiInstance } from "@/shared/config/apiConfig"; import { apiInstance } from "@/shared/config/apiConfig";
import { IReviewList } from "@/shared/types/review-type"; import { IReviewList } from "@/shared/types/review-type";
import { signIn, useSession } from "next-auth/react"; 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 calendar from "./icons/calendar.svg";
import Image from "next/image"; import Image from "next/image";
import { import {
@ -12,6 +12,7 @@ import {
usePathname, usePathname,
useRouter, useRouter,
} from "@/shared/config/navigation"; } from "@/shared/config/navigation";
import Loader from "@/shared/ui/components/Loader/Loader";
interface IReviewsSectionProps { interface IReviewsSectionProps {
endpoint: string; endpoint: string;
@ -22,7 +23,30 @@ const ReviewSection: React.FC<IReviewsSectionProps> = ({
endpoint, endpoint,
id, id,
}: IReviewsSectionProps) => { }: 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 pathname = usePathname();
const session = useSession(); const session = useSession();
const handleSubmit: React.MouseEventHandler< const handleSubmit: React.MouseEventHandler<
@ -55,6 +79,7 @@ const ReviewSection: React.FC<IReviewsSectionProps> = ({
formData, formData,
config config
); );
getReviews(); getReviews();
} catch (error) { } catch (error) {
console.log(error); console.log(error);
@ -62,15 +87,45 @@ const ReviewSection: React.FC<IReviewsSectionProps> = ({
}; };
const getReviews = async () => { const getReviews = async () => {
setLoader(true);
const response = await apiInstance.get<IReviewList>( 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); 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(() => { useEffect(() => {
getReviews(); getReviews();
}, []); }, [pageSize]);
const months: Record<string, string> = { const months: Record<string, string> = {
"01": "Январь", "01": "Январь",
@ -86,6 +141,7 @@ const ReviewSection: React.FC<IReviewsSectionProps> = ({
"11": "Ноябрь", "11": "Ноябрь",
"12": "Декабрь", "12": "Декабрь",
}; };
return ( return (
<section className="review-section"> <section className="review-section">
<h3> <h3>
@ -116,7 +172,7 @@ const ReviewSection: React.FC<IReviewsSectionProps> = ({
</h3> </h3>
{reviews?.results.length !== 0 ? ( {reviews?.results.length !== 0 ? (
<ul> <ul key="unuqie key">
{reviews?.results.map((review) => ( {reviews?.results.map((review) => (
<li key={review.id} className="review"> <li key={review.id} className="review">
<div className="review__author"> <div className="review__author">
@ -152,6 +208,15 @@ const ReviewSection: React.FC<IReviewsSectionProps> = ({
Оставьте комментарий первым :) Оставьте комментарий первым :)
</p> </p>
)} )}
{loader ? (
<div className="review-section__loader">
<Loader color="#000" />
</div>
) : null}
<div
ref={lastElement}
className="review-section__list_bottom"
></div>
</div> </div>
</section> </section>
); );