|
|
|
@ -1,39 +1,43 @@
|
|
|
|
import { useReducer, useEffect } from "react";
|
|
|
|
import { useReducer, useEffect } from "react"
|
|
|
|
import { Routes, Route } from "react-router-dom";
|
|
|
|
import { Routes, Route } from "react-router-dom"
|
|
|
|
import { Toaster } from "react-hot-toast";
|
|
|
|
import { Toaster } from "react-hot-toast"
|
|
|
|
import { LOCAL_STORAGE } from "./constants";
|
|
|
|
import { QueryClient, QueryClientProvider } from "react-query"
|
|
|
|
import { reducer, initialState } from "./reducers";
|
|
|
|
|
|
|
|
import { useLocalStorageAuth } from "./hooks/auth";
|
|
|
|
|
|
|
|
import { checkHttpStatus } from "./services/helpers";
|
|
|
|
|
|
|
|
import { authSelf } from "./reducers";
|
|
|
|
|
|
|
|
import { refresh, self } from "./services/auth";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import Project from "./components/Project";
|
|
|
|
import { LOCAL_STORAGE } from "./constants"
|
|
|
|
import Profile from "./components/Profile";
|
|
|
|
import { reducer, initialState } from "./reducers"
|
|
|
|
import Signup from "./components/Auth/Signup";
|
|
|
|
import { useLocalStorageAuth } from "./hooks/auth"
|
|
|
|
import Login from "./components/Auth/Login";
|
|
|
|
import { checkHttpStatus } from "./services/helpers"
|
|
|
|
|
|
|
|
import { authSelf } from "./reducers"
|
|
|
|
|
|
|
|
import { refresh, self } from "./services/auth"
|
|
|
|
|
|
|
|
|
|
|
|
import { ProtectedRouteProps } from "./partials/ProtectedRoute";
|
|
|
|
import Project from "./components/Project"
|
|
|
|
import ProtectedRoute from "./partials/ProtectedRoute";
|
|
|
|
import Profile from "./components/Profile"
|
|
|
|
|
|
|
|
import Signup from "./components/Auth/Signup"
|
|
|
|
|
|
|
|
import Login from "./components/Auth/Login"
|
|
|
|
|
|
|
|
|
|
|
|
import "./index.css";
|
|
|
|
import { ProtectedRouteProps } from "./partials/ProtectedRoute"
|
|
|
|
|
|
|
|
import ProtectedRoute from "./partials/ProtectedRoute"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import "./index.css"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const queryClient = new QueryClient()
|
|
|
|
|
|
|
|
|
|
|
|
export default function App() {
|
|
|
|
export default function App() {
|
|
|
|
const [state, dispatch] = useReducer(reducer, initialState);
|
|
|
|
const [state, dispatch] = useReducer(reducer, initialState)
|
|
|
|
const auth = useLocalStorageAuth();
|
|
|
|
const auth = useLocalStorageAuth()
|
|
|
|
const isAuthenticated = !!(auth && Object.keys(auth).length);
|
|
|
|
const isAuthenticated = !!(auth && Object.keys(auth).length)
|
|
|
|
|
|
|
|
|
|
|
|
const defaultProtectedRouteProps: Omit<ProtectedRouteProps, 'outlet'> = {
|
|
|
|
const defaultProtectedRouteProps: Omit<ProtectedRouteProps, "outlet"> = {
|
|
|
|
isAuthenticated: isAuthenticated,
|
|
|
|
isAuthenticated: isAuthenticated,
|
|
|
|
authenticationPath: '/login',
|
|
|
|
authenticationPath: "/login"
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
useEffect(() => {
|
|
|
|
if (isAuthenticated) {
|
|
|
|
if (isAuthenticated) {
|
|
|
|
self()
|
|
|
|
self()
|
|
|
|
.then(checkHttpStatus)
|
|
|
|
.then(checkHttpStatus)
|
|
|
|
.then(data => {
|
|
|
|
.then(data => {
|
|
|
|
dispatch(authSelf(data));
|
|
|
|
dispatch(authSelf(data))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.catch(err => {
|
|
|
|
.catch(err => {
|
|
|
|
// since auth is set in localstorage,
|
|
|
|
// since auth is set in localstorage,
|
|
|
|
@ -41,44 +45,63 @@ export default function App() {
|
|
|
|
// on error clear localstorage
|
|
|
|
// on error clear localstorage
|
|
|
|
if (err.status === 401) {
|
|
|
|
if (err.status === 401) {
|
|
|
|
err.text().then((text: string) => {
|
|
|
|
err.text().then((text: string) => {
|
|
|
|
const textObj = JSON.parse(text);
|
|
|
|
const textObj = JSON.parse(text)
|
|
|
|
if (textObj.code === "user_not_found") {
|
|
|
|
if (textObj.code === "user_not_found") {
|
|
|
|
localStorage.removeItem(LOCAL_STORAGE);
|
|
|
|
localStorage.removeItem(LOCAL_STORAGE)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
refresh()
|
|
|
|
refresh()
|
|
|
|
.then(checkHttpStatus)
|
|
|
|
.then(checkHttpStatus)
|
|
|
|
.then(data => {
|
|
|
|
.then(data => {
|
|
|
|
const localData = localStorage.getItem(LOCAL_STORAGE);
|
|
|
|
const localData = localStorage.getItem(LOCAL_STORAGE)
|
|
|
|
|
|
|
|
|
|
|
|
if (localData) {
|
|
|
|
if (localData) {
|
|
|
|
const localDataParsed = JSON.parse(localData);
|
|
|
|
const localDataParsed = JSON.parse(localData)
|
|
|
|
if (localDataParsed && Object.keys(localDataParsed).length) {
|
|
|
|
if (localDataParsed && Object.keys(localDataParsed).length) {
|
|
|
|
localDataParsed.access_token = data.access;
|
|
|
|
localDataParsed.access_token = data.access
|
|
|
|
localStorage.setItem(LOCAL_STORAGE, JSON.stringify(localDataParsed))
|
|
|
|
localStorage.setItem(
|
|
|
|
|
|
|
|
LOCAL_STORAGE,
|
|
|
|
|
|
|
|
JSON.stringify(localDataParsed)
|
|
|
|
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.catch(err => {
|
|
|
|
.catch(err => {
|
|
|
|
localStorage.removeItem(LOCAL_STORAGE);
|
|
|
|
localStorage.removeItem(LOCAL_STORAGE)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, [dispatch, isAuthenticated]);
|
|
|
|
}, [dispatch, isAuthenticated])
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
|
|
|
|
<QueryClientProvider client={queryClient}>
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
<Toaster />
|
|
|
|
<Toaster />
|
|
|
|
<Routes>
|
|
|
|
<Routes>
|
|
|
|
<Route path="/" element={<Project dispatch={dispatch} state={state} />} />
|
|
|
|
<Route
|
|
|
|
<Route path="/projects/:uuid" element={<Project dispatch={dispatch} state={state} />} />
|
|
|
|
path="/"
|
|
|
|
|
|
|
|
element={<Project dispatch={dispatch} state={state} />}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
<Route
|
|
|
|
|
|
|
|
path="/projects/:uuid"
|
|
|
|
|
|
|
|
element={<Project dispatch={dispatch} state={state} />}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<Route path="/profile" element={<ProtectedRoute {...defaultProtectedRouteProps} outlet={<Profile dispatch={dispatch} state={state} />} />} />
|
|
|
|
<Route
|
|
|
|
|
|
|
|
path="/profile"
|
|
|
|
|
|
|
|
element={
|
|
|
|
|
|
|
|
<ProtectedRoute
|
|
|
|
|
|
|
|
{...defaultProtectedRouteProps}
|
|
|
|
|
|
|
|
outlet={<Profile dispatch={dispatch} state={state} />}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/>
|
|
|
|
<Route path="/signup" element={<Signup dispatch={dispatch} />} />
|
|
|
|
<Route path="/signup" element={<Signup dispatch={dispatch} />} />
|
|
|
|
<Route path="/login" element={<Login dispatch={dispatch} />} />
|
|
|
|
<Route path="/login" element={<Login dispatch={dispatch} />} />
|
|
|
|
</Routes>
|
|
|
|
</Routes>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
</QueryClientProvider>
|
|
|
|
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|