начало подвязки к беку

This commit is contained in:
krokodilka 2023-03-19 18:26:39 +03:00
parent b92e54683b
commit d9e7ba2c19
10 changed files with 7762 additions and 6800 deletions

@ -2,36 +2,7 @@
<project version="4">
<component name="ChangeListManager">
<list default="true" id="3a23e62a-21bd-4f51-a89e-05a6cca5b71f" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/craco.config.js" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/assets/Icons/ZeroIcons.svg" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/assets/Icons/tariffs-time/Infinity.svg" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/assets/Icons/tariffs-time/NineIcons.svg" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/assets/Icons/tariffs-time/OneIcons.svg" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/assets/Icons/tariffs-time/SixIcons.svg" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/assets/Icons/tariffs-time/ThreeIcons.svg" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/assets/Icons/tariffs-volume/FiveIcons.svg" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/assets/Icons/tariffs-volume/FourIcons.svg" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/assets/Icons/tariffs-volume/OneIcons.svg" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/assets/Icons/tariffs-volume/ThreeIcons.svg" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/assets/Icons/tariffs-volume/TwoIcons.svg" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/components/icons/CalendarIcon.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/lib/IconsCreate.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/pages/Tariffs/FreeTariffCard.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/pages/Tariffs/TariffCardTimeAndVolume.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/pages/Tariffs/TariffsTime.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/pages/Tariffs/TariffsVolume.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/tsconfig.extend.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/package-lock.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/App.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/App.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/components/icons/CustomIcon.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/icons/CustomIcon.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/CustomTariff/TariffConstructorCard.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/CustomTariff/TariffConstructorCard.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/Tariffs/CalendarIcon.tsx" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/Tariffs/TariffCard.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/Tariffs/TariffCard.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/Tariffs/Tariffs.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/Tariffs/Tariffs.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/utils/decorators.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/utils/decorators.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tsconfig.json" beforeDir="false" afterPath="$PROJECT_DIR$/tsconfig.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -53,7 +24,7 @@
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../amo" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.selected.package.eslint" value="(autodetect)" />
<property name="nodejs_package_manager_path" value="yarn" />
@ -71,7 +42,7 @@
<workItem from="1678978983245" duration="601000" />
<workItem from="1679058561119" duration="973000" />
<workItem from="1679059624759" duration="2016000" />
<workItem from="1679061985124" duration="718000" />
<workItem from="1679061985124" duration="1330000" />
</task>
<servers />
</component>

