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
@@ -5,3 +5,13 @@ const API_URL = process.env["NEXT_PUBLIC_BASE_API"];
|
||||
export const apiInstance = axios.create({
|
||||
baseURL: API_URL,
|
||||
});
|
||||
|
||||
export const authInstanse = (access_token: string) => {
|
||||
return axios.create({
|
||||
baseURL: API_URL,
|
||||
headers: {
|
||||
Authorization: `Bearer ${access_token}`,
|
||||
},
|
||||
method: "",
|
||||
});
|
||||
};
|
||||
@@ -2,24 +2,45 @@ import axios from "axios";
|
||||
import { AuthOptions } from "next-auth";
|
||||
import { JWT } from "next-auth/jwt";
|
||||
import CredentialsProvider from "next-auth/providers/credentials";
|
||||
import { apiInstance } from "./apiConfig";
|
||||
import { IRefresh, ITokens } from "../types/token-type";
|
||||
import GoogleProvider from "next-auth/providers/google";
|
||||
|
||||
interface IToken {
|
||||
access: string;
|
||||
}
|
||||
const verifyToken = async (access_token: string) => {
|
||||
const res = await apiInstance.post("/token/verify/", {
|
||||
token: access_token,
|
||||
});
|
||||
|
||||
if ([200, 201].includes(res.status)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const refreshToken = async (token: JWT): Promise<JWT> => {
|
||||
const data = {
|
||||
refresh: token.refresh_token,
|
||||
};
|
||||
// const date = new Date().toLocaleTimeString();
|
||||
// const expire = new Date(token.expires_in).toLocaleTimeString();
|
||||
|
||||
const response = await axios.post<IToken>(
|
||||
"https://api.kgroaduat.fishrungames.com/api/v1/token/refresh/",
|
||||
const verify = await verifyToken(token.access_token);
|
||||
|
||||
if (verify)
|
||||
return {
|
||||
...token,
|
||||
};
|
||||
|
||||
const response = await apiInstance.post<IRefresh>(
|
||||
"/users/refresh/",
|
||||
data
|
||||
);
|
||||
|
||||
return {
|
||||
...token,
|
||||
access_token: response.data.access,
|
||||
expires_in: response.data.expires_at,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -27,7 +48,6 @@ export const authConfig: AuthOptions = {
|
||||
providers: [
|
||||
CredentialsProvider({
|
||||
name: "Credentials",
|
||||
|
||||
credentials: {
|
||||
email: {
|
||||
label: "Email",
|
||||
@@ -36,35 +56,30 @@ export const authConfig: AuthOptions = {
|
||||
},
|
||||
password: { label: "Password", type: "password" },
|
||||
},
|
||||
|
||||
async authorize(credentials, req) {
|
||||
if (!credentials?.email || !credentials?.password)
|
||||
return null;
|
||||
|
||||
const { email, password } = credentials as any;
|
||||
const data = {
|
||||
email,
|
||||
password,
|
||||
};
|
||||
|
||||
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,
|
||||
}),
|
||||
}
|
||||
);
|
||||
const res = await apiInstance.post("/users/login/", data);
|
||||
|
||||
if (res.status.toString()[0] === "4") {
|
||||
if (![200, 201].includes(res.status)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const user = await res.json();
|
||||
const user = res.data;
|
||||
return user;
|
||||
},
|
||||
}),
|
||||
GoogleProvider({
|
||||
clientId: process.env.CLIENT_ID as string,
|
||||
clientSecret: process.env.CLIENT_SECRET as string,
|
||||
}),
|
||||
],
|
||||
pages: {
|
||||
signIn: "/sign-in",
|
||||
@@ -73,9 +88,39 @@ export const authConfig: AuthOptions = {
|
||||
strategy: "jwt",
|
||||
},
|
||||
callbacks: {
|
||||
async jwt({ token, user }) {
|
||||
async signIn({ account, profile, user }) {
|
||||
if (!profile?.email) {
|
||||
throw new Error("No Profile");
|
||||
}
|
||||
|
||||
if (account?.provider === "google") {
|
||||
const data = {
|
||||
auth_token: account?.id_token,
|
||||
};
|
||||
|
||||
const res = await apiInstance.post<ITokens>(
|
||||
"/users/google/",
|
||||
data
|
||||
);
|
||||
|
||||
if (![200, 201].includes(res.status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
user.access_token = res.data.access_token;
|
||||
user.refresh_token = res.data.refresh_token;
|
||||
user.expires_in = res.data.expires_in;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
async jwt({ token, user, account }) {
|
||||
if (user) return { ...token, ...user };
|
||||
|
||||
if (token.exp) {
|
||||
return token;
|
||||
}
|
||||
|
||||
return refreshToken(token);
|
||||
},
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { createSharedPathnamesNavigation } from "next-intl/navigation";
|
||||
|
||||
export const locales = ["en", "ru", "kg"] as const;
|
||||
export const localePrefix = "always"; // Default
|
||||
|
||||
export const { Link, redirect, usePathname, useRouter } =
|
||||
createSharedPathnamesNavigation({ locales, localePrefix });
|
||||
@@ -1,5 +1,5 @@
|
||||
export interface ILocation {
|
||||
id: 4;
|
||||
id: number;
|
||||
latitude: string;
|
||||
longitude: string;
|
||||
address: string;
|
||||
|
||||
@@ -3,3 +3,8 @@ export interface ITokens {
|
||||
access_token: string;
|
||||
expires_in: string;
|
||||
}
|
||||
|
||||
export interface IRefresh {
|
||||
access: string;
|
||||
expires_at: string;
|
||||
}
|
||||
@@ -1,7 +1,23 @@
|
||||
export const LINKS = [
|
||||
{ id: 1, pagename: "Главная", pathname: "/" },
|
||||
{ id: 2, pagename: "О нас", pathname: "/about-us" },
|
||||
{ id: 3, pagename: "Статистика", pathname: "/statistics" },
|
||||
{ id: 4, pagename: "Новости", pathname: "/news" },
|
||||
{ id: 5, pagename: "Волонтеры", pathname: "/volunteers" },
|
||||
];
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export const LINKS = () => {
|
||||
const t = useTranslations("navigation");
|
||||
|
||||
const LINKS = [
|
||||
{ id: 1, pagename: t("home"), pathname: "/" },
|
||||
{ id: 2, pagename: t("about_us"), pathname: "/about-us" },
|
||||
{ id: 3, pagename: t("statistics"), pathname: "/statistics" },
|
||||
{ id: 4, pagename: t("news"), pathname: "/news" },
|
||||
{ id: 5, pagename: t("volunteers"), pathname: "/volunteers" },
|
||||
];
|
||||
|
||||
return LINKS;
|
||||
};
|
||||
|
||||
// export const LINKS = [
|
||||
// { id: 1, pagename: "Главная", pathname: "/" },
|
||||
// { id: 2, pagename: "О нас", pathname: "/about-us" },
|
||||
// { id: 3, pagename: "Статистика", pathname: "/statistics" },
|
||||
// { id: 4, pagename: "Новости", pathname: "/news" },
|
||||
// { id: 5, pagename: "Волонтеры", pathname: "/volunteers" },
|
||||
// ];
|
||||
@@ -0,0 +1,14 @@
|
||||
export const MONTHS: Record<string, string> = {
|
||||
"01": "Январь",
|
||||
"02": "Февраль",
|
||||
"03": "Март",
|
||||
"04": "Апрель",
|
||||
"05": "Май",
|
||||
"06": "Июнь",
|
||||
"07": "Июль",
|
||||
"08": "Август",
|
||||
"09": "Сентябрь",
|
||||
"10": "Октябрь",
|
||||
"11": "Ноябрь",
|
||||
"12": "Декабрь",
|
||||
};
|
||||
@@ -1,20 +1,4 @@
|
||||
export const ROAD_TYPES_STATS: Record<number, string> = {
|
||||
1: "Разбитых дорог",
|
||||
2: "Очагов аварийности",
|
||||
3: "Локальных дефектов",
|
||||
4: "В планах ремонта",
|
||||
5: "Отремонтировано",
|
||||
6: "Локальных дефектов исправлено",
|
||||
};
|
||||
|
||||
export const ROAD_TYPES: Record<number, string> = {
|
||||
1: "Разбитая дорога",
|
||||
2: "Очаг аварийности",
|
||||
3: "Локальный дефект",
|
||||
4: "В планах ремонта",
|
||||
5: "Отремонтировано",
|
||||
6: "Локальный дефект исправлен",
|
||||
};
|
||||
import { getTranslations } from "next-intl/server";
|
||||
|
||||
export const ROAD_TYPES_COLORS: Record<number, string> = {
|
||||
1: "rgb(230, 68, 82)",
|
||||
|
||||
Reference in new issue
Block a user