diff --git a/src/Entities/InputWithLabel/InputWithLabel.tsx b/src/Entities/InputWithLabel/InputWithLabel.tsx index 536ec60..fbaf19b 100644 --- a/src/Entities/InputWithLabel/InputWithLabel.tsx +++ b/src/Entities/InputWithLabel/InputWithLabel.tsx @@ -29,6 +29,7 @@ const InputWithLabel: React.FC = ({ onChange(e); } }; + return (
diff --git a/src/Pages/SignInPage/SignInPage.tsx b/src/Pages/SignInPage/SignInPage.tsx index cb3f449..5e8ef14 100644 --- a/src/Pages/SignInPage/SignInPage.tsx +++ b/src/Pages/SignInPage/SignInPage.tsx @@ -1,4 +1,3 @@ -import Image from "next/image"; import "./SignInPage.scss"; import sign_in_icon from "./icons/sign-in-icon.svg"; import AuthHeader from "@/Entities/AuthHeader/AuthHeader"; diff --git a/src/Shared/types.ts b/src/Shared/types.ts index 575587b..91516ec 100644 --- a/src/Shared/types.ts +++ b/src/Shared/types.ts @@ -1,6 +1,6 @@ export interface IFetch { response?: string; - data?: any; + data?: unknown; loading: boolean; error?: string; } diff --git a/src/Widgets/home/RatingSection/RatingSection.scss b/src/Widgets/home/RatingSection/RatingSection.scss index 2bfc29c..8c27a06 100644 --- a/src/Widgets/home/RatingSection/RatingSection.scss +++ b/src/Widgets/home/RatingSection/RatingSection.scss @@ -1,9 +1,128 @@ +@import "../../../Shared/variables.scss"; + .rating-section { + padding: 0 90px; margin-top: 110px; display: flex; flex-direction: column; align-items: center; gap: 30px; + + &__table { + width: 100%; + padding: 15px; + background-color: #fff; + border: 1px solid $gray-300; + overflow: hidden; + overflow-x: auto; + + table { + width: 100%; + border-collapse: collapse; + border-radius: 6px; + thead { + tr { + border-bottom: 1px solid #ddd; + th { + padding: 15px 0; + text-align: left; + color: $gray-500; + font-size: 16px; + font-weight: 500; + gap: 4px; + } + + #report-header-date, + #report-header-comment, + #report-header-like { + cursor: pointer; + + div { + display: flex; + align-items: center; + gap: 4px; + } + } + } + } + + tbody { + tr { + border-bottom: 1px solid #ddd; + + td { + padding: 15px 0; + } + + #report-date { + min-width: 150px; + color: $gray-500; + font-weight: 500; + font-size: 16px; + } + + #report-location { + min-width: 200px; + overflow: hidden; + + a { + text-decoration: underline; + white-space: preserve nowrap; + color: $light-blue; + font-size: 16px; + font-weight: 500; + } + } + + #report-type { + min-width: 210px; + + span { + width: 120px; + padding: 4px 12px; + font-size: 14px; + border-radius: 20px; + background: rgba(230, 68, 82, 0.8); + color: #fff; + } + } + + #report-description { + min-width: 378px; + + p { + width: 318px; + color: #32303a; + font-size: 18px; + font-weight: 500; + line-height: 20px; + letter-spacing: 0.1px; + text-align: justify; + } + } + + #report-comment, + #report-like { + div { + display: flex; + align-items: center; + gap: 7px; + } + } + } + + tr:last-child { + border-bottom: none; + } + } + } + } +} + +@media screen and (max-width: 1024px) { + .rating-section { + padding: 0 30px; + } } @media screen and (max-width: 768px) { @@ -14,6 +133,8 @@ @media screen and (max-width: 550px) { .rating-section { + padding: 0 16px; + margin-top: 70px; } } diff --git a/src/Widgets/home/RatingSection/RatingSection.tsx b/src/Widgets/home/RatingSection/RatingSection.tsx index 7a095c9..ff8e1f4 100644 --- a/src/Widgets/home/RatingSection/RatingSection.tsx +++ b/src/Widgets/home/RatingSection/RatingSection.tsx @@ -1,14 +1,116 @@ +"use client"; + import SectionHeader from "@/Shared/UI/SectionHeader/SectionHeader"; import "./RatingSection.scss"; import SearchBar from "@/Features/SearchBar/SearchBar"; +import arrow_down_icon from "./icons/arrow-down-icon.svg"; +import arrow_up_icon from "./icons/arrow-up-icon.svg"; +import like_icon from "./icons/like-icon.svg"; +import message_icon from "./icons/message-icon.svg"; +import Image from "next/image"; +import { useRating } from "./rating.store"; +import { useEffect } from "react"; +import Link from "next/link"; const RatingSection = () => { + const { data: reports, getRatings } = useRating(); + + useEffect(() => { + getRatings(); + }, []); + + 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; + }; + return (
Рейтинг + +
+ + + + + + + + + + + + + {reports.results.map((report) => ( + + + + + + + + + ))} + +
+
+ Дата + Arrow Down + Arrow Up +
+
АдресСтатусОписание +
+ Комментарии + Arrow Down + Arrow Up +
+
+
+ Рейтинг + Arrow Down + Arrow Up +
+
+ {sliceDate(report.created_at)} + + + {sliceLocation(report.location[0].address)} + + + Разбитая дорога + +

{sliceDescription(report.description)}

+
+
+ Message Icon + {report.count_reviews} +
+
+
+ Like Icon + {report.total_likes} +
+
+
); }; diff --git a/src/Widgets/home/RatingSection/icons/arrow-down-icon.svg b/src/Widgets/home/RatingSection/icons/arrow-down-icon.svg new file mode 100644 index 0000000..c551a14 --- /dev/null +++ b/src/Widgets/home/RatingSection/icons/arrow-down-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/Widgets/home/RatingSection/icons/arrow-up-icon.svg b/src/Widgets/home/RatingSection/icons/arrow-up-icon.svg new file mode 100644 index 0000000..ffd6c64 --- /dev/null +++ b/src/Widgets/home/RatingSection/icons/arrow-up-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/Widgets/home/RatingSection/icons/like-icon.svg b/src/Widgets/home/RatingSection/icons/like-icon.svg new file mode 100644 index 0000000..81f3b3b --- /dev/null +++ b/src/Widgets/home/RatingSection/icons/like-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/Widgets/home/RatingSection/icons/message-icon.svg b/src/Widgets/home/RatingSection/icons/message-icon.svg new file mode 100644 index 0000000..a718e8e --- /dev/null +++ b/src/Widgets/home/RatingSection/icons/message-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/Widgets/home/RatingSection/rating.store.ts b/src/Widgets/home/RatingSection/rating.store.ts new file mode 100644 index 0000000..2413818 --- /dev/null +++ b/src/Widgets/home/RatingSection/rating.store.ts @@ -0,0 +1,32 @@ +import { baseAPI } from "@/Shared/API/baseAPI"; +import { IFetch } from "@/Shared/types"; +import axios from "axios"; +import { create } from "zustand"; +import { IReport } from "./types"; + +interface IRatingStore extends IFetch { + data: IReport; + getRatings: () => Promise; +} + +export const useRating = create((set) => ({ + data: { + count: 0, + results: [], + }, + loading: false, + error: "", + getRatings: async () => { + try { + set({ loading: true }); + + const response = await axios.get(`${baseAPI}/report/`); + + set({ data: response.data }); + } catch (error: any) { + set({ error: error.message }); + } finally { + set({ loading: false }); + } + }, +})); diff --git a/src/Widgets/home/RatingSection/types.ts b/src/Widgets/home/RatingSection/types.ts new file mode 100644 index 0000000..cb7a0ef --- /dev/null +++ b/src/Widgets/home/RatingSection/types.ts @@ -0,0 +1,19 @@ +export interface ILocation { + id: number; + address: string; +} + +export interface IReport { + count: number; + results: IResults[]; +} + +interface IResults { + id: number; + created_at: string; + location: ILocation[]; + category: number; + description: string; + count_reviews: number; + total_likes: number; +}