787
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -14,6 +14,7 @@
"@types/node": "^16.7.13",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"axios": "^1.3.4",
"formik": "^2.2.9",
"isomorphic-fetch": "^3.0.0",
"notistack": "^2.0.8",
@ -23,7 +24,8 @@
"react-scripts": "5.0.1",
"reconnecting-eventsource": "^1.6.2",
"typescript": "^4.9.3",
"web-vitals": "^2.1.0"
"web-vitals": "^2.1.0",
"zustand": "^4.3.6"
},
"scripts": {
"start": "craco start",

@ -2,6 +2,7 @@ import { Box, IconButton, Link, Typography, useMediaQuery, useTheme } from "@mui
import CloseIcon from "@mui/icons-material/Close";
import { useNavigate } from "react-router-dom";
import { useFormik } from "formik";
import { authStore } from "@stores/makeRequest"
import CustomButton from "@components/CustomButton";
import InputTextfield from "@components/InputTextfield";
@ -37,6 +38,7 @@ export default function Signin() {
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
const navigate = useNavigate();
const { makeRequest } = authStore()
const formik = useFormik<Values>({
initialValues: {
email: "",
@ -44,18 +46,17 @@ export default function Signin() {
},
validate,
onSubmit: async (values: Values) => {
const result = await apiRequestHandler.login({
email: values.email,
password: values.password,
});
if (result instanceof ApiError) {
enqueueSnackbar(`Error: ${result.message}`);
} else if (result instanceof Error) {
console.log(result);
enqueueSnackbar(`Unknown error`);
} else {
// navigate("/"); // TODO
}
makeRequest({
url: "https://hub.pena.digital/auth/login",
body: {
"email": values.email,
"password": values.password
},
useToken: false
})
.catch((e:any) => {
enqueueSnackbar(e.message ? e.message : `Unknown error`)
})
},
});

@ -10,6 +10,7 @@ import PenaLogo from "@components/PenaLogo";
import { ApiError } from "@utils/api/types";
import { useSnackbar } from "notistack";
import {authStore} from "@stores/makeRequest";
interface Values {
login: string;
@ -43,6 +44,7 @@ export default function Signup() {
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
const navigate = useNavigate();
const { makeRequest } = authStore()
const formik = useFormik<Values>({
initialValues: {
login: "",
@ -53,22 +55,20 @@ export default function Signup() {
},
validate,
onSubmit: async (values: Values) => {
const result = await apiRequestHandler.register({
email: values.email,
login: values.login,
password: values.password,
phoneNumber: values.phoneNumber,
});
if (result instanceof ApiError) {
enqueueSnackbar(`Error: ${result.message}`);
return;
} else if (result instanceof Error) {
console.log(result);
enqueueSnackbar(`Unknown error`);
return;
} else {
// navigate("/signin"); // TODO
}
makeRequest({
url: "https://hub.pena.digital/auth/register",
body: {
"login": values.email,
"email": values.email,
"password": values.repeatPassword,
"phoneNumber": "--"
},
useToken: false
})
.catch((e:any) => {
console.log(e)
enqueueSnackbar(e.response && e.response.data && e.response.data.message ? e.response.data.message : `Unknown error`)
})
},
});

90
src/stores/makeRequest.ts Normal file

@ -0,0 +1,90 @@
import axios from 'axios'
import { create } from "zustand";
import { persist } from "zustand/middleware";
type Token = string
interface AuthStore {
token: Token
// setToken: () => Promise;
}
interface FirstRequest {
method?: string
url: string
body?: unknown
useToken?: boolean
contentType?: boolean
}
export const authStore = create<any>()(
persist(
(set, get) => ({
token: "",
makeRequest: (props:FirstRequest) => {
const newProps = {...props, HC: (newToken:Token) => set({ token: newToken }),token: get().token}
return (
new Promise(async (resolve, reject) => {
await makeRequest(newProps)
.then(r => resolve(r))
.catch(r => reject(r))
})
)
},
clearToken: () => set({token: ""})
}),
{
name: "token"
}
)
);
interface MakeRequest extends FirstRequest {
HC: (newToken:Token) => void
token:Token
}
function makeRequest({
method = "post",
url,
body,
useToken = true,
contentType = false,
HC,
token
}: MakeRequest) {
//В случае 401 рефреш должен попробовать вызваться 1 раз
let counterRefresh = true
let headers: any = {}
if (useToken) headers["Authorization"] = token
if (contentType) headers["Content-Type"] = "application/json"
return axios({
url: url,
method: method,
headers: headers,
data: body
})
.then(response => {
if (response.data && response.data.accessToken) {
HC(response.data.accessToken)
}
return response
})
.catch(error => {
if (error.response.status == 401 && counterRefresh) {
refresh().then(response => {
if (response.data && response.data.accessToken) HC(response.data.accessToken)
counterRefresh = false
})
} else {
throw error
}
throw error
})
}
function refresh() {
return axios("https://admin.pena.digital/auth/refresh", {
headers: {
"Authorization": localStorage.getItem('AT'),
"Content-Type": "application/json"
}
})
}

@ -0,0 +1,15 @@
import * as React from "react";
import { useLocation, Navigate } from 'react-router-dom'
import {authStore} from "@stores/makeRequest";
export default ({ children }: any) => {
const location = useLocation()
const { token } = authStore()
console.log(token)
//Если пользователь авторизован, перенаправляем его на нужный путь. Иначе выкидываем в регистрацию
if (token) {
return children
}
return <Navigate to="/" state={{from: location}} />
}

@ -1,11 +1,15 @@
import * as React from "react";
import { useLocation, Navigate } from "react-router-dom";
import { useLocation, Navigate } from 'react-router-dom'
import {authStore} from "@stores/makeRequest";
export default ({ children }: any) => {
const location = useLocation();
//Если пользователь авторизован, перенаправляем его в приложение. Иначе пускаем куда хотел
if (localStorage.getItem("AT")) {
return <Navigate to="/users" state={{ from: location }} />;
}
return children;
};
const location = useLocation()
const { token } = authStore()
console.log(token)
//Если пользователь авторизован, перенаправляем его в приложение. Иначе пускаем куда хотел
if (token) {
return <Navigate to="/users" state={{from: location}} />
}
return children
}

@ -4,7 +4,8 @@
"paths": {
"@root/*": ["./*"],
"@utils/*": ["./utils/*"],
"@components/*": ["./components/*"]
"@components/*": ["./components/*"],
"@stores/*": ["./stores/*"]
}
}
}

13551
yarn.lock

File diff suppressed because it is too large Load Diff