forked from Transparency/kgroad-frontend2
Compare commits
17
Commits
release006
...
release008
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2282ee5b0 | ||
|
|
775e238e77 | ||
|
|
5eff43ef61 | ||
|
|
3c810dad82 | ||
|
|
b10ab93bf1 | ||
|
|
49cb64a368 | ||
|
|
cbe5c0656c | ||
|
|
1a606f4ecd | ||
|
|
19397689b1 | ||
|
|
922d8386c6 | ||
|
|
dcac729914 | ||
|
|
ecd3848ec3 | ||
|
|
32761ce479 | ||
|
|
54ec09afe0 | ||
|
|
ea58e4f2d1 | ||
|
|
c3697c9e55 | ||
|
|
b85d1e8f30 |
No files matched your search
@@ -1,3 +1,12 @@
|
|||||||
|
## TL;DR
|
||||||
|
|
||||||
|
```
|
||||||
|
git pull
|
||||||
|
yarn install
|
||||||
|
yarn build
|
||||||
|
yarn start
|
||||||
|
```
|
||||||
|
|
||||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"@next/third-parties": "^14.1.0",
|
"@next/third-parties": "^14.1.0",
|
||||||
"axios": "^1.6.5",
|
"axios": "^1.6.5",
|
||||||
"dotenv": "^16.4.1",
|
"dotenv": "^16.4.1",
|
||||||
|
"html-react-parser": "^5.1.15",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"next": "^14.1.0",
|
"next": "^14.1.0",
|
||||||
"next-auth": "^4.24.5",
|
"next-auth": "^4.24.5",
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
.app {
|
// .app {
|
||||||
padding-top: 78px;
|
// padding-top: 78px;
|
||||||
}
|
// }
|
||||||
|
|
||||||
@media screen and (max-width: 768px) {
|
// @media screen and (max-width: 768px) {
|
||||||
.app {
|
// .app {
|
||||||
padding-top: 72px;
|
// padding-top: 72px;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
@@ -8,15 +8,14 @@ import calendar from "./icons/calendar.svg";
|
|||||||
import ReviewSection from "@/widgets/ReviewSection/ReviewSection";
|
import ReviewSection from "@/widgets/ReviewSection/ReviewSection";
|
||||||
import BreadCrumbs from "@/features/BreadCrumbs/BreadCrumbs";
|
import BreadCrumbs from "@/features/BreadCrumbs/BreadCrumbs";
|
||||||
import { Metadata } from "next";
|
import { Metadata } from "next";
|
||||||
|
import parse from "html-react-parser";
|
||||||
|
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
params,
|
params,
|
||||||
}: {
|
}: {
|
||||||
params: { id: string };
|
params: { id: string };
|
||||||
}): Promise<Metadata> {
|
}): Promise<Metadata> {
|
||||||
const response = await apiInstance.get<INews>(
|
const response = await apiInstance.get<INews>(`/news/${params.id}/`);
|
||||||
`/news/${params.id}/`
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: response.data.title,
|
title: response.data.title,
|
||||||
@@ -28,6 +27,17 @@ export async function generateMetadata({
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
function convertLinksToHtml(text: string) {
|
||||||
|
const urlPattern =
|
||||||
|
/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|$!:,.;]*[-A-Z0-9+&@#\/%=~_|$])[\s.,;]?/gi;
|
||||||
|
return text.replace(urlPattern, (url) => {
|
||||||
|
const href = url.trim();
|
||||||
|
return `<a href="${href}" target="_blank" rel="noopener noreferrer">${href}</a>`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const formatDescription = (text: string) => {
|
||||||
|
return text.replace(/(\r\n|\n|\r)/g, "<br />");
|
||||||
|
};
|
||||||
|
|
||||||
const NewsDetails = async ({
|
const NewsDetails = async ({
|
||||||
params,
|
params,
|
||||||
@@ -35,9 +45,7 @@ const NewsDetails = async ({
|
|||||||
params: { id: string; новость: string };
|
params: { id: string; новость: string };
|
||||||
}) => {
|
}) => {
|
||||||
const getNewsById = async () => {
|
const getNewsById = async () => {
|
||||||
const response = await apiInstance.get<INews>(
|
const response = await apiInstance.get<INews>(`/news/${params.id}/`);
|
||||||
`/news/${params.id}/`
|
|
||||||
);
|
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
@@ -58,7 +66,8 @@ const NewsDetails = async ({
|
|||||||
"11": "Ноябрь",
|
"11": "Ноябрь",
|
||||||
"12": "Декабрь",
|
"12": "Декабрь",
|
||||||
};
|
};
|
||||||
|
const htmlContentWithLinks = convertLinksToHtml(data.description);
|
||||||
|
const formattedHtmlContent = formatDescription(htmlContentWithLinks);
|
||||||
return (
|
return (
|
||||||
<div className="news-details page-padding">
|
<div className="news-details page-padding">
|
||||||
<BreadCrumbs />
|
<BreadCrumbs />
|
||||||
@@ -71,9 +80,9 @@ const NewsDetails = async ({
|
|||||||
<Image src={calendar} alt="Calendar Icon" />
|
<Image src={calendar} alt="Calendar Icon" />
|
||||||
<p>
|
<p>
|
||||||
{months[data.created_at.slice(5, 7)]}{" "}
|
{months[data.created_at.slice(5, 7)]}{" "}
|
||||||
{data.created_at.slice(5, 7).slice(0, 1) === "0"
|
{data.created_at.slice(8, 10) === "0"
|
||||||
? data.created_at.slice(6, 7)
|
? data.created_at.slice(9, 10)
|
||||||
: data.created_at.slice(5, 7)}
|
: data.created_at.slice(8, 10)}
|
||||||
, {data.created_at.slice(0, 4)}
|
, {data.created_at.slice(0, 4)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -87,7 +96,9 @@ const NewsDetails = async ({
|
|||||||
|
|
||||||
<div className="news-details__text">
|
<div className="news-details__text">
|
||||||
<h3>{data.title}</h3>
|
<h3>{data.title}</h3>
|
||||||
<p>{data.description}</p>
|
<div className="news-details__description">
|
||||||
|
{parse(formattedHtmlContent)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ReviewSection endpoint="news" id={data.id} />
|
<ReviewSection endpoint="news" id={data.id} />
|
||||||
|
|||||||
@@ -29,10 +29,7 @@ const NewsCard: React.FC<INewsCard> = ({
|
|||||||
return title;
|
return title;
|
||||||
};
|
};
|
||||||
const sliceDate = (date: string) => {
|
const sliceDate = (date: string) => {
|
||||||
return `${date.slice(8, 10)}/${date.slice(5, 7)}/${date.slice(
|
return `${date.slice(8, 10)}/${date.slice(5, 7)}/${date.slice(0, 4)}`;
|
||||||
0,
|
|
||||||
4
|
|
||||||
)}`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const sliceDescription = (description: string) => {
|
const sliceDescription = (description: string) => {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
img {
|
img {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ export const LINKS = () => {
|
|||||||
{ id: 1, pagename: t("home"), pathname: "/" },
|
{ id: 1, pagename: t("home"), pathname: "/" },
|
||||||
{ id: 2, pagename: t("about_us"), pathname: "/about-us" },
|
{ id: 2, pagename: t("about_us"), pathname: "/about-us" },
|
||||||
{ id: 3, pagename: t("privacy"), pathname: "/privacy" },
|
{ id: 3, pagename: t("privacy"), pathname: "/privacy" },
|
||||||
{ id: 3, pagename: t("support"), pathname: "/support" },
|
{ id: 4, pagename: t("support"), pathname: "/support" },
|
||||||
{ id: 4, pagename: t("statistics"), pathname: "/statistics" },
|
{ id: 5, pagename: t("statistics"), pathname: "/statistics" },
|
||||||
{ id: 5, pagename: t("news"), pathname: "/news" },
|
{ id: 6, pagename: t("news"), pathname: "/news" },
|
||||||
{ id: 6, pagename: t("volunteers"), pathname: "/volunteers" },
|
{ id: 7, pagename: t("volunteers"), pathname: "/volunteers" },
|
||||||
];
|
];
|
||||||
|
|
||||||
return LINKS;
|
return LINKS;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import play_market_btn from "./icons/play-market-btn.svg";
|
|||||||
import { Link } from "@/shared/config/navigation";
|
import { Link } from "@/shared/config/navigation";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import NetKgTracker from "@/widgets/NetKgTracker/NetKgTracker";
|
import NetKgTracker from "@/widgets/NetKgTracker/NetKgTracker";
|
||||||
|
import GoogleAnalyticsWidget from "@/widgets/GoogleAnalyticsWidget/GoogleAnalyticsWidget";
|
||||||
|
|
||||||
const Footer = () => {
|
const Footer = () => {
|
||||||
const t = useTranslations("general");
|
const t = useTranslations("general");
|
||||||
@@ -29,13 +30,16 @@ const Footer = () => {
|
|||||||
<ul>
|
<ul>
|
||||||
{LINKS().map((link) => (
|
{LINKS().map((link) => (
|
||||||
<li key={link.id}>
|
<li key={link.id}>
|
||||||
<Link href={link.pathname} key={link.id}>
|
<Link href={link.pathname}>{link.pagename}</Link>
|
||||||
{link.pagename}
|
|
||||||
</Link>
|
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
{/* Only for production*/}
|
||||||
<NetKgTracker />
|
<NetKgTracker />
|
||||||
|
<div className="footer__logo">
|
||||||
|
<GoogleAnalyticsWidget />
|
||||||
|
</div>
|
||||||
|
*
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="footer__contacts">
|
<div className="footer__contacts">
|
||||||
@@ -47,7 +51,7 @@ const Footer = () => {
|
|||||||
<li>
|
<li>
|
||||||
{[youtube, facebook, instagram].map((net, i) => (
|
{[youtube, facebook, instagram].map((net, i) => (
|
||||||
<Link key={i} href="#">
|
<Link key={i} href="#">
|
||||||
<Image src={net} alt="Net Icon" key={net} />
|
<Image src={net} alt="Net Icon" />
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</li>
|
</li>
|
||||||
@@ -60,7 +64,7 @@ const Footer = () => {
|
|||||||
<div className="footer__apps-btns">
|
<div className="footer__apps-btns">
|
||||||
{[app_store_btn, play_market_btn].map((app, i) => (
|
{[app_store_btn, play_market_btn].map((app, i) => (
|
||||||
<Link key={i} href="#">
|
<Link key={i} href="#">
|
||||||
<Image src={app} alt="App Button" key={app} />
|
<Image src={app} alt="App Button" />
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
'use client'
|
||||||
|
import React, { useEffect, useState, useCallback } from 'react';
|
||||||
|
import { apiInstance } from "@/shared/config/apiConfig";
|
||||||
|
import { AxiosError } from "axios";
|
||||||
|
|
||||||
|
const GoogleAnalyticsWidget = () => {
|
||||||
|
|
||||||
|
const [visitors, setVisitors] = useState<string>("");
|
||||||
|
|
||||||
|
/* const getAnalytics = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiInstance.get("/report/google_analytics/");
|
||||||
|
return response.data;
|
||||||
|
} catch (error: unknown) {
|
||||||
|
if (error instanceof AxiosError) console.log(error.message);
|
||||||
|
}
|
||||||
|
};*/
|
||||||
|
|
||||||
|
//const data = await getAnalytics();
|
||||||
|
|
||||||
|
const fetchMyAPI = useCallback(async () => {
|
||||||
|
const getAnalytics = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiInstance.get("/report/google_analytics/");
|
||||||
|
return response.data;
|
||||||
|
} catch (error: unknown) {
|
||||||
|
if (error instanceof AxiosError) console.log(error.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const data = await getAnalytics();
|
||||||
|
setVisitors(data.visitors);
|
||||||
|
}, [visitors])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchMyAPI();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div><p>Total cummulative visitors: {visitors}</p></div>
|
||||||
|
)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GoogleAnalyticsWidget;
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
min-width: 130px;
|
min-width: 130px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 120%;
|
top: 120%;
|
||||||
|
z-index: 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__option,
|
&__option,
|
||||||
|
|||||||
@@ -2,17 +2,12 @@
|
|||||||
|
|
||||||
.navbar {
|
.navbar {
|
||||||
padding: 15px 90px;
|
padding: 15px 90px;
|
||||||
// padding: 15px;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
// height: 78px;
|
|
||||||
position: fixed;
|
|
||||||
z-index: 10005;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
box-shadow: 0 4px 6px #0000001a;
|
box-shadow: 0 4px 6px #0000001a;
|
||||||
margin-bottom: 40px;
|
|
||||||
|
|
||||||
&__logo {
|
&__logo {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Reference in new issue
Block a user