Skip to content
Snippets Groups Projects
AdminLogin4.jsx 7.12 KiB
import { useState } from "react"; 
import { FiMail, FiEye, FiEyeOff } from "react-icons/fi";
import { useNavigate } from "react-router-dom";
import axios from "axios";
const loginImage = new URL("/public/assets/login_img/loginadmin.svg", import.meta.url).href;
//const API_BASE_URL = "https://8dfst7hm-3000.inc1.devtunnels.ms/";
const API_BASE_URL = "http://localhost:5000/";

export default function AdminLogin() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [showPassword, setShowPassword] = useState(false);
  const [error, setError] = useState({ email: "", password: "", general: "" });

  const validateEmail = (email) => /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email);
  const validatePassword = (pass) => pass.length >= 8;

  const navigate = useNavigate(); 

  const handleEmailChange = (e) => {
    const value = e.target.value;
    setEmail(value);
    setError((prev) => ({
      ...prev,
      email: value === "" ? "" : !validateEmail(value) ? "Invalid email format" : ""
    }));
  };

  const handlePasswordChange = (e) => {
    const value = e.target.value;
    setPassword(value);
    setError((prev) => ({
      ...prev,
      password: value === "" ? "" : !validatePassword(value) ? "Password must be at least 8 characters" : ""
    }));
  };
  const [loading, setLoading] = useState(false); 

const handleSubmit = async (e) => {
  e.preventDefault();
  
  if (loading) return; 
  setLoading(true);

  let newErrors = { email: "", password: "", general: "" };

  // Validation
  if (!validateEmail(email)) newErrors.email = "Invalid email format.";
  if (!validatePassword(password)) newErrors.password = "Password must be at least 8 characters long.";

  if (newErrors.email || newErrors.password) {
    //newErrors.general = "*Incorrect Email or Password!";
    setError(newErrors);
    setLoading(false); 
    return;
  }

  try {
    const response = await axios.post(
      `${API_BASE_URL}api/auth/login`,
      { email, password },
      {
        headers: { "Content-Type": "application/json" },
        withCredentials: true,
      }
    );

    if (response.status === 200) {
      console.log("Login Success:", response.data);
      alert("Login Successful!");
      setError({ email: "", password: "", general: "" });
      navigate("/dashboard"); 
    }
  } catch (error) {
    console.error(error.response?.data || error.message);
    setError({
      email: error.response?.data?.email || "",
    password: error.response?.data?.password || "",
    general: error.response?.data?.message || "Login failed. Please check your credentials.",

    });
  }finally{

  setLoading(false);
  }
};

  
  return (
    <div className="flex flex-col items-center justify-center h-screen bg-[#D9F6F0] px-6 py-4">
      <h1 className="text-4xl font-font-primary font-bold text-[#0C4339] mb-6 text-center w-full max-w-[90%] md:text-left">
        OMPOI - Admin
      </h1>

      <div className="bg-[#2E2E2E] p-6 rounded-[32.6px] shadow-lg w-[90%] h-[85%] flex flex-col md:flex-row py-12">
      <div className="hidden md:flex w-1/2 items-center justify-center p-4 min-w-[300px]">
  <img src={loginImage} alt="Login" className="w-[80%] lg:w-[80%] xl:w-[80%]" />
</div>


        <div className="w-[1px]  bg-[#7DEBD9] hidden md:block"></div>

        <div className="w-full md:w-1/2 flex flex-col items-center justify-start p-6 text-[#6FE7D1] mt-12">
          <h2 className="text-4xl md:text-3xl font-font-primary font-semibold text-[7DEBD9] mb-11 md:mb-15">
            Admin Login
          </h2>
          <form onSubmit={handleSubmit} className="w-full max-w-md">
            
          <div className="relative w-full mb-8">
  <div className={`relative border-2 rounded-lg border-[#6FE7D1] bg-transparent ${error.email ? "border-[#EEAB4D]" : ""}`}>
    <label
      className={`absolute -top-3 left-4 px-2 bg-[#2E2E2E] border border-[#6FE7D1] rounded-md text-sm font-font-primary font-medium ${error.email ? "border-[#EEAB4D] text-[#EEAB4D]" : "text-[#6FE7D1]"}`}
    >
     Admin Email
    </label>
    <input
      type="text"
      value={email}
      onChange={handleEmailChange}
      placeholder="Enter email"
      className={`w-full h-14 px-3 pr-12 bg-transparent text-white text-lg focus:outline-none font-font-primary  ${
         error.email ? "border-red-500" : "border-gray-300"
      }`}
    />
    <FiMail 
      className="absolute right-4 top-1/2 transform -translate-y-1/2 text-xl"
      style={{ color: error.email ? "#EEAB4D" : "#6FE7D1" }} 
    />
  </div>
  {error.email && <p className="text-[#EEAB4D] text-sm mt-1">{error.email}</p>}
</div>

{/* Passwd Input */}
<div className="relative w-full mb-2">
  <div className={`relative border-2 rounded-lg border-[#6FE7D1] bg-transparent ${error.password ? "border-[#EEAB4D]" : ""}`}>
    <label
      className={`absolute -top-3 left-4 px-2 bg-[#2E2E2E] border border-[#6FE7D1] rounded-md text-sm font-font-primary font-medium ${error.password ? "border-[#EEAB4D] text-[#EEAB4D]" : "text-[#6FE7D1]"}`}
    >
      Password
    </label>
    <input
      type={showPassword ? "text" : "password"}
      value={password}
      onChange={handlePasswordChange}
      placeholder="Enter your password"
      className="w-full h-14 px-4 pr-12 bg-transparent text-white text-lg focus:outline-none font-font-primary"
    />
    {showPassword ? (
      <FiEyeOff 
        className="absolute right-4 top-1/2 transform -translate-y-1/2 text-xl cursor-pointer"
        style={{ color: error.password ? "#EEAB4D" : "#6FE7D1" }}
        onClick={() => setShowPassword(!showPassword)}
      />
    ) : (
      <FiEye 
        className="absolute right-4 top-1/2 transform -translate-y-1/2 text-xl cursor-pointer"
        style={{ color: error.password ? "#EEAB4D" : "#6FE7D1" }}
        onClick={() => setShowPassword(!showPassword)}
      />
    )}
  </div>
  {error.password && <p className="text-[#EEAB4D] text-sm mt-1">{error.password}</p>}
</div>



            {/* Fgt Passwd & general error */}
            <div className="flex justify-between items-center mt-2 w-full">
              <a href="#" className="text-[#27DEBF] hover:underline text-sm font-font-primary font-semibold">
                Forgot Password?
              </a>
              {error.general && (
                <span className="text-[#EEAB4D] text-sm font-semibold font-font-primary">
                  {error.general}
                </span>
              )}
            </div>

            {/* signin btn */}
            <div className="mt-8 flex justify-center">
            <button 
  type="submit"
  className="w-[100%] md:w-48 h-14 text-[#263238] font-bold rounded-full bg-[#6FE7D1] shadow-md hover:bg-[#5CC4AE] transition text-lg font-font-primary font-extrabold flex items-center justify-center"
  disabled={loading}
>
  {loading ? (
    <svg className="animate-spin h-6 w-6 mr-2" viewBox="0 0 24 24">
      <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
      <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z"></path>
    </svg>
  ) : (
    "Sign In"
  )}
</button>

                  </div>
               </form>
              </div>
         </div>
        </div>
  );
}