Merge branch 'master' of https://git.sentientgeeks.us/Amit/mui-demo-project
This commit is contained in:
commit
54f0cdfa00
4
constant/route.constant.ts
Normal file
4
constant/route.constant.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const routes = {
|
||||||
|
LOGIN: '/login',
|
||||||
|
PRODUCTS: '/products',
|
||||||
|
};
|
@ -25,6 +25,7 @@
|
|||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"react-hook-form": "^7.52.2",
|
"react-hook-form": "^7.52.2",
|
||||||
"react-redux": "^9.1.2",
|
"react-redux": "^9.1.2",
|
||||||
|
"redux-persist": "^6.0.0",
|
||||||
"sass": "^1.77.8",
|
"sass": "^1.77.8",
|
||||||
"zod": "^3.23.8"
|
"zod": "^3.23.8"
|
||||||
},
|
},
|
||||||
|
@ -19,6 +19,7 @@ import { useRouter } from "next/navigation";
|
|||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { RootState } from "@/services/store";
|
import { RootState } from "@/services/store";
|
||||||
import { setAuthTokens, setUserDetails } from "@/services/store/authSlice";
|
import { setAuthTokens, setUserDetails } from "@/services/store/authSlice";
|
||||||
|
import { routes } from "constant/route.constant";
|
||||||
import { grey } from "@mui/material/colors";
|
import { grey } from "@mui/material/colors";
|
||||||
|
|
||||||
const loginSchema = z.object({
|
const loginSchema = z.object({
|
||||||
@ -54,8 +55,8 @@ export default function LoginPage() {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
dispatch(setUserDetails(response));
|
dispatch(setUserDetails(response));
|
||||||
setLoader(false);
|
setLoader(false)
|
||||||
router.push("/home");
|
router.push(routes.PRODUCTS);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setLoader(false);
|
setLoader(false);
|
||||||
setError("Invalid credentials");
|
setError("Invalid credentials");
|
@ -4,10 +4,12 @@ import { ThemeProvider } from "@mui/material/styles";
|
|||||||
import theme from "../theme";
|
import theme from "../theme";
|
||||||
import "./globals.scss";
|
import "./globals.scss";
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import store from "@/services/store";
|
import { PersistGate } from 'redux-persist/integration/react';
|
||||||
|
import { store, persistor } from '.././services/store';
|
||||||
import AuthGuard from "@/hoc/authGuard/authGuard";
|
import AuthGuard from "@/hoc/authGuard/authGuard";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
import { routes } from "constant/route.constant";
|
||||||
|
|
||||||
interface RootLayoutProps {
|
interface RootLayoutProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
@ -21,18 +23,20 @@ function RootLayout(props: RootLayoutProps): JSX.Element {
|
|||||||
|
|
||||||
const token = localStorage.getItem('token');
|
const token = localStorage.getItem('token');
|
||||||
if (!token) {
|
if (!token) {
|
||||||
router.push('/log-in');
|
router.push(routes.LOGIN);
|
||||||
} else {
|
} else {
|
||||||
router.replace('/home');
|
router.replace(routes.PRODUCTS);
|
||||||
}
|
}
|
||||||
}, [router])
|
}, [router])
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<body>
|
<body>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<AppRouterCacheProvider>
|
<PersistGate loading={null} persistor={persistor}>
|
||||||
<ThemeProvider theme={theme}>{children}</ThemeProvider>
|
<AppRouterCacheProvider>
|
||||||
</AppRouterCacheProvider>
|
<ThemeProvider theme={theme}>{children}</ThemeProvider>
|
||||||
|
</AppRouterCacheProvider>
|
||||||
|
</PersistGate>
|
||||||
</Provider>
|
</Provider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -22,6 +22,7 @@ import { BUILDING, GEAR } from "@/utilities/svgConstant";
|
|||||||
import LogoutIcon from "@mui/icons-material/Logout";
|
import LogoutIcon from "@mui/icons-material/Logout";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
|
import { routes } from "constant/route.constant";
|
||||||
|
|
||||||
const drawerWidth = 260;
|
const drawerWidth = 260;
|
||||||
|
|
||||||
@ -129,7 +130,7 @@ export default function DashboardWrapper(props: Props) {
|
|||||||
const logoutHandler = () => {
|
const logoutHandler = () => {
|
||||||
localStorage.removeItem("token");
|
localStorage.removeItem("token");
|
||||||
localStorage.removeItem("refreshToken");
|
localStorage.removeItem("refreshToken");
|
||||||
router.push("/log-in");
|
router.push(routes.LOGIN);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
import { routes } from 'constant/route.constant';
|
||||||
// hoc/withAuth.tsx
|
// hoc/withAuth.tsx
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
@ -10,7 +11,7 @@ const AuthGuard = (WrappedComponent: any) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const token = localStorage.getItem('token');
|
const token = localStorage.getItem('token');
|
||||||
if (!token) {
|
if (!token) {
|
||||||
router.push('/log-in');
|
router.push(routes.LOGIN);
|
||||||
}
|
}
|
||||||
}, [router]);
|
}, [router]);
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// axiosInstance.ts
|
// axiosInstance.ts
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import { routes } from 'constant/route.constant';
|
||||||
|
|
||||||
const axiosInstance = axios.create({
|
const axiosInstance = axios.create({
|
||||||
baseURL: process.env.NEXT_PUBLIC_API_URL,
|
baseURL: process.env.NEXT_PUBLIC_API_URL,
|
||||||
@ -55,7 +56,7 @@ axiosInstance.interceptors.response.use(
|
|||||||
|
|
||||||
const refreshToken = localStorage.getItem('refreshToken');
|
const refreshToken = localStorage.getItem('refreshToken');
|
||||||
if (!refreshToken) {
|
if (!refreshToken) {
|
||||||
window.location.href = '/log-in';
|
window.location.href = routes.LOGIN;
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +75,7 @@ axiosInstance.interceptors.response.use(
|
|||||||
processQueue(err, null);
|
processQueue(err, null);
|
||||||
localStorage.removeItem('token');
|
localStorage.removeItem('token');
|
||||||
localStorage.removeItem('refreshToken');
|
localStorage.removeItem('refreshToken');
|
||||||
window.location.href = '/login';
|
window.location.href = routes.LOGIN;
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
} finally {
|
} finally {
|
||||||
isRefreshing = false;
|
isRefreshing = false;
|
||||||
|
@ -1,15 +1,28 @@
|
|||||||
|
|
||||||
// store/index.ts
|
// store/index.ts
|
||||||
import { configureStore } from '@reduxjs/toolkit';
|
import { configureStore, combineReducers } from '@reduxjs/toolkit';
|
||||||
|
import { persistStore, persistReducer } from 'redux-persist';
|
||||||
|
import storage from 'redux-persist/lib/storage'; // defaults to localStorage for web
|
||||||
import authReducer from './authSlice';
|
import authReducer from './authSlice';
|
||||||
|
|
||||||
const store = configureStore({
|
const rootReducer = combineReducers({
|
||||||
reducer: {
|
auth: authReducer,
|
||||||
auth: authReducer,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type RootState = ReturnType<typeof store.getState>;
|
const persistConfig = {
|
||||||
|
key: 'root',
|
||||||
|
storage,
|
||||||
|
whitelist: ['auth'], // only auth will be persisted
|
||||||
|
};
|
||||||
|
|
||||||
|
const persistedReducer = persistReducer(persistConfig, rootReducer);
|
||||||
|
|
||||||
|
const store = configureStore({
|
||||||
|
reducer: persistedReducer,
|
||||||
|
});
|
||||||
|
|
||||||
|
const persistor = persistStore(store);
|
||||||
|
|
||||||
|
export type RootState = ReturnType<typeof rootReducer>;
|
||||||
export type AppDispatch = typeof store.dispatch;
|
export type AppDispatch = typeof store.dispatch;
|
||||||
|
|
||||||
export default store;
|
export { store, persistor };
|
||||||
|
@ -4013,12 +4013,17 @@ redent@^3.0.0:
|
|||||||
indent-string "^4.0.0"
|
indent-string "^4.0.0"
|
||||||
strip-indent "^3.0.0"
|
strip-indent "^3.0.0"
|
||||||
|
|
||||||
|
redux-persist@^6.0.0:
|
||||||
|
version "6.0.0"
|
||||||
|
resolved "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz"
|
||||||
|
integrity sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==
|
||||||
|
|
||||||
redux-thunk@^3.1.0:
|
redux-thunk@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz"
|
resolved "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz"
|
||||||
integrity sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==
|
integrity sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==
|
||||||
|
|
||||||
redux@^5.0.0, redux@^5.0.1:
|
redux@^5.0.0, redux@^5.0.1, redux@>4.0.0:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz"
|
resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz"
|
||||||
integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==
|
integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==
|
||||||
|
Loading…
x
Reference in New Issue
Block a user