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();
|
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">
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -46,6 +46,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__loader {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
form {
|
form {
|
||||||
margin-bottom: 70px;
|
margin-bottom: 70px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user