Merge branch 'master' of https://git.sentientgeeks.us/Amit/mui-demo-project
This commit is contained in:
commit
0811f3a797
@ -1,4 +1,4 @@
|
|||||||
"use client"
|
"use client";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styles from "./loginPage.module.scss";
|
import styles from "./loginPage.module.scss";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
@ -8,12 +8,12 @@ import { UTILITY_CONSTANT } from "@/utilities/utilityConstant";
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import CustomizedInputsStyled from "@/ui/CustomizedInputsStyled";
|
import CustomizedInputsStyled from "@/ui/CustomizedInputsStyled";
|
||||||
import CustomizedButtons from "@/ui/customizedButtons";
|
import CustomizedButtons from "@/ui/customizedButtons";
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from "react-hook-form";
|
||||||
import { z } from 'zod';
|
import { z } from "zod";
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useState } from 'react';
|
import { useState } from "react";
|
||||||
import { loginApi } from "@/services/api/loginApi";
|
import { loginApi } from "@/services/api/loginApi";
|
||||||
import { FormControl } from '@mui/material';
|
import { FormControl } from "@mui/material";
|
||||||
import CustomTextField from "@/ui/CustomTextField";
|
import CustomTextField from "@/ui/CustomTextField";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
@ -28,22 +28,30 @@ const loginSchema = z.object({
|
|||||||
type LoginFormValues = z.infer<typeof loginSchema>;
|
type LoginFormValues = z.infer<typeof loginSchema>;
|
||||||
|
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
|
const [loader, setLoader] = useState(false);
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { register, handleSubmit, formState: { errors }, control } = useForm<LoginFormValues>({
|
const { register, handleSubmit, formState: { errors }, control } = useForm<LoginFormValues>({
|
||||||
resolver: zodResolver(loginSchema),
|
resolver: zodResolver(loginSchema),
|
||||||
});
|
});
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState("");
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const onSubmit = async (data: LoginFormValues) => {
|
const onSubmit = async (data: LoginFormValues) => {
|
||||||
try {
|
try {
|
||||||
|
setLoader(true)
|
||||||
const response = await loginApi(data);
|
const response = await loginApi(data);
|
||||||
localStorage.setItem('token', response.token);
|
localStorage.setItem("token", response.token);
|
||||||
localStorage.setItem('refreshToken', response.refreshToken);
|
localStorage.setItem("refreshToken", response.refreshToken);
|
||||||
dispatch(setAuthTokens({ token: response.token, refreshToken: response.refreshToken }));
|
dispatch(
|
||||||
|
setAuthTokens({
|
||||||
|
token: response.token,
|
||||||
|
refreshToken: response.refreshToken,
|
||||||
|
})
|
||||||
|
);
|
||||||
dispatch(setUserDetails(response));
|
dispatch(setUserDetails(response));
|
||||||
|
setLoader(false)
|
||||||
router.push('/home');
|
router.push('/home');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
setLoader(false)
|
||||||
setError('Invalid credentials');
|
setError('Invalid credentials');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -107,7 +115,7 @@ export default function LoginPage() {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box width={"100%"} marginBlockStart={"20px"}>
|
<Box width={"100%"} marginBlockStart={"20px"}>
|
||||||
<CustomizedButtons btnType="submit" label={"Sign In"} />
|
<CustomizedButtons btnType="submit" label={!loader ? "Login" : "Login..."} />
|
||||||
</Box>
|
</Box>
|
||||||
</form>
|
</form>
|
||||||
<Box
|
<Box
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
"use client"
|
"use client"
|
||||||
import DashboardWrapper from "@/components/wrapper/dashboardWrapper";
|
import DashboardWrapper from "@/components/wrapper/dashboardWrapper";
|
||||||
import AuthGuard from "@/hoc/authGuard/authGuard";
|
|
||||||
|
|
||||||
interface RootLayoutProps {
|
interface RootLayoutProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
@ -11,4 +9,4 @@ function RootLayout(props: RootLayoutProps): JSX.Element {
|
|||||||
return <DashboardWrapper>{children}</DashboardWrapper>;
|
return <DashboardWrapper>{children}</DashboardWrapper>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AuthGuard(RootLayout);
|
export default RootLayout;
|
@ -5,13 +5,27 @@ 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 store from "@/services/store";
|
||||||
|
import AuthGuard from "@/hoc/authGuard/authGuard";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
interface RootLayoutProps {
|
interface RootLayoutProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RootLayout(props: RootLayoutProps): JSX.Element {
|
function RootLayout(props: RootLayoutProps): JSX.Element {
|
||||||
|
const router = useRouter();
|
||||||
const { children } = props;
|
const { children } = props;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
const token = localStorage.getItem('token');
|
||||||
|
if (!token) {
|
||||||
|
router.push('/log-in');
|
||||||
|
} else {
|
||||||
|
router.replace('/home');
|
||||||
|
}
|
||||||
|
}, [router])
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<body>
|
<body>
|
||||||
@ -24,3 +38,4 @@ export default function RootLayout(props: RootLayoutProps): JSX.Element {
|
|||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
export default AuthGuard(RootLayout);
|
||||||
|
@ -21,6 +21,7 @@ import styled from "@emotion/styled";
|
|||||||
import { BUILDING, GEAR } from "@/utilities/svgConstant";
|
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";
|
||||||
|
|
||||||
const drawerWidth = 260;
|
const drawerWidth = 260;
|
||||||
|
|
||||||
@ -74,7 +75,8 @@ export default function DashboardWrapper(props: Props) {
|
|||||||
const { children: Children } = props;
|
const { children: Children } = props;
|
||||||
const [mobileOpen, setMobileOpen] = useState(false);
|
const [mobileOpen, setMobileOpen] = useState(false);
|
||||||
const [isClosing, setIsClosing] = useState(false);
|
const [isClosing, setIsClosing] = useState(false);
|
||||||
const router = useRouter()
|
const userData = useSelector((state: any) => state?.auth);
|
||||||
|
const router = useRouter();
|
||||||
const handleDrawerClose = () => {
|
const handleDrawerClose = () => {
|
||||||
setIsClosing(true);
|
setIsClosing(true);
|
||||||
setMobileOpen(false);
|
setMobileOpen(false);
|
||||||
@ -91,6 +93,10 @@ export default function DashboardWrapper(props: Props) {
|
|||||||
};
|
};
|
||||||
const [activeIndex, setActiveIndex] = useState<number | null>(null);
|
const [activeIndex, setActiveIndex] = useState<number | null>(null);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
console.log("User Data", userData);
|
||||||
|
}, [userData]);
|
||||||
|
|
||||||
const drawer = (
|
const drawer = (
|
||||||
<>
|
<>
|
||||||
<Toolbar sx={{ minHeight: "72px !important" }}>
|
<Toolbar sx={{ minHeight: "72px !important" }}>
|
||||||
@ -106,7 +112,7 @@ export default function DashboardWrapper(props: Props) {
|
|||||||
<ListItem
|
<ListItem
|
||||||
key={text}
|
key={text}
|
||||||
disablePadding
|
disablePadding
|
||||||
selected={activeIndex === index} // Add this line to make the item "active"
|
selected={true} // Add this line to make the item "active"
|
||||||
onClick={() => setActiveIndex(index)} // Add this line to handle click events
|
onClick={() => setActiveIndex(index)} // Add this line to handle click events
|
||||||
>
|
>
|
||||||
<ListItemButton>
|
<ListItemButton>
|
||||||
@ -125,10 +131,10 @@ export default function DashboardWrapper(props: Props) {
|
|||||||
window !== undefined ? () => window().document.body : undefined;
|
window !== undefined ? () => window().document.body : undefined;
|
||||||
|
|
||||||
const logoutHandler = () => {
|
const logoutHandler = () => {
|
||||||
localStorage.removeItem('token');
|
localStorage.removeItem("token");
|
||||||
localStorage.removeItem('refreshToken');
|
localStorage.removeItem("refreshToken");
|
||||||
router.push('/log-in');
|
router.push("/log-in");
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@ -169,18 +175,34 @@ export default function DashboardWrapper(props: Props) {
|
|||||||
borderRadius: "30px",
|
borderRadius: "30px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Avatar
|
{userData?.image && userData?.image?.length > 0 ? (
|
||||||
sx={{
|
<Avatar
|
||||||
width: 34,
|
sx={{
|
||||||
height: 34,
|
width: 34,
|
||||||
cursor: "pointer",
|
height: 34,
|
||||||
background: "var(--primary_light)",
|
cursor: "pointer",
|
||||||
color: "var(--primary_Active_text)",
|
background: "var(--primary_light)",
|
||||||
fontSize: "0.8rem",
|
color: "var(--primary_Active_text)",
|
||||||
}}
|
fontSize: "0.8rem",
|
||||||
alt="Remy Sharp"
|
}}
|
||||||
src="/static/images/avatar/1.jpg"
|
alt="Remy Sharp"
|
||||||
/>
|
src={userData?.image}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Avatar
|
||||||
|
sx={{
|
||||||
|
width: 34,
|
||||||
|
height: 34,
|
||||||
|
cursor: "pointer",
|
||||||
|
background: "var(--primary_light)",
|
||||||
|
color: "var(--primary_Active_text)",
|
||||||
|
fontSize: "0.8rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{userData?.firstName?.charAt(0)}
|
||||||
|
</Avatar>
|
||||||
|
)}
|
||||||
|
|
||||||
<IconButton aria-label="log out" size="medium" color="error">
|
<IconButton aria-label="log out" size="medium" color="error">
|
||||||
<LogoutIcon fontSize="small" onClick={logoutHandler} />
|
<LogoutIcon fontSize="small" onClick={logoutHandler} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// store/slices/authSlice.ts
|
// store/slices/authSlice.ts
|
||||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||||
import { LoginResponse } from '../api/loginApi';
|
import { LoginResponse } from "../api/loginApi";
|
||||||
|
|
||||||
interface AuthState {
|
interface AuthState {
|
||||||
token: string | null;
|
token: string | null;
|
||||||
@ -18,16 +18,16 @@ const initialState: AuthState = {
|
|||||||
token: null,
|
token: null,
|
||||||
refreshToken: null,
|
refreshToken: null,
|
||||||
id: 0,
|
id: 0,
|
||||||
username: '',
|
username: "",
|
||||||
email: '',
|
email: "",
|
||||||
firstName: '',
|
firstName: "",
|
||||||
lastName: '',
|
lastName: "",
|
||||||
gender: '',
|
gender: "",
|
||||||
image: '',
|
image: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
const authSlice = createSlice({
|
const authSlice = createSlice({
|
||||||
name: 'auth',
|
name: "auth",
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
setAuthTokens: (
|
setAuthTokens: (
|
||||||
@ -36,17 +36,25 @@ const authSlice = createSlice({
|
|||||||
) => {
|
) => {
|
||||||
state.token = action.payload.token;
|
state.token = action.payload.token;
|
||||||
state.refreshToken = action.payload.refreshToken;
|
state.refreshToken = action.payload.refreshToken;
|
||||||
localStorage.setItem('token', action.payload.token);
|
localStorage.setItem("token", action.payload.token);
|
||||||
localStorage.setItem('refreshToken', action.payload.refreshToken);
|
localStorage.setItem("refreshToken", action.payload.refreshToken);
|
||||||
},
|
},
|
||||||
clearAuthTokens: (state) => {
|
clearAuthTokens: (state) => {
|
||||||
state.token = null;
|
state.token = null;
|
||||||
state.refreshToken = null;
|
state.refreshToken = null;
|
||||||
localStorage.removeItem('token');
|
localStorage.removeItem("token");
|
||||||
localStorage.removeItem('refreshToken');
|
localStorage.removeItem("refreshToken");
|
||||||
},
|
},
|
||||||
setUserDetails: (state, action: PayloadAction<LoginResponse>) => {
|
setUserDetails: (state, action: PayloadAction<LoginResponse>) => {
|
||||||
state = action.payload;
|
state.token = action.payload.token;
|
||||||
|
state.refreshToken = action.payload.refreshToken;
|
||||||
|
state.id = action.payload.id;
|
||||||
|
state.username = action.payload.username;
|
||||||
|
state.email = action.payload.email;
|
||||||
|
state.firstName = action.payload.firstName;
|
||||||
|
state.lastName = action.payload.lastName;
|
||||||
|
state.gender = action.payload.gender;
|
||||||
|
state.image = action.payload.image;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -38,10 +38,12 @@ const CssTextField = styled(TextField)({
|
|||||||
const CustomTextField: React.FC<CustomTextFieldProps> = ({ name, control, label, type = 'text', error, helperText }) => {
|
const CustomTextField: React.FC<CustomTextFieldProps> = ({ name, control, label, type = 'text', error, helperText }) => {
|
||||||
return (
|
return (
|
||||||
<Controller
|
<Controller
|
||||||
|
|
||||||
name={name}
|
name={name}
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<CssTextField
|
<CssTextField
|
||||||
|
autoComplete='off'
|
||||||
{...field}
|
{...field}
|
||||||
label={label}
|
label={label}
|
||||||
type={type}
|
type={type}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user