forked from Transparency/kgroad-frontend2
remade folder structure, fixed problem with build
This commit is contained in:
1 parent
60b136effd
commit
1468fac1cc
39 files changed
+436
-117
No files matched your search
@@ -1,21 +0,0 @@
|
||||
import "./globals.scss";
|
||||
import "./fonts.scss";
|
||||
import "./App.scss";
|
||||
import Footer from "@/widgets/Footer/Footer";
|
||||
import Navbar from "@/widgets/Navbar/Navbar";
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<Navbar />
|
||||
<div className="app">{children}</div>
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
"use client";
|
||||
|
||||
import { SessionProvider } from "next-auth/react";
|
||||
|
||||
export const Providers = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
return <SessionProvider>{children}</SessionProvider>;
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
const AboutUs = () => {
|
||||
return <div>AboutUs</div>;
|
||||
};
|
||||
|
||||
export default AboutUs;
|
||||
@@ -0,0 +1,6 @@
|
||||
import NextAuth from "next-auth";
|
||||
import { authConfig } from "@/shared/config/authConfig";
|
||||
|
||||
const handler = NextAuth(authConfig);
|
||||
|
||||
export { handler as GET, handler as POST };
|
||||
@@ -1,9 +0,0 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@200;300;400;500;600;700;800;900&display=swap");
|
||||
|
||||
@import url("https://fonts.cdnfonts.com/css/arial");
|
||||
|
||||
@import url("../shared/fonts/TildaSans.css");
|
||||
|
||||
* {
|
||||
font-family: Tilda Sans;
|
||||
}
|
||||
+19
-14
@@ -1,25 +1,30 @@
|
||||
@import url("https://fonts.cdnfonts.com/css/inter");
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: "Tilda Sans";
|
||||
}
|
||||
|
||||
button,
|
||||
a {
|
||||
cursor: pointer;
|
||||
color: black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
text-decoration: none;
|
||||
a,
|
||||
input {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol,
|
||||
li {
|
||||
list-style-type: none;
|
||||
list-style: none;
|
||||
button {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
input {
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
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";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Kg Road",
|
||||
description: "Road in KR",
|
||||
};
|
||||
|
||||
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>
|
||||
);
|
||||
}
|
||||
@@ -1,24 +1,30 @@
|
||||
import "./Home.scss";
|
||||
import dynamic from "next/dynamic";
|
||||
import Header from "@/widgets/Header/Header";
|
||||
import StatisticsSection from "@/widgets/StatisticsSection/StatisticsSection";
|
||||
import MapSection from "@/widgets/MapSection/MapSection";
|
||||
import RatingSection from "@/widgets/RatingSection/RatingSection";
|
||||
import NewsSection from "@/widgets/NewsSection/NewsSection";
|
||||
|
||||
const Home = ({
|
||||
const DynamicMap = dynamic(
|
||||
() => import("@/widgets/MapSection/MapSection"),
|
||||
{
|
||||
ssr: false,
|
||||
}
|
||||
);
|
||||
|
||||
const Home = async ({
|
||||
searchParams,
|
||||
}: {
|
||||
searchParams: {
|
||||
"тип-дороги": string;
|
||||
"поиск-на-карте": string;
|
||||
"поиск-рейтинг": string;
|
||||
["тип-дороги"]: string;
|
||||
["поиск-на-карте"]: string;
|
||||
["поиск-рейтинг"]: string;
|
||||
};
|
||||
}) => {
|
||||
return (
|
||||
<div className="home">
|
||||
<Header />
|
||||
<StatisticsSection />
|
||||
<MapSection
|
||||
<DynamicMap
|
||||
categories={searchParams["тип-дороги"]}
|
||||
queryMap={searchParams["поиск-на-карте"]}
|
||||
queryRating={searchParams["поиск-рейтинг"]}
|
||||
@@ -0,0 +1,5 @@
|
||||
const Profile = () => {
|
||||
return <div>Profile</div>;
|
||||
};
|
||||
|
||||
export default Profile;
|
||||
@@ -0,0 +1,8 @@
|
||||
import React from "react";
|
||||
import classes from "./styles.module.scss";
|
||||
|
||||
const SignIn = () => {
|
||||
return <div className={classes.root}>SignIn</div>;
|
||||
};
|
||||
|
||||
export default SignIn;
|
||||
File renamed without changes.
@@ -1,2 +0,0 @@
|
||||
export const baseAPI =
|
||||
"https://api.kgroaduat.fishrungames.com/api/v1";
|
||||
@@ -0,0 +1,7 @@
|
||||
import axios from "axios";
|
||||
|
||||
const API_URL = process.env["NEXT_PUBLIC_BASE_API"];
|
||||
|
||||
export const apiInstance = axios.create({
|
||||
baseURL: API_URL,
|
||||
});
|
||||
@@ -0,0 +1,89 @@
|
||||
import axios from "axios";
|
||||
import { AuthOptions } from "next-auth";
|
||||
import { JWT } from "next-auth/jwt";
|
||||
import CredentialsProvider from "next-auth/providers/credentials";
|
||||
|
||||
interface IToken {
|
||||
access: string;
|
||||
}
|
||||
|
||||
const refreshToken = async (token: JWT): Promise<JWT> => {
|
||||
const data = {
|
||||
refresh: token.refresh_token,
|
||||
};
|
||||
|
||||
const response = await axios.post<IToken>(
|
||||
"https://api.kgroaduat.fishrungames.com/api/v1/token/refresh/",
|
||||
data
|
||||
);
|
||||
|
||||
return {
|
||||
...token,
|
||||
access_token: response.data.access,
|
||||
};
|
||||
};
|
||||
|
||||
export const authConfig: AuthOptions = {
|
||||
providers: [
|
||||
CredentialsProvider({
|
||||
name: "Credentials",
|
||||
|
||||
credentials: {
|
||||
email: {
|
||||
label: "Email",
|
||||
type: "text",
|
||||
placeholder: "jsmith@example.com",
|
||||
},
|
||||
password: { label: "Password", type: "password" },
|
||||
},
|
||||
|
||||
async authorize(credentials, req) {
|
||||
if (!credentials?.email || !credentials?.password)
|
||||
return null;
|
||||
|
||||
const { email, password } = credentials as any;
|
||||
|
||||
const res = await fetch(
|
||||
"https://api.kgroaduat.fishrungames.com/api/v1/users/login/",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
password,
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
if (res.status.toString()[0] === "4") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const user = await res.json();
|
||||
return user;
|
||||
},
|
||||
}),
|
||||
],
|
||||
pages: {
|
||||
signIn: "/sign-in",
|
||||
},
|
||||
session: {
|
||||
strategy: "jwt",
|
||||
},
|
||||
callbacks: {
|
||||
async jwt({ token, user }) {
|
||||
if (user) return { ...token, ...user };
|
||||
|
||||
return refreshToken(token);
|
||||
},
|
||||
|
||||
async session({ token, session }) {
|
||||
session.access_token = token.access_token;
|
||||
session.refresh_token = token.refresh_token;
|
||||
|
||||
return session;
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -5,4 +5,5 @@
|
||||
url("TildaSans-Black.woff2") format("woff2"),
|
||||
url("TildaSans-Black.woff") format("woff");
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
}
|
||||
@@ -5,4 +5,5 @@
|
||||
url("TildaSans-Regular.woff2") format("woff2"),
|
||||
url("TildaSans-Regular.woff") format("woff");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@@ -3,5 +3,5 @@
|
||||
@import "./TildaSans-Medium/TildaSans-Medium.css";
|
||||
@import "./TildaSans-Semibold/TildaSans-Semibold.css";
|
||||
@import "./TildaSans-Bold/TildaSans-Bold.css";
|
||||
@import "./TildaSans-ExtraBold/TildaSans-ExtraBold.css";
|
||||
@import "./TildaSans-Extrabold/TildaSans-Extrabold.css";
|
||||
@import "./TildaSans-Black/TildaSans-Black.css";
|
||||
@@ -10,7 +10,7 @@
|
||||
height: fit-content;
|
||||
color: white;
|
||||
justify-content: flex-start;
|
||||
font-family: "Inter";
|
||||
font-family: "Inter", sans-serif;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ const Footer = () => {
|
||||
<h4>Навигация</h4>
|
||||
<ul>
|
||||
{LINKS.map((link) => (
|
||||
<li>
|
||||
<li key={link.id}>
|
||||
<Link href={link.pathname} key={link.id}>
|
||||
{link.pagename}
|
||||
</Link>
|
||||
@@ -34,8 +34,8 @@ const Footer = () => {
|
||||
<li>namename@gmail.com</li>
|
||||
<li>+09646895467</li>
|
||||
<li>
|
||||
{[youtube, facebook, instagram].map((net) => (
|
||||
<Link href="#">
|
||||
{[youtube, facebook, instagram].map((net, i) => (
|
||||
<Link key={i} href="#">
|
||||
<Image src={net} alt="Net Icon" key={net} />
|
||||
</Link>
|
||||
))}
|
||||
@@ -46,8 +46,8 @@ const Footer = () => {
|
||||
<div className="footer__apps">
|
||||
<h4>Скачивай наше приложение</h4>
|
||||
<div className="footer__apps-btns">
|
||||
{[app_store_btn, play_market_btn].map((app) => (
|
||||
<Link href="#">
|
||||
{[app_store_btn, play_market_btn].map((app, i) => (
|
||||
<Link key={i} href="#">
|
||||
<Image src={app} alt="App Button" key={app} />
|
||||
</Link>
|
||||
))}
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
border-radius: 15px;
|
||||
background-color: #fff;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { baseAPI } from "@/shared/api/baseAPI";
|
||||
import { apiInstance } from "@/shared/config/apiConfig";
|
||||
import { IFetch } from "@/shared/types/fetch-type";
|
||||
import { IList } from "@/shared/types/list-type";
|
||||
import { IReport } from "@/shared/types/report-type";
|
||||
import axios from "axios";
|
||||
import { create } from "zustand";
|
||||
|
||||
interface IFetchReports extends IList {
|
||||
@@ -27,8 +26,8 @@ export const useMapStore = create<IMapStore>((set) => ({
|
||||
try {
|
||||
set({ isLoading: true });
|
||||
|
||||
const response = await axios.get<IFetchReports>(
|
||||
`${baseAPI}/report/?category=${categories}`
|
||||
const response = await apiInstance.get<IFetchReports>(
|
||||
`/report/?category=${categories}`
|
||||
);
|
||||
|
||||
set({ data: response.data });
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
background-color: #fff;
|
||||
|
||||
&__links {
|
||||
height: 60%;
|
||||
height: 40%;
|
||||
display: flex;
|
||||
gap: 60px;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { baseAPI } from "@/shared/api/baseAPI";
|
||||
import { apiInstance } from "@/shared/config/apiConfig";
|
||||
import { IList } from "@/shared/types/list-type";
|
||||
import { INews } from "@/shared/types/news-type";
|
||||
import axios, { AxiosError } from "axios";
|
||||
@@ -9,8 +9,7 @@ interface IFetchNews extends IList {
|
||||
|
||||
export const getNews = async () => {
|
||||
try {
|
||||
const data = (await axios.get<IFetchNews>(`${baseAPI}/news/`))
|
||||
.data;
|
||||
const data = (await apiInstance.get<IFetchNews>("/news/")).data;
|
||||
|
||||
return data.results.slice(0, 4);
|
||||
} catch (error: unknown) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { baseAPI } from "@/shared/api/baseAPI";
|
||||
import { apiInstance } from "@/shared/config/apiConfig";
|
||||
import { IFetch } from "@/shared/types/fetch-type";
|
||||
import { IList } from "@/shared/types/list-type";
|
||||
import { IReport } from "@/shared/types/report-type";
|
||||
@@ -27,9 +27,8 @@ export const useRatingStore = create<IRatingStore>((set) => ({
|
||||
try {
|
||||
set({ isLoading: true });
|
||||
|
||||
const data = (
|
||||
await axios.get<IFetchReports>(`${baseAPI}/report/`)
|
||||
).data;
|
||||
const data = (await apiInstance.get<IFetchReports>("/report/"))
|
||||
.data;
|
||||
|
||||
const searched = data.results.filter((rating) => {
|
||||
return rating.location.some((location) => {
|
||||
|
||||
@@ -20,7 +20,7 @@ const StatisticsSection = async () => {
|
||||
<section className="statistics-section">
|
||||
<ul className="statistics-section__list">
|
||||
{mockArray.map((cat) => (
|
||||
<li>
|
||||
<li key={cat.category}>
|
||||
<p>{ROAD_TYPES_STATS[cat.category]}</p>
|
||||
<span>{cat.count}</span>
|
||||
</li>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { baseAPI } from "@/shared/api/baseAPI";
|
||||
import axios, { AxiosError } from "axios";
|
||||
import { apiInstance } from "@/shared/config/apiConfig";
|
||||
import { AxiosError } from "axios";
|
||||
|
||||
interface IStatsCount {
|
||||
category: number;
|
||||
@@ -10,8 +10,8 @@ export const statiscsSectionStore = () => {
|
||||
let errorMessage = "";
|
||||
async function getStatsCount() {
|
||||
try {
|
||||
const response = await axios.get<IStatsCount[]>(
|
||||
`${baseAPI}/report/category_count/`
|
||||
const response = await apiInstance.get<IStatsCount[]>(
|
||||
"/report/category_count/"
|
||||
);
|
||||
|
||||
return response.data;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export { default } from "next-auth/middleware";
|
||||
|
||||
export const config = { matcher: ["/profile"] };
|
||||
Reference in new issue
Block a user