made filters in rating section

This commit is contained in:
Alibek 2024-02-16 14:11:15 +06:00
parent a12aaa1213
commit d4c49a1061
9 changed files with 139 additions and 86 deletions

View File

@ -12,14 +12,22 @@
background-color: rgb(255, 255, 255); background-color: rgb(255, 255, 255);
} }
&__prev { &__prev,
&__prev-disabled {
border-radius: 8px 0px 0px 8px; border-radius: 8px 0px 0px 8px;
} }
&__next { &__next,
&__next-disabled {
border-radius: 0px 8px 8px 0px; border-radius: 0px 8px 8px 0px;
} }
&__next-disabled,
&__prev-disabled {
cursor: auto;
opacity: 0.7;
}
&__page, &__page,
&__page_active { &__page_active {
font-size: 14px; font-size: 14px;

View File

@ -121,7 +121,9 @@ const Pagination: React.FC<IPaginationProps> = ({
<button <button
onClick={prevPage} onClick={prevPage}
disabled={prev === null} disabled={prev === null}
className="pagination__prev" className={`pagination__prev${
prev === null ? "-disabled" : ""
}`}
> >
<Image src={arrow_left} alt="" /> <Image src={arrow_left} alt="" />
</button> </button>
@ -129,7 +131,9 @@ const Pagination: React.FC<IPaginationProps> = ({
<button <button
onClick={nextPage} onClick={nextPage}
disabled={next === null} disabled={next === null}
className="pagination__next" className={`pagination__next${
next === null ? "-disabled" : ""
}`}
> >
<Image src={arrow_right} alt="" /> <Image src={arrow_right} alt="" />
</button> </button>

View File

Before

Width:  |  Height:  |  Size: 417 B

After

Width:  |  Height:  |  Size: 417 B

View File

Before

Width:  |  Height:  |  Size: 416 B

After

Width:  |  Height:  |  Size: 416 B

View File

@ -4,8 +4,6 @@ import Image from "next/image";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import SearchForm from "@/features/SearchForm/SearchForm"; import SearchForm from "@/features/SearchForm/SearchForm";
import arrow_down_icon from "./icons/arrow-down.svg";
import arrow_up_icon from "./icons/arrow-up.svg";
import like_icon from "./icons/like.svg"; import like_icon from "./icons/like.svg";
import message_icon from "./icons/message.svg"; import message_icon from "./icons/message.svg";
import { useRatingStore } from "./ratingSectionStore"; import { useRatingStore } from "./ratingSectionStore";
@ -19,7 +17,12 @@ import RoadType from "@/entities/RoadType/RoadType";
import Typography from "@/shared/ui/components/Typography/Typography"; import Typography from "@/shared/ui/components/Typography/Typography";
import Paragraph from "@/shared/ui/components/Paragraph/Paragraph"; import Paragraph from "@/shared/ui/components/Paragraph/Paragraph";
import arrows from "../../shared/icons/arrows.svg"; import arrows from "../../shared/icons/arrows.svg";
import Pagination from "@/entities/Pagination/Pagination"; import Pagination from "@/features/Pagination/Pagination";
import {
sliceDate,
sliceDescription,
sliceLocation,
} from "./helpers";
interface IRatingSectionProps { interface IRatingSectionProps {
[key: string]: string; [key: string]: string;
@ -35,6 +38,10 @@ const RatingSection: React.FC<IRatingSectionProps> = ({
queryRating || "" queryRating || ""
); );
const [activePage, setActivePage] = useState<number>(+page); const [activePage, setActivePage] = useState<number>(+page);
const [filter, setFilter] = useState({
option: "date",
toggle: false,
});
const router = useRouter(); const router = useRouter();
const reports = useRatingStore(useShallow((state) => state.data)); const reports = useRatingStore(useShallow((state) => state.data));
@ -43,7 +50,7 @@ const RatingSection: React.FC<IRatingSectionProps> = ({
); );
useEffect(() => { useEffect(() => {
getReports(ratingSearch, +page); getReports(ratingSearch, +page, filter);
}, []); }, []);
const handleSubmit: React.FormEventHandler< const handleSubmit: React.FormEventHandler<
@ -64,7 +71,7 @@ const RatingSection: React.FC<IRatingSectionProps> = ({
} }
); );
getReports(ratingSearch, activePage); getReports(ratingSearch, activePage, filter);
if (reports.results.length < 8 && page !== "1") { if (reports.results.length < 8 && page !== "1") {
setActivePage(1); setActivePage(1);
@ -83,36 +90,22 @@ const RatingSection: React.FC<IRatingSectionProps> = ({
} }
); );
getReports(ratingSearch, activePage); getReports(ratingSearch, activePage, filter);
}, [activePage]); }, [activePage]);
const sliceDate = (date: string) => {
return `${date.slice(8, 10)}.${date.slice(5, 7)}.${date.slice(
0,
4
)}`;
};
const sliceLocation = (location: string) => {
if (location.length > 15) return `${location.slice(0, 15)}...`;
return location;
};
const sliceDescription = (description: string) => {
if (description.length > 49) {
return `${description.slice(0, 50)}...`;
}
return description;
};
const params = [ const params = [
{ {
id: 1, id: 1,
name: "Дата", name: "Дата",
handleClick() { handleClick() {
console.log(this.name); if (filter.option !== "date") {
return setFilter({ option: "date", toggle: false });
}
setFilter((prev) => {
return { option: "date", toggle: !prev.toggle };
});
getReports(ratingSearch, activePage, filter);
}, },
}, },
{ id: 2, name: "Адрес" }, { id: 2, name: "Адрес" },
@ -122,14 +115,28 @@ const RatingSection: React.FC<IRatingSectionProps> = ({
id: 5, id: 5,
name: "Комментарии", name: "Комментарии",
handleClick() { handleClick() {
console.log(this.name); if (filter.option !== "reviews") {
return setFilter({ option: "reviews", toggle: false });
}
setFilter((prev) => {
return { option: "reviews", toggle: !prev.toggle };
});
getReports(ratingSearch, activePage, filter);
}, },
}, },
{ {
id: 6, id: 6,
name: "Рейтинг", name: "Рейтинг",
handleClick() { handleClick() {
console.log(this.name); if (filter.option !== "rating") {
return setFilter({ option: "rating", toggle: false });
}
setFilter((prev) => {
return { option: "rating", toggle: !prev.toggle };
});
getReports(ratingSearch, activePage, filter);
}, },
}, },
]; ];

View File

@ -0,0 +1,20 @@
export const sliceDate = (date: string) => {
return `${date.slice(8, 10)}.${date.slice(5, 7)}.${date.slice(
0,
4
)}`;
};
export const sliceLocation = (location: string) => {
if (location.length > 15) return `${location.slice(0, 15)}...`;
return location;
};
export const sliceDescription = (description: string) => {
if (description.length > 49) {
return `${description.slice(0, 50)}...`;
}
return description;
};

View File

@ -2,7 +2,6 @@ import { apiInstance } from "@/shared/config/apiConfig";
import { IFetch } from "@/shared/types/fetch-type"; import { IFetch } from "@/shared/types/fetch-type";
import { IList } from "@/shared/types/list-type"; import { IList } from "@/shared/types/list-type";
import { IReport } from "@/shared/types/report-type"; import { IReport } from "@/shared/types/report-type";
import axios from "axios";
import { create } from "zustand"; import { create } from "zustand";
interface IFetchReports extends IList { interface IFetchReports extends IList {
@ -11,7 +10,11 @@ interface IFetchReports extends IList {
interface IRatingStore extends IFetch { interface IRatingStore extends IFetch {
data: IFetchReports; data: IFetchReports;
getReports: (categories: string, page: number) => Promise<void>; getReports: (
categories: string,
page: number,
filter: { option: string; toggle: boolean }
) => Promise<void>;
} }
export const useRatingStore = create<IRatingStore>((set) => ({ export const useRatingStore = create<IRatingStore>((set) => ({
@ -23,7 +26,11 @@ export const useRatingStore = create<IRatingStore>((set) => ({
}, },
isLoading: false, isLoading: false,
error: "", error: "",
getReports: async (query: string = "", page: number = 1) => { getReports: async (
query: string = "",
page: number = 1,
filter: { option: string; toggle: boolean }
) => {
try { try {
set({ isLoading: true }); set({ isLoading: true });
@ -41,6 +48,46 @@ export const useRatingStore = create<IRatingStore>((set) => ({
data.results = [...searched]; data.results = [...searched];
if (filter.option === "date" && filter.toggle === false) {
data.results = data.results.sort((a, b) => {
const dateA = new Date(a.created_at) as unknown as number;
const dateB = new Date(b.created_at) as unknown as number;
return dateA - dateB;
});
} else if (filter.option === "date" && filter.toggle === true) {
data.results = data.results.sort((a, b) => {
const dateA = new Date(a.created_at) as unknown as number;
const dateB = new Date(b.created_at) as unknown as number;
return dateB - dateA;
});
}
if (filter.option === "reviews" && filter.toggle === false) {
data.results = data.results.sort(
(a, b) => a.count_reviews - b.count_reviews
);
} else if (
filter.option === "reviews" &&
filter.toggle === true
) {
data.results = data.results.sort(
(a, b) => b.count_reviews - a.count_reviews
);
}
if (filter.option === "rating" && filter.toggle === false) {
data.results = data.results.sort(
(a, b) => a.total_likes - b.total_likes
);
} else if (
filter.option === "rating" &&
filter.toggle === true
) {
data.results = data.results.sort(
(a, b) => b.total_likes - a.total_likes
);
}
set({ data: data }); set({ data: data });
} catch (error: any) { } catch (error: any) {
set({ error: error.message }); set({ error: error.message });

View File

@ -1,28 +1,30 @@
import { ROAD_TYPES_STATS } from "@/shared/variables/road-types"; import { ROAD_TYPES_STATS } from "@/shared/variables/road-types";
import "./StatisticsSection.scss"; import "./StatisticsSection.scss";
import { statiscsSectionStore } from "./statisticsSection.store"; import { apiInstance } from "@/shared/config/apiConfig";
interface ICategoryStatistics {
category: number;
total: number;
}
const StatisticsSection = async () => { const StatisticsSection = async () => {
// const { getStatsCount, getErrorMessage } = statiscsSectionStore(); const getCategoryStatistics = async () => {
// const statistics = await getStatsCount(); const res = await apiInstance.get<ICategoryStatistics[]>(
// const error = getErrorMessage(); "/report/category_count/"
);
const mockArray = [ return res.data;
{ category: 1, count: 132 }, };
{ category: 2, count: 12 },
{ category: 3, count: 1432 }, const statistics = await getCategoryStatistics();
{ category: 4, count: 18 },
{ category: 5, count: 95 },
{ category: 6, count: 54 },
];
return ( return (
<section className="statistics-section"> <section className="statistics-section">
<ul className="statistics-section__list"> <ul className="statistics-section__list">
{mockArray.map((cat) => ( {statistics.map((cat) => (
<li key={cat.category}> <li key={cat.category}>
<p>{ROAD_TYPES_STATS[cat.category]}</p> <p>{ROAD_TYPES_STATS[cat.category]}</p>
<span>{cat.count}</span> <span>{cat.total}</span>
</li> </li>
))} ))}
</ul> </ul>

View File

@ -1,35 +0,0 @@
import { apiInstance } from "@/shared/config/apiConfig";
import { AxiosError } from "axios";
interface IStatsCount {
category: number;
count: number;
}
export const statiscsSectionStore = () => {
let errorMessage = "";
async function getStatsCount() {
try {
const response = await apiInstance.get<IStatsCount[]>(
"/report/category_count/"
);
return response.data;
} catch (error: unknown) {
if (error instanceof AxiosError) {
errorMessage = error.message;
} else {
errorMessage = "An error ocured";
}
}
}
function getErrorMessage() {
return errorMessage;
}
return {
getStatsCount,
getErrorMessage,
};
};