forked from Transparency/kgroad-frontend2
added next-intl, composed next-auth and next-intl in middleware, fixed some bugs, completed details page, added google auth
This commit is contained in:
1 parent
9cd7b2a67d
commit
6637ab4eae
172 files changed
+1772
-502
No files matched your search
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -10,7 +10,7 @@ export const metadata: Metadata = {
|
||||
};
|
||||
|
||||
const DynamicForm = dynamic(
|
||||
() => import("@/widgets/ReportForm/ReportForm"),
|
||||
() => import("@/widgets/forms/ReportForm/ReportForm"),
|
||||
{
|
||||
ssr: false,
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,34 @@
|
||||
import type { Metadata } from "next";
|
||||
import "./globals.scss";
|
||||
import "./App.scss";
|
||||
// import "@/shared/fonts/fonts.scss";
|
||||
import Navbar from "@/widgets/Navbar/Navbar";
|
||||
import Footer from "@/widgets/Footer/Footer";
|
||||
import { NextIntlClientProvider, useMessages } from "next-intl";
|
||||
import { Providers } from "./Providers";
|
||||
|
||||
export default function LocaleLayout({
|
||||
children,
|
||||
params,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
params: { locale: string };
|
||||
}>) {
|
||||
const messages = useMessages();
|
||||
return (
|
||||
<html lang={params.locale}>
|
||||
<body>
|
||||
<NextIntlClientProvider
|
||||
locale={params.locale}
|
||||
messages={messages}
|
||||
>
|
||||
<Providers>
|
||||
<Navbar />
|
||||
<div className="app">{children}</div>
|
||||
<Footer />
|
||||
</Providers>
|
||||
</NextIntlClientProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,7 +1,5 @@
|
||||
import "./News.scss";
|
||||
import Typography from "@/shared/ui/components/Typography/Typography";
|
||||
import { apiInstance } from "@/shared/config/apiConfig";
|
||||
import { INewsList } from "@/shared/types/news-type";
|
||||
import NewsList from "@/widgets/NewsList/NewsList";
|
||||
import { Metadata } from "next";
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import Header from "@/widgets/Header/Header";
|
||||
import StatisticsSection from "@/widgets/StatisticsSection/StatisticsSection";
|
||||
import RatingSection from "@/widgets/RatingSection/RatingSection";
|
||||
import NewsSection from "@/widgets/NewsSection/NewsSection";
|
||||
import MapSection from "@/widgets/MapSection/MapSection";
|
||||
import Header from "@/widgets/home/Header/Header";
|
||||
import StatisticsSection from "@/widgets/home/StatisticsSection/StatisticsSection";
|
||||
import RatingSection from "@/widgets/home/RatingSection/RatingSection";
|
||||
import NewsSection from "@/widgets/home/NewsSection/NewsSection";
|
||||
import MapSection from "@/widgets/home/MapSection/MapSection";
|
||||
import { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
@@ -14,13 +14,9 @@ const AuthGuard = ({ children }: { children: React.ReactNode }) => {
|
||||
};
|
||||
await apiInstance.post("/token/verify/", data);
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError) {
|
||||
if (error.response?.data.code === "token_not_valid") {
|
||||
signOut({
|
||||
callbackUrl: "/",
|
||||
});
|
||||
}
|
||||
}
|
||||
signOut({
|
||||
callbackUrl: "/",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
File renamed without changes.
@@ -6,7 +6,6 @@ import { AxiosError } from "axios";
|
||||
import { apiInstance } from "@/shared/config/apiConfig";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { authConfig } from "@/shared/config/authConfig";
|
||||
import { IProfile } from "@/shared/types/profile-type";
|
||||
import { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
@@ -1,4 +1,4 @@
|
||||
import ProfileTable from "@/widgets/ProfileTable/ProfileTable";
|
||||
import ProfileTable from "@/widgets/tables/ProfileTable/ProfileTable";
|
||||
import React from "react";
|
||||
|
||||
const MyReports = async ({
|
||||
@@ -1,5 +1,3 @@
|
||||
import React from "react";
|
||||
|
||||
const page = () => {
|
||||
return <div>page</div>;
|
||||
};
|
||||
@@ -4,7 +4,7 @@ import ProfileAvatar from "@/features/ProfileAvatar/ProfileAvatar";
|
||||
import { apiInstance } from "@/shared/config/apiConfig";
|
||||
import { authConfig } from "@/shared/config/authConfig";
|
||||
import { IProfile } from "@/shared/types/profile-type";
|
||||
import ProfileForm from "@/widgets/ProfileForm/ProfileForm";
|
||||
import ProfileForm from "@/widgets/forms/ProfileForm/ProfileForm";
|
||||
import { AxiosError } from "axios";
|
||||
import { getServerSession } from "next-auth";
|
||||
import React from "react";
|
||||
@@ -0,0 +1,37 @@
|
||||
.report-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 75px;
|
||||
&__container {
|
||||
display: grid;
|
||||
grid-template-columns: 1.05fr 1fr;
|
||||
gap: 76px;
|
||||
}
|
||||
|
||||
&__map {
|
||||
grid-row: 2 / 3;
|
||||
grid-column: 1 / 3;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
.report-details {
|
||||
&__container {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 45px;
|
||||
}
|
||||
|
||||
&__map {
|
||||
grid-row: 2 / 3;
|
||||
grid-column: 1 / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 550px) {
|
||||
.report-details {
|
||||
&__container {
|
||||
gap: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,66 @@
|
||||
import "./ReportDetails.scss";
|
||||
import { IReport } from "@/shared/types/report-type";
|
||||
|
||||
import ReviewSection from "@/widgets/ReviewSection/ReviewSection";
|
||||
import { Metadata } from "next";
|
||||
import ReportInformation from "@/widgets/report-details/ReportInformation/ReportInformation";
|
||||
import ReportImages from "@/widgets/report-details/ReportImages/ReportImages";
|
||||
import dynamic from "next/dynamic";
|
||||
import BreadCrumbs from "@/features/BreadCrumbs/BreadCrumbs";
|
||||
|
||||
const DynamicMap = dynamic(
|
||||
() => import("@/widgets/report-details/ReportMap/ReportMap"),
|
||||
{
|
||||
ssr: false,
|
||||
}
|
||||
);
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "KG ROAD | Обращение",
|
||||
description:
|
||||
"Страница обращения Kyrgyzstan Transperency International",
|
||||
};
|
||||
|
||||
const ReportDetails = async ({
|
||||
params,
|
||||
}: {
|
||||
params: { id: string };
|
||||
}) => {
|
||||
const getReportDetails = async () => {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_BASE_API}/report/${params.id}/`,
|
||||
{ cache: "no-store" }
|
||||
);
|
||||
|
||||
return res.json();
|
||||
};
|
||||
const report: IReport = await getReportDetails();
|
||||
|
||||
return (
|
||||
<div className="report-details page-padding">
|
||||
<BreadCrumbs />
|
||||
<div className="report-details__container">
|
||||
<ReportInformation
|
||||
id={report.id}
|
||||
location={report.location[0]}
|
||||
date={report.created_at}
|
||||
description={report.description}
|
||||
category={report.category}
|
||||
total_likes={report.total_likes}
|
||||
author={report.author}
|
||||
/>
|
||||
<div className="report-details__map">
|
||||
<DynamicMap
|
||||
location={report.location}
|
||||
category={report.category}
|
||||
/>
|
||||
</div>
|
||||
<ReportImages images={report.image} />
|
||||
</div>
|
||||
|
||||
<ReviewSection endpoint="report" id={+params.id} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReportDetails;
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import "@/shared/ui/auth-classes.scss";
|
||||
import ForgotPasswordForm from "@/widgets/ForgotPasswordForm/ForgotPasswordForm";
|
||||
import ForgotPasswordForm from "@/widgets/forms/ForgotPasswordForm/ForgotPasswordForm";
|
||||
|
||||
const ForgotPassword = () => {
|
||||
return (
|
||||
File renamed without changes.
@@ -1,9 +1,9 @@
|
||||
import "@/shared/ui/auth-classes.scss";
|
||||
import Image from "next/image";
|
||||
import sign_in_icon from "./icons/sign-in_icon.svg";
|
||||
import SignInForm from "@/widgets/SignInForm/SignInForm";
|
||||
import Link from "next/link";
|
||||
import SignInForm from "@/widgets/forms/SignInForm/SignInForm";
|
||||
import { Metadata } from "next";
|
||||
import { Link } from "@/shared/config/navigation";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "KG ROAD | Вход",
|
||||
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
import "@/shared/ui/auth-classes.scss";
|
||||
import Image from "next/image";
|
||||
import key from "./icons/key.svg";
|
||||
import ResetCodeForm from "@/widgets/ResetCodeForm/ResetCodeForm";
|
||||
import ResetCodeForm from "@/widgets/forms/ResetCodeForm/ResetCodeForm";
|
||||
|
||||
const ResetCode = () => {
|
||||
return (
|
||||
File renamed without changes.
+1
-1
@@ -1,7 +1,7 @@
|
||||
import "@/shared/ui/auth-classes.scss";
|
||||
import Image from "next/image";
|
||||
import mail from "./icons/mail.svg";
|
||||
import ConfirmEmailForm from "@/widgets/ConfirmEmailForm/ConfirmEmailForm";
|
||||
import ConfirmEmailForm from "@/widgets/forms/ConfirmEmailForm/ConfirmEmailForm";
|
||||
|
||||
const ConfirmEmail = ({
|
||||
searchParams,
|
||||
File renamed without changes.
@@ -1,9 +1,9 @@
|
||||
import "@/shared/ui/auth-classes.scss";
|
||||
import Image from "next/image";
|
||||
import flag from "./icons/flag.svg";
|
||||
import Link from "next/link";
|
||||
import SignUpForm from "@/widgets/SignUpForm/SignUpForm";
|
||||
import SignUpForm from "@/widgets/forms/SignUpForm/SignUpForm";
|
||||
import { Metadata } from "next";
|
||||
import { Link } from "@/shared/config/navigation";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "KG ROAD | Регистрация",
|
||||
File renamed without changes.
@@ -1,9 +1,6 @@
|
||||
import Typography from "@/shared/ui/components/Typography/Typography";
|
||||
import "./Statistics.scss";
|
||||
import { apiInstance } from "@/shared/config/apiConfig";
|
||||
import { IStatistics } from "@/shared/types/statistics-type";
|
||||
import { AxiosError } from "axios";
|
||||
import StatisticsTable from "@/widgets/StatisticsTable/StatisticsTable";
|
||||
import StatisticsTable from "@/widgets/tables/StatisticsTable/StatisticsTable";
|
||||
import { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
File renamed without changes.
@@ -1,6 +1,6 @@
|
||||
import Typography from "@/shared/ui/components/Typography/Typography";
|
||||
import "./Volunteers.scss";
|
||||
import VolunteersTable from "@/widgets/VolunteersTable/VolunteersTable";
|
||||
import VolunteersTable from "@/widgets/tables/VolunteersTable/VolunteersTable";
|
||||
import { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
+7
-23
@@ -1,25 +1,9 @@
|
||||
import type { Metadata } from "next";
|
||||
import "./globals.scss";
|
||||
import "./App.scss";
|
||||
// import "@/shared/fonts/fonts.scss";
|
||||
import { Providers } from "./Providers";
|
||||
import Navbar from "@/widgets/Navbar/Navbar";
|
||||
import Footer from "@/widgets/Footer/Footer";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<Providers>
|
||||
<Navbar />
|
||||
<div className="app">{children}</div>
|
||||
<Footer />
|
||||
</Providers>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
type Props = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
export default function RootLayout({ children }: Props) {
|
||||
return children;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import Error from "next/error";
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<Error statusCode={404} />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
.report-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 75px;
|
||||
&__container {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
.report-information {
|
||||
max-width: 646px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
|
||||
h2 {
|
||||
margin-bottom: 4px;
|
||||
text-align: start;
|
||||
font-size: 42px;
|
||||
font-weight: 500;
|
||||
line-height: 50px;
|
||||
color: rgb(0, 0, 0);
|
||||
}
|
||||
|
||||
&__date-and-like {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 80px;
|
||||
}
|
||||
|
||||
&__date {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
|
||||
p {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
color: rgba(62, 50, 50, 0.75);
|
||||
}
|
||||
}
|
||||
|
||||
&__description {
|
||||
margin-bottom: 4px;
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
line-height: 34px;
|
||||
color: rgb(62, 50, 50);
|
||||
}
|
||||
|
||||
&__author {
|
||||
margin-bottom: 40px;
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
line-height: 34px;
|
||||
color: rgb(102, 102, 102);
|
||||
|
||||
span {
|
||||
color: rgb(72, 159, 225);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
&__show-map {
|
||||
width: fit-content;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
line-height: 34px;
|
||||
text-decoration: underline;
|
||||
color: rgb(102, 102, 102);
|
||||
}
|
||||
}
|
||||
|
||||
.report-images {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
gap: 20px;
|
||||
|
||||
&__exist {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
&__default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 10px;
|
||||
background-color: rgb(209, 217, 226);
|
||||
}
|
||||
|
||||
&__item1 {
|
||||
grid-column: 1 / 5;
|
||||
height: 441px;
|
||||
}
|
||||
|
||||
&__item2,
|
||||
&__item3,
|
||||
&__item4,
|
||||
&__item5 {
|
||||
height: 102px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
.report-details {
|
||||
&__container {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 45px;
|
||||
}
|
||||
}
|
||||
|
||||
.report-information {
|
||||
max-width: 100%;
|
||||
|
||||
h2 {
|
||||
font-size: 36px;
|
||||
line-height: 43px;
|
||||
}
|
||||
|
||||
&__description {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 550px) {
|
||||
.report-details {
|
||||
&__container {
|
||||
gap: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.report-information {
|
||||
h2 {
|
||||
font-size: 24px;
|
||||
line-height: 29px;
|
||||
}
|
||||
|
||||
&__description {
|
||||
font-size: 16px;
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
&__author {
|
||||
margin-bottom: 0px;
|
||||
font-size: 16px;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
&__show-map {
|
||||
font-size: 16px;
|
||||
line-height: 34px;
|
||||
}
|
||||
}
|
||||
|
||||
.report-images {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
|
||||
&__item1 {
|
||||
grid-column: 1 / 2;
|
||||
}
|
||||
|
||||
&__item1,
|
||||
&__item2,
|
||||
&__item3,
|
||||
&__item4,
|
||||
&__item5 {
|
||||
height: 162px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<svg width="16.000000" height="16.000000" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<desc>
|
||||
Created with Pixso.
|
||||
</desc>
|
||||
<defs>
|
||||
<clipPath id="clip2340_50999">
|
||||
<rect id="calendar" width="16.000000" height="16.000000" fill="white" fill-opacity="0"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<rect id="calendar" width="16.000000" height="16.000000" fill="#FFFFFF" fill-opacity="0"/>
|
||||
<g clip-path="url(#clip2340_50999)">
|
||||
<path id="Vector" d="M12.666 2.66699C13.4023 2.66699 14 3.26367 14 4L14 13.334C14 14.0703 13.4023 14.667 12.666 14.667L3.33398 14.667C2.59766 14.667 2 14.0703 2 13.334L2 4C2 3.26367 2.59766 2.66699 3.33398 2.66699L12.666 2.66699Z" stroke="#6E6565" stroke-opacity="1.000000" stroke-width="1.000000" stroke-linejoin="round"/>
|
||||
<path id="Vector" d="M10.666 1.33301L10.666 4" stroke="#6E6565" stroke-opacity="1.000000" stroke-width="1.000000" stroke-linejoin="round" stroke-linecap="round"/>
|
||||
<path id="Vector" d="M5.33398 1.33301L5.33398 4" stroke="#6E6565" stroke-opacity="1.000000" stroke-width="1.000000" stroke-linejoin="round" stroke-linecap="round"/>
|
||||
<path id="Vector" d="M2 6.66699L14 6.66699" stroke="#6E6565" stroke-opacity="1.000000" stroke-width="1.000000" stroke-linejoin="round" stroke-linecap="round"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,17 +0,0 @@
|
||||
<svg width="24.000000" height="24.000000" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<desc>
|
||||
Created with Pixso.
|
||||
</desc>
|
||||
<defs>
|
||||
<clipPath id="clip824_20705">
|
||||
<rect id="map-pin" width="24.000000" height="24.000000" fill="white" fill-opacity="0"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<rect id="map-pin" width="24.000000" height="24.000000" fill="#FFFFFF" fill-opacity="0"/>
|
||||
<g clip-path="url(#clip824_20705)">
|
||||
<path id="Vector" d="M21 10C21 17 12 23 12 23C12 23 3 17 3 10C3 7.61328 3.94727 5.32422 5.63672 3.63574C7.32422 1.94824 9.61328 1 12 1C14.3867 1 16.6758 1.94824 18.3633 3.63574C20.0527 5.32422 21 7.61328 21 10Z" fill="#3998E8" fill-opacity="1.000000" fill-rule="nonzero"/>
|
||||
<path id="Vector" d="M12 23C12 23 3 17 3 10C3 7.61328 3.94727 5.32422 5.63672 3.63574C7.32422 1.94824 9.61328 1 12 1C14.3867 1 16.6758 1.94824 18.3633 3.63574C20.0527 5.32422 21 7.61328 21 10C21 17 12 23 12 23Z" stroke="#3998E8" stroke-opacity="1.000000" stroke-width="2.000000" stroke-linejoin="round"/>
|
||||
<path id="Vector" d="M12 13C13.6562 13 15 11.6572 15 10C15 8.34277 13.6562 7 12 7C10.3438 7 9 8.34277 9 10C9 11.6572 10.3438 13 12 13Z" fill="#FFFFFF" fill-opacity="1.000000" fill-rule="nonzero"/>
|
||||
<path id="Vector" d="M12 13C10.3438 13 9 11.6572 9 10C9 8.34277 10.3438 7 12 7C13.6562 7 15 8.34277 15 10C15 11.6572 13.6562 13 12 13Z" stroke="#FFFFFF" stroke-opacity="1.000000" stroke-width="2.000000" stroke-linejoin="round"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,138 +0,0 @@
|
||||
import "./ReportDetails.scss";
|
||||
import Image from "next/image";
|
||||
import RoadType from "@/entities/RoadType/RoadType";
|
||||
import ReportLike from "@/features/ReportLike/ReportLike";
|
||||
import { apiInstance } from "@/shared/config/apiConfig";
|
||||
import { IReport } from "@/shared/types/report-type";
|
||||
import {
|
||||
ROAD_TYPES,
|
||||
ROAD_TYPES_COLORS,
|
||||
} from "@/shared/variables/road-types";
|
||||
import calendar from "./icons/calendar.svg";
|
||||
import map_pin from "./icons/map-pin.svg";
|
||||
import def_image from "./icons/def_image.svg";
|
||||
import ReviewSection from "@/widgets/ReviewSection/ReviewSection";
|
||||
import { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "KG ROAD | Обращение",
|
||||
description:
|
||||
"Страница обращения Kyrgyzstan Transperency International",
|
||||
};
|
||||
|
||||
const ReportDetails = async ({
|
||||
params,
|
||||
}: {
|
||||
params: { id: string };
|
||||
}) => {
|
||||
const getReportDetails = async () => {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_BASE_API}/report/${params.id}/`,
|
||||
{ cache: "no-store" }
|
||||
);
|
||||
|
||||
return res.json();
|
||||
};
|
||||
const report: IReport = await getReportDetails();
|
||||
|
||||
const months: Record<string, string> = {
|
||||
"01": "Январь",
|
||||
"02": "Февраль",
|
||||
"03": "Март",
|
||||
"04": "Апрель",
|
||||
"05": "Май",
|
||||
"06": "Июнь",
|
||||
"07": "Июль",
|
||||
"08": "Август",
|
||||
"09": "Сентябрь",
|
||||
"10": "Октябрь",
|
||||
"11": "Ноябрь",
|
||||
"12": "Декабрь",
|
||||
};
|
||||
|
||||
const showImages = () => {
|
||||
const images = [];
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
if (report.image[i]) {
|
||||
const image = (
|
||||
<img
|
||||
className={`report-images__exist report-images__item${
|
||||
i + 1
|
||||
}`}
|
||||
key={i}
|
||||
src={report.image[i].image}
|
||||
alt="Report Image"
|
||||
/>
|
||||
);
|
||||
images.push(image);
|
||||
} else {
|
||||
const defImage = (
|
||||
<div
|
||||
className={`report-images__default report-images__item${
|
||||
i + 1
|
||||
}`}
|
||||
key={i}
|
||||
>
|
||||
<Image src={def_image} alt="Default Image" />
|
||||
</div>
|
||||
);
|
||||
images.push(defImage);
|
||||
}
|
||||
}
|
||||
|
||||
return images;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="report-details page-padding">
|
||||
<div className="report-details__container">
|
||||
<div className="report-information">
|
||||
<RoadType color={ROAD_TYPES_COLORS[report.category]}>
|
||||
{ROAD_TYPES[report.category]}
|
||||
</RoadType>
|
||||
<h2>{report.location[0].address}</h2>
|
||||
<div className="report-information__date-and-like">
|
||||
<div className="report-information__date">
|
||||
<Image src={calendar} alt="Calendar Icon" />
|
||||
<p>
|
||||
{months[report.created_at.slice(5, 7)]}{" "}
|
||||
{report.created_at.slice(5, 7).slice(0, 1) === "0"
|
||||
? report.created_at.slice(6, 7)
|
||||
: report.created_at.slice(5, 7)}
|
||||
, {report.created_at.slice(0, 4)}
|
||||
</p>
|
||||
</div>
|
||||
<ReportLike
|
||||
count={report.total_likes}
|
||||
report_id={report.id}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p className="report-information__description">
|
||||
{report.description}
|
||||
</p>
|
||||
|
||||
<p className="report-information__author">
|
||||
Автор обращения:{" "}
|
||||
<span>
|
||||
{report.author.first_name}{" "}
|
||||
{report.author.last_name.slice(0, 1)}.
|
||||
</span>
|
||||
</p>
|
||||
<button className="report-information__show-map">
|
||||
<Image src={map_pin} alt="Map Pin Icon" />
|
||||
Показать на карте
|
||||
</button>
|
||||
</div>
|
||||
<div className="report-images">
|
||||
{showImages().map((image) => image)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ReviewSection endpoint="report" id={+params.id} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReportDetails;
|
||||
Reference in new issue
Block a user