kgroad-frontend2/src/widgets/ReviewSection/ReviewSection.tsx
2024-03-01 19:54:03 +06:00

225 lines
6.1 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.

"use client";
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, useRef, useState } from "react";
import calendar from "./icons/calendar.svg";
import Image from "next/image";
import {
Link,
usePathname,
useRouter,
} from "@/shared/config/navigation";
import Loader from "@/shared/ui/components/Loader/Loader";
interface IReviewsSectionProps {
endpoint: string;
id: number;
}
const ReviewSection: React.FC<IReviewsSectionProps> = ({
endpoint,
id,
}: IReviewsSectionProps) => {
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<
HTMLFormElement
> = async (e) => {
e.preventDefault();
const Authorization = `Bearer ${session.data?.access_token}`;
const formData = new FormData(e.currentTarget);
const config = {
headers: {
Authorization,
},
};
if (session.status === "unauthenticated") {
signIn(undefined, { callbackUrl: pathname });
}
if (!formData.get("review")) {
return;
}
formData.append("news", id.toString());
try {
const res = await apiInstance.post(
`/${endpoint}/${id}/reviews/`,
formData,
config
);
getReviews();
} catch (error) {
console.log(error);
}
};
const getReviews = async () => {
setLoader(true);
const response = await apiInstance.get<IReviewList>(
`/${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) {
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": "Январь",
"02": "Февраль",
"03": "Март",
"04": "Апрель",
"05": "Май",
"06": "Июнь",
"07": "Июль",
"08": "Август",
"09": "Сентябрь",
"10": "Октябрь",
"11": "Ноябрь",
"12": "Декабрь",
};
return (
<section className="review-section">
<h3>
<span id="blue-point" /> Написать комментарий
</h3>
{session.status === "authenticated" ? (
<form onSubmit={handleSubmit}>
<textarea name="review" />
<button type="submit">Отправить</button>
</form>
) : (
<p className="review-section__auth-warning">
Перед тем как оставить комментарий, пожалуйста
<button
onClick={() =>
signIn(undefined, { callbackUrl: pathname })
}
>
войдите в аккаунт
</button>
</p>
)}
<div className="review-section__list">
<h3>
<span id="blue-point" /> Комментарии
</h3>
{reviews?.results.length !== 0 ? (
<ul key="unuqie key">
{reviews?.results.map((review) => (
<li key={review.id} className="review">
<div className="review__author">
<img
id="author-img"
src={review.author.image}
alt="Author Image"
/>
<div className="review__header">
<h5 className="review__author-name">
{review.author.first_name}{" "}
{review.author.last_name}
</h5>
<div className="review__date">
<Image src={calendar} alt="Calendar Icon" />
<p>
{months[review.created_at.slice(5, 7)]}{" "}
{review.created_at.slice(5, 7).slice(0, 1) ===
"0"
? review.created_at.slice(6, 7)
: review.created_at.slice(5, 7)}
, {review.created_at.slice(0, 4)}
</p>
</div>
</div>
</div>
<p className="review__description">{review.review}</p>
</li>
))}
</ul>
) : (
<p className="review-section__warning">
Оставьте комментарий первым :)
</p>
)}
{loader ? (
<div className="review-section__loader">
<Loader color="#000" />
</div>
) : null}
<div
ref={lastElement}
className="review-section__list_bottom"
></div>
</div>
</section>
);
};
export default ReviewSection;