thirukalyanamweb/src/pages/auth/LoginPage.jsx

210 lines
6.5 KiB
JavaScript

import React, { useState } from "react";
import {
Box,
Button,
TextField,
Typography,
InputAdornment,
IconButton,
Link as MuiLink,
} from "@mui/material";
import { Visibility, VisibilityOff } from "@mui/icons-material";
import { useNavigate, Link } from "react-router-dom";
import toast from "react-hot-toast";
import axiosInstance, { setAccessToken } from "../../api/axiosInstance";
import PromoPanel from "../../components/auth/PromoPanel";
const LoginPage = () => {
const navigate = useNavigate();
const [showPassword, setShowPassword] = useState(false);
const [loading, setLoading] = useState(false);
const [formData, setFormData] = useState({
mobile: "",
password: "",
});
const [errors, setErrors] = useState({});
const handleChange = (e) => {
const { name, value } = e.target;
setFormData((prev) => ({
...prev,
[name]: value,
}));
if (errors[name]) {
setErrors((prev) => ({ ...prev, [name]: "" }));
}
};
const validate = () => {
const newErrors = {};
if (!formData.mobile) newErrors.mobile = "Mobile number is required";
else if (!/^\d{10}$/.test(formData.mobile))
newErrors.mobile = "Enter a valid 10-digit mobile number";
if (!formData.password) newErrors.password = "Password is required";
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleLogin = async (e) => {
e.preventDefault();
if (!validate()) return;
setLoading(true);
// Retrieve FCM token from localStorage
const fcmToken = localStorage.getItem("fcm_token") || "";
const payload = {
mobile: formData.mobile,
password: formData.password,
web_fcm_token: fcmToken,
};
try {
const response = await axiosInstance.post("/login", payload);
const data = response.data;
// Extract token from response
const token = data?.access_token || data?.token || data?.accessToken || data?.data?.access_token;
if (token) {
// Store token in localStorage and axios instance
localStorage.setItem("access_token", token);
setAccessToken(token);
// Store profile_id and user_id for WebSocket channels
const profileId = data?.profile_id || data?.data?.profile_id;
const userId = data?.user_id || data?.data?.user_id;
if (profileId) localStorage.setItem("profile_id", profileId);
if (userId) localStorage.setItem("user_id", userId);
toast.success("Login Successful!");
navigate("/dashboard-home");
} else {
toast.error("Login failed: No access token received.");
}
} catch (error) {
console.error("Login error:", error);
const errorMessage =
error?.response?.data?.message ||
error?.response?.data?.error ||
"Login failed. Please check your credentials.";
toast.error(errorMessage);
} finally {
setLoading(false);
}
};
return (
<div className="h-full max-h-dvh w-full max-w-[1100px] mx-auto">
<div className="my-6 grid grid-cols-1 md:grid-cols-[60%_40%] gap-2">
<div className="">
<PromoPanel />
</div>
<div className="">
<div className="bg-white p-8 rounded-lg shadow-sm h-full flex flex-col justify-center border border-gray-100">
<Typography variant="h4" fontWeight="700" color="primary" gutterBottom align="center">
Welcome Back
</Typography>
<Typography variant="body1" color="text.secondary" mb={4} align="center">
Please login to your account
</Typography>
<form onSubmit={handleLogin}>
<Box display="flex" flexDirection="column" gap={3}>
<TextField
fullWidth
label="Mobile Number"
name="mobile"
value={formData.mobile}
onChange={handleChange}
error={Boolean(errors.mobile)}
helperText={errors.mobile}
variant="outlined"
placeholder="Enter 10-digit mobile number"
inputProps={{ maxLength: 10 }}
/>
<TextField
fullWidth
label="Password"
name="password"
type={showPassword ? "text" : "password"}
value={formData.password}
onChange={handleChange}
error={Boolean(errors.password)}
helperText={errors.password}
variant="outlined"
placeholder="Enter your password"
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={() => setShowPassword(!showPassword)}
edge="end"
>
{showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
),
}}
/>
<Box display="flex" justifyContent="flex-end">
<MuiLink
component={Link}
to="/forgot-password"
underline="hover"
variant="body2"
color="primary"
>
Forgot Password?
</MuiLink>
</Box>
<Button
type="submit"
variant="contained"
color="primary"
size="large"
fullWidth
disabled={loading}
sx={{
py: 1.5,
fontSize: "1rem",
fontWeight: "bold",
textTransform: "none",
borderRadius: 2,
}}
>
{loading ? "Logging in..." : "Login"}
</Button>
<Box mt={2} textAlign="center">
<Typography variant="body2" color="text.secondary">
Don't have an account?{" "}
<MuiLink
component={Link}
to="/registration"
underline="hover"
fontWeight="bold"
color="primary"
>
Register Now
</MuiLink>
</Typography>
</Box>
</Box>
</form>
</div>
</div>
</div>
</div>
);
};
export default LoginPage;