начало подвязки к беку
This commit is contained in:
parent
b92e54683b
commit
d9e7ba2c19
@ -2,36 +2,7 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="3a23e62a-21bd-4f51-a89e-05a6cca5b71f" name="Changes" comment="">
|
<list default="true" id="3a23e62a-21bd-4f51-a89e-05a6cca5b71f" name="Changes" comment="">
|
||||||
<change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" 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" />
|
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@ -53,7 +24,7 @@
|
|||||||
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
|
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
|
||||||
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
|
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
|
||||||
<property name="WebServerToolWindowFactoryState" value="false" />
|
<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.detected.package.eslint" value="true" />
|
||||||
<property name="node.js.selected.package.eslint" value="(autodetect)" />
|
<property name="node.js.selected.package.eslint" value="(autodetect)" />
|
||||||
<property name="nodejs_package_manager_path" value="yarn" />
|
<property name="nodejs_package_manager_path" value="yarn" />
|
||||||
@ -71,7 +42,7 @@
|
|||||||
<workItem from="1678978983245" duration="601000" />
|
<workItem from="1678978983245" duration="601000" />
|
||||||
<workItem from="1679058561119" duration="973000" />
|
<workItem from="1679058561119" duration="973000" />
|
||||||
<workItem from="1679059624759" duration="2016000" />
|
<workItem from="1679059624759" duration="2016000" />
|
||||||
<workItem from="1679061985124" duration="718000" />
|
<workItem from="1679061985124" duration="1330000" />
|
||||||
</task>
|
</task>
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
|
787
package-lock.json
generated
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/node": "^16.7.13",
|
||||||
"@types/react": "^18.0.0",
|
"@types/react": "^18.0.0",
|
||||||
"@types/react-dom": "^18.0.0",
|
"@types/react-dom": "^18.0.0",
|
||||||
|
"axios": "^1.3.4",
|
||||||
"formik": "^2.2.9",
|
"formik": "^2.2.9",
|
||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
"notistack": "^2.0.8",
|
"notistack": "^2.0.8",
|
||||||
@ -23,7 +24,8 @@
|
|||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"reconnecting-eventsource": "^1.6.2",
|
"reconnecting-eventsource": "^1.6.2",
|
||||||
"typescript": "^4.9.3",
|
"typescript": "^4.9.3",
|
||||||
"web-vitals": "^2.1.0"
|
"web-vitals": "^2.1.0",
|
||||||
|
"zustand": "^4.3.6"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "craco start",
|
"start": "craco start",
|
||||||
|
@ -2,6 +2,7 @@ import { Box, IconButton, Link, Typography, useMediaQuery, useTheme } from "@mui
|
|||||||
import CloseIcon from "@mui/icons-material/Close";
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useFormik } from "formik";
|
import { useFormik } from "formik";
|
||||||
|
import { authStore } from "@stores/makeRequest"
|
||||||
|
|
||||||
import CustomButton from "@components/CustomButton";
|
import CustomButton from "@components/CustomButton";
|
||||||
import InputTextfield from "@components/InputTextfield";
|
import InputTextfield from "@components/InputTextfield";
|
||||||
@ -37,6 +38,7 @@ export default function Signin() {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { makeRequest } = authStore()
|
||||||
const formik = useFormik<Values>({
|
const formik = useFormik<Values>({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
email: "",
|
email: "",
|
||||||
@ -44,18 +46,17 @@ export default function Signin() {
|
|||||||
},
|
},
|
||||||
validate,
|
validate,
|
||||||
onSubmit: async (values: Values) => {
|
onSubmit: async (values: Values) => {
|
||||||
const result = await apiRequestHandler.login({
|
makeRequest({
|
||||||
email: values.email,
|
url: "https://hub.pena.digital/auth/login",
|
||||||
password: values.password,
|
body: {
|
||||||
});
|
"email": values.email,
|
||||||
if (result instanceof ApiError) {
|
"password": values.password
|
||||||
enqueueSnackbar(`Error: ${result.message}`);
|
},
|
||||||
} else if (result instanceof Error) {
|
useToken: false
|
||||||
console.log(result);
|
})
|
||||||
enqueueSnackbar(`Unknown error`);
|
.catch((e:any) => {
|
||||||
} else {
|
enqueueSnackbar(e.message ? e.message : `Unknown error`)
|
||||||
// navigate("/"); // TODO
|
})
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import PenaLogo from "@components/PenaLogo";
|
|||||||
import { ApiError } from "@utils/api/types";
|
import { ApiError } from "@utils/api/types";
|
||||||
|
|
||||||
import { useSnackbar } from "notistack";
|
import { useSnackbar } from "notistack";
|
||||||
|
import {authStore} from "@stores/makeRequest";
|
||||||
|
|
||||||
interface Values {
|
interface Values {
|
||||||
login: string;
|
login: string;
|
||||||
@ -43,6 +44,7 @@ export default function Signup() {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { makeRequest } = authStore()
|
||||||
const formik = useFormik<Values>({
|
const formik = useFormik<Values>({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
login: "",
|
login: "",
|
||||||
@ -53,22 +55,20 @@ export default function Signup() {
|
|||||||
},
|
},
|
||||||
validate,
|
validate,
|
||||||
onSubmit: async (values: Values) => {
|
onSubmit: async (values: Values) => {
|
||||||
const result = await apiRequestHandler.register({
|
makeRequest({
|
||||||
email: values.email,
|
url: "https://hub.pena.digital/auth/register",
|
||||||
login: values.login,
|
body: {
|
||||||
password: values.password,
|
"login": values.email,
|
||||||
phoneNumber: values.phoneNumber,
|
"email": values.email,
|
||||||
});
|
"password": values.repeatPassword,
|
||||||
if (result instanceof ApiError) {
|
"phoneNumber": "--"
|
||||||
enqueueSnackbar(`Error: ${result.message}`);
|
},
|
||||||
return;
|
useToken: false
|
||||||
} else if (result instanceof Error) {
|
})
|
||||||
console.log(result);
|
.catch((e:any) => {
|
||||||
enqueueSnackbar(`Unknown error`);
|
console.log(e)
|
||||||
return;
|
enqueueSnackbar(e.response && e.response.data && e.response.data.message ? e.response.data.message : `Unknown error`)
|
||||||
} else {
|
})
|
||||||
// navigate("/signin"); // TODO
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
90
src/stores/makeRequest.ts
Normal file
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"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
15
src/utils/privateRoute.tsx
Normal file
15
src/utils/privateRoute.tsx
Normal file
@ -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 * 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) => {
|
export default ({ children }: any) => {
|
||||||
const location = useLocation();
|
const location = useLocation()
|
||||||
//Если пользователь авторизован, перенаправляем его в приложение. Иначе пускаем куда хотел
|
const { token } = authStore()
|
||||||
if (localStorage.getItem("AT")) {
|
console.log(token)
|
||||||
return <Navigate to="/users" state={{ from: location }} />;
|
//Если пользователь авторизован, перенаправляем его в приложение. Иначе пускаем куда хотел
|
||||||
}
|
if (token) {
|
||||||
return children;
|
return <Navigate to="/users" state={{from: location}} />
|
||||||
};
|
}
|
||||||
|
return children
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
"paths": {
|
"paths": {
|
||||||
"@root/*": ["./*"],
|
"@root/*": ["./*"],
|
||||||
"@utils/*": ["./utils/*"],
|
"@utils/*": ["./utils/*"],
|
||||||
"@components/*": ["./components/*"]
|
"@components/*": ["./components/*"],
|
||||||
|
"@stores/*": ["./stores/*"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user