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).
|
||||
|
||||
## Getting Started
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"@next/third-parties": "^14.1.0",
|
||||
"axios": "^1.6.5",
|
||||
"dotenv": "^16.4.1",
|
||||
"html-react-parser": "^5.1.15",
|
||||
"leaflet": "^1.9.4",
|
||||
"next": "^14.1.0",
|
||||
"next-auth": "^4.24.5",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
.app {
|
||||
padding-top: 78px;
|
||||
}
|
||||
// .app {
|
||||
// padding-top: 78px;
|
||||
// }
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.app {
|
||||
padding-top: 72px;
|
||||
}
|
||||
}
|
||||
// @media screen and (max-width: 768px) {
|
||||
// .app {
|
||||
// padding-top: 72px;
|
||||
// }
|
||||
// }
|
||||
@@ -8,15 +8,14 @@ import calendar from "./icons/calendar.svg";
|
||||
import ReviewSection from "@/widgets/ReviewSection/ReviewSection";
|
||||
import BreadCrumbs from "@/features/BreadCrumbs/BreadCrumbs";
|
||||
import { Metadata } from "next";
|
||||
import parse from "html-react-parser";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: { id: string };
|
||||
}): Promise<Metadata> {
|
||||
const response = await apiInstance.get<INews>(
|
||||
`/news/${params.id}/`
|
||||
);
|
||||
const response = await apiInstance.get<INews>(`/news/${params.id}/`);
|
||||
|
||||
return {
|
||||
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 ({
|
||||
params,
|
||||
@@ -35,9 +45,7 @@ const NewsDetails = async ({
|
||||
params: { id: string; новость: string };
|
||||
}) => {
|
||||
const getNewsById = async () => {
|
||||
const response = await apiInstance.get<INews>(
|
||||
`/news/${params.id}/`
|
||||
);
|
||||
const response = await apiInstance.get<INews>(`/news/${params.id}/`);
|
||||
|
||||
return response.data;
|
||||
};
|
||||
@@ -58,7 +66,8 @@ const NewsDetails = async ({
|
||||
"11": "Ноябрь",
|
||||
"12": "Декабрь",
|
||||
};
|
||||
|
||||
const htmlContentWithLinks = convertLinksToHtml(data.description);
|
||||
const formattedHtmlContent = formatDescription(htmlContentWithLinks);
|
||||
return (
|
||||
<div className="news-details page-padding">
|
||||
<BreadCrumbs />
|
||||
@@ -71,9 +80,9 @@ const NewsDetails = async ({
|
||||
<Image src={calendar} alt="Calendar Icon" />
|
||||
<p>
|
||||
{months[data.created_at.slice(5, 7)]}{" "}
|
||||
{data.created_at.slice(5, 7).slice(0, 1) === "0"
|
||||
? data.created_at.slice(6, 7)
|
||||
: data.created_at.slice(5, 7)}
|
||||
{data.created_at.slice(8, 10) === "0"
|
||||
? data.created_at.slice(9, 10)
|
||||
: data.created_at.slice(8, 10)}
|
||||
, {data.created_at.slice(0, 4)}
|
||||
</p>
|
||||
</div>
|
||||
@@ -87,7 +96,9 @@ const NewsDetails = async ({
|
||||
|
||||
<div className="news-details__text">
|
||||
<h3>{data.title}</h3>
|
||||
<p>{data.description}</p>
|
||||
<div className="news-details__description">
|
||||
{parse(formattedHtmlContent)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ReviewSection endpoint="news" id={data.id} />
|
||||
|
||||
@@ -29,10 +29,7 @@ const NewsCard: React.FC<INewsCard> = ({
|
||||
return title;
|
||||
};
|
||||
const sliceDate = (date: string) => {
|
||||
return `${date.slice(8, 10)}/${date.slice(5, 7)}/${date.slice(
|
||||
0,
|
||||
4
|
||||
)}`;
|
||||
return `${date.slice(8, 10)}/${date.slice(5, 7)}/${date.slice(0, 4)}`;
|
||||
};
|
||||
|
||||
const sliceDescription = (description: string) => {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
img {
|
||||
width: 50px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
input {
|
||||
|
||||
@@ -7,10 +7,10 @@ export const LINKS = () => {
|
||||
{ id: 1, pagename: t("home"), pathname: "/" },
|
||||
{ id: 2, pagename: t("about_us"), pathname: "/about-us" },
|
||||
{ id: 3, pagename: t("privacy"), pathname: "/privacy" },
|
||||
{ id: 3, pagename: t("support"), pathname: "/support" },
|
||||
{ id: 4, pagename: t("statistics"), pathname: "/statistics" },
|
||||
{ id: 5, pagename: t("news"), pathname: "/news" },
|
||||
{ id: 6, pagename: t("volunteers"), pathname: "/volunteers" },
|
||||
{ id: 4, pagename: t("support"), pathname: "/support" },
|
||||
{ id: 5, pagename: t("statistics"), pathname: "/statistics" },
|
||||
{ id: 6, pagename: t("news"), pathname: "/news" },
|
||||
{ id: 7, pagename: t("volunteers"), pathname: "/volunteers" },
|
||||
];
|
||||
|
||||
return LINKS;
|
||||
|
||||
@@ -10,6 +10,7 @@ import play_market_btn from "./icons/play-market-btn.svg";
|
||||
import { Link } from "@/shared/config/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
import NetKgTracker from "@/widgets/NetKgTracker/NetKgTracker";
|
||||
import GoogleAnalyticsWidget from "@/widgets/GoogleAnalyticsWidget/GoogleAnalyticsWidget";
|
||||
|
||||
const Footer = () => {
|
||||
const t = useTranslations("general");
|
||||
@@ -29,13 +30,16 @@ const Footer = () => {
|
||||
<ul>
|
||||
{LINKS().map((link) => (
|
||||
<li key={link.id}>
|
||||
<Link href={link.pathname} key={link.id}>
|
||||
{link.pagename}
|
||||
</Link>
|
||||
<Link href={link.pathname}>{link.pagename}</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{/* Only for production*/}
|
||||
<NetKgTracker />
|
||||
<div className="footer__logo">
|
||||
<GoogleAnalyticsWidget />
|
||||
</div>
|
||||
*
|
||||
</div>
|
||||
|
||||
<div className="footer__contacts">
|
||||
@@ -47,7 +51,7 @@ const Footer = () => {
|
||||
<li>
|
||||
{[youtube, facebook, instagram].map((net, i) => (
|
||||
<Link key={i} href="#">
|
||||
<Image src={net} alt="Net Icon" key={net} />
|
||||
<Image src={net} alt="Net Icon" />
|
||||
</Link>
|
||||
))}
|
||||
</li>
|
||||
@@ -60,7 +64,7 @@ const Footer = () => {
|
||||
<div className="footer__apps-btns">
|
||||
{[app_store_btn, play_market_btn].map((app, i) => (
|
||||
<Link key={i} href="#">
|
||||
<Image src={app} alt="App Button" key={app} />
|
||||
<Image src={app} alt="App Button" />
|
||||
</Link>
|
||||
))}
|
||||
</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;
|
||||
position: absolute;
|
||||
top: 120%;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
&__option,
|
||||
|
||||
@@ -2,17 +2,12 @@
|
||||
|
||||
.navbar {
|
||||
padding: 15px 90px;
|
||||
// padding: 15px;
|
||||
width: 100%;
|
||||
// height: 78px;
|
||||
position: fixed;
|
||||
z-index: 10005;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 4px 6px #0000001a;
|
||||
margin-bottom: 40px;
|
||||
|
||||
&__logo {
|
||||
display: flex;
|
||||
|
||||
Reference in new issue
Block a user