From bb852f511928b0a989bfb6648b7e0e7bea4ee8c1 Mon Sep 17 00:00:00 2001 From: Alibek Date: Thu, 25 Jan 2024 16:48:05 +0600 Subject: [PATCH] made news details page, made review section --- package.json | 1 + src/Entities/NewsCard/NewsCard.tsx | 2 + src/Entities/ReviewCard/ReviewCard.scss | 53 +++++++++ src/Entities/ReviewCard/ReviewCard.tsx | 67 +++++++++++ .../ReviewCard/icons/calendar-icon.svg | 8 ++ src/Features/CreateReview/CreateReview.scss | 48 ++++++++ src/Features/CreateReview/CreateReview.tsx | 46 ++++++++ src/Features/CreateReview/actions.ts | 59 ++++++++++ src/Features/SignInForm/sign-in.store.ts | 2 +- src/Features/SignUpForm/sign-up.store.ts | 2 +- .../NewsDetailsPage/NewsDetailsPage.scss | 65 +++++++++++ src/Pages/NewsDetailsPage/NewsDetailsPage.tsx | 66 ++++++++++- .../NewsDetailsPage/icons/calendar-icon.svg | 8 ++ .../NewsDetailsPage/icons/message-icon.svg | 5 + src/Pages/NewsDetailsPage/store/index.ts | 1 + src/Pages/NewsDetailsPage/store/store.ts | 54 +++++++++ src/Pages/NewsPage/NewsPage.tsx | 4 +- src/Shared/UI/Button/Button.tsx | 11 +- src/Shared/helpers/getTokens.ts | 20 ++++ src/Widgets/NewsList/NewsList.tsx | 20 ++-- src/Widgets/NewsList/store/index.ts | 1 + src/Widgets/NewsList/store/store.ts | 39 +++++++ .../NewsReviewsSection.scss | 34 ++++++ .../NewsReviewsSection/NewsReviewsSection.tsx | 46 ++++++++ .../StatisticsTable/StatisticsTable.scss | 2 +- .../StatisticsTable/StatisticsTable.tsx | 110 ++++++++---------- .../StatisticsTable/statistics.store.ts | 38 +----- src/Widgets/general/Navbar/Navbar.tsx | 2 +- tsconfig.json | 7 +- yarn.lock | 12 +- 30 files changed, 710 insertions(+), 123 deletions(-) create mode 100644 src/Entities/ReviewCard/ReviewCard.scss create mode 100644 src/Entities/ReviewCard/ReviewCard.tsx create mode 100644 src/Entities/ReviewCard/icons/calendar-icon.svg create mode 100644 src/Features/CreateReview/CreateReview.scss create mode 100644 src/Features/CreateReview/CreateReview.tsx create mode 100644 src/Features/CreateReview/actions.ts create mode 100644 src/Pages/NewsDetailsPage/icons/calendar-icon.svg create mode 100644 src/Pages/NewsDetailsPage/icons/message-icon.svg create mode 100644 src/Pages/NewsDetailsPage/store/index.ts create mode 100644 src/Pages/NewsDetailsPage/store/store.ts create mode 100644 src/Shared/helpers/getTokens.ts create mode 100644 src/Widgets/NewsList/store/index.ts create mode 100644 src/Widgets/NewsList/store/store.ts create mode 100644 src/Widgets/NewsReviewsSection/NewsReviewsSection.scss create mode 100644 src/Widgets/NewsReviewsSection/NewsReviewsSection.tsx diff --git a/package.json b/package.json index f1e64f1..c6f06bb 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "react": "^18", "react-dom": "^18", "sass": "^1.70.0", + "swr": "^2.2.4", "zustand": "^4.5.0" }, "devDependencies": { diff --git a/src/Entities/NewsCard/NewsCard.tsx b/src/Entities/NewsCard/NewsCard.tsx index a8341a0..c27340f 100644 --- a/src/Entities/NewsCard/NewsCard.tsx +++ b/src/Entities/NewsCard/NewsCard.tsx @@ -1,3 +1,5 @@ +"use client"; + import Image, { StaticImageData } from "next/image"; import "./NewsCard.scss"; import Link from "next/link"; diff --git a/src/Entities/ReviewCard/ReviewCard.scss b/src/Entities/ReviewCard/ReviewCard.scss new file mode 100644 index 0000000..840c0dc --- /dev/null +++ b/src/Entities/ReviewCard/ReviewCard.scss @@ -0,0 +1,53 @@ +.review-card { + padding: 15px 20px; + display: flex; + flex-direction: column; + gap: 15px; + border-radius: 12px; + border: 1px solid #c5c6c5; + + &__header { + display: flex; + align-items: center; + gap: 10px; + + &_left { + min-width: 60px; + width: 60px; + height: 60px; + border-radius: 50%; + object-fit: cover; + } + + &_right { + display: flex; + flex-direction: column; + gap: 8px; + + h4 { + color: #3e3232; + font-size: 16px; + font-weight: 800; + } + + span { + display: flex; + align-items: center; + gap: 8px; + + color: rgba(62, 50, 50, 0.75); + font-size: 14px; + font-weight: 500; + line-height: 20px; + } + } + } + + p { + color: rgba(0, 0, 0, 0.75); + font-size: 18px; + font-weight: 500; + line-height: 20px; + letter-spacing: 0.25px; + } +} diff --git a/src/Entities/ReviewCard/ReviewCard.tsx b/src/Entities/ReviewCard/ReviewCard.tsx new file mode 100644 index 0000000..a22efb7 --- /dev/null +++ b/src/Entities/ReviewCard/ReviewCard.tsx @@ -0,0 +1,67 @@ +import Image from "next/image"; +import "./ReviewCard.scss"; +import calendar_icon from "./icons/calendar-icon.svg"; + +interface IReviewCardProps { + item: IReview; +} + +interface IReview { + id: number; + author: IAuthor; + review: string; + created_at: string; +} + +interface IAuthor { + id: number; + first_name: string; + last_name: string; + image: string; +} + +const ReviewCard: React.FC = ({ + item, +}: IReviewCardProps) => { + const months: Record = { + "01": "Январь", + "02": "Февраль", + "03": "Март", + "04": "Апрель", + "05": "Май", + "06": "Июнь", + "07": "Июль", + "08": "Август", + "09": "Сентябрь", + "10": "Октябрь", + "11": "Ноябрь", + "12": "Декабрь", + }; + + const year = item?.created_at.slice(0, 4); + const month = item?.created_at.slice(5, 7); + const day = item?.created_at.slice(8, 10); + return ( +
+
+ Author Image +
+

+ {item.author.first_name} {item.author.last_name} +

+ + Calendar Icon + {month && months[month]} {day}, {year} + +
+
+

{item.review}

+
+ ); +}; + +export default ReviewCard; diff --git a/src/Entities/ReviewCard/icons/calendar-icon.svg b/src/Entities/ReviewCard/icons/calendar-icon.svg new file mode 100644 index 0000000..9780d27 --- /dev/null +++ b/src/Entities/ReviewCard/icons/calendar-icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/Features/CreateReview/CreateReview.scss b/src/Features/CreateReview/CreateReview.scss new file mode 100644 index 0000000..ef2cc2e --- /dev/null +++ b/src/Features/CreateReview/CreateReview.scss @@ -0,0 +1,48 @@ +.create-review { + margin-top: 70px; + display: flex; + flex-direction: column; + gap: 40px; + + h3 { + display: flex; + align-items: center; + gap: 6px; + color: #3e3232; + font-size: 24px; + font-weight: 500; + + span { + width: 4px; + height: 10px; + border-radius: 12px; + background: #3998e8; + } + } + + div { + display: flex; + flex-direction: column; + gap: 18px; + + textarea { + height: 258px; + padding: 27px 18px; + resize: none; + border-radius: 12px; + border: 1px solid #c5c6c5; + font-size: 16px; + outline: none; + } + ::placeholder { + color: #c5c6c5; + font-size: 16px; + font-weight: 400; + } + + button { + width: fit-content; + align-self: flex-end; + } + } +} diff --git a/src/Features/CreateReview/CreateReview.tsx b/src/Features/CreateReview/CreateReview.tsx new file mode 100644 index 0000000..eb2bfcb --- /dev/null +++ b/src/Features/CreateReview/CreateReview.tsx @@ -0,0 +1,46 @@ +"use client"; + +import "./CreateReview.scss"; +import { useState } from "react"; +import Button from "@/Shared/UI/Button/Button"; +import { createReviewAction } from "./actions"; +import { StaticImageData } from "next/image"; + +interface ICreateReviewProps { + endpoint: string; + id: number | null | undefined; +} + +const CreateReview: React.FC = ({ + endpoint, + id, +}: ICreateReviewProps) => { + const [review, setReview] = useState(""); + + return ( +
+

+ + Написать комментарий +

+
+