diff --git a/src/assets/fonts/Montserrat-Bold.ttf b/src/assets/fonts/Montserrat-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..02ff6fff07885b50373c35a6f59819b68e3ca8f3 Binary files /dev/null and b/src/assets/fonts/Montserrat-Bold.ttf differ diff --git a/src/assets/fonts/Montserrat-Thin.ttf b/src/assets/fonts/Montserrat-Thin.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2a85a52c8072b74749cebdc5853b940c8aa683d1 Binary files /dev/null and b/src/assets/fonts/Montserrat-Thin.ttf differ diff --git a/src/assets/seller-login/open-eye.svg b/src/assets/seller-login/open-eye.svg new file mode 100644 index 0000000000000000000000000000000000000000..88ba1acaaee455fc272e0464eedeef10729cbfee --- /dev/null +++ b/src/assets/seller-login/open-eye.svg @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg fill="#000000" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" + width="800px" height="800px" viewBox="0 0 60.254 60.254" + xml:space="preserve"> +<g> + <g> + <g> + <path d="M29.008,48.308c-16.476,0-28.336-17.029-28.833-17.754c-0.248-0.36-0.231-0.841,0.039-1.184 + c0.561-0.712,13.906-17.424,29.913-17.424c17.953,0,29.474,16.769,29.956,17.482c0.23,0.342,0.229,0.79-0.007,1.129 + c-0.475,0.688-11.842,16.818-29.899,17.721C29.786,48.297,29.396,48.308,29.008,48.308z M2.267,30.028 + c2.326,3.098,13.553,16.967,27.812,16.254c15.237-0.76,25.762-13.453,27.938-16.3c-2.175-2.912-12.811-16.035-27.889-16.035 + C16.7,13.947,4.771,27.084,2.267,30.028z"/> + </g> + <g> + <path d="M30.127,37.114c-3.852,0-6.986-3.135-6.986-6.986c0-3.851,3.134-6.985,6.986-6.985s6.986,3.135,6.986,6.985 + C37.113,33.979,33.979,37.114,30.127,37.114z"/> + </g> + <g> + <path d="M30.127,42.614c-6.885,0-12.486-5.602-12.486-12.486c0-6.883,5.602-12.485,12.486-12.485 + c6.884,0,12.486,5.602,12.486,12.485C42.613,37.012,37.013,42.614,30.127,42.614z M30.127,19.641 + c-5.782,0-10.486,4.704-10.486,10.486c0,5.781,4.704,10.485,10.486,10.485s10.486-4.704,10.486-10.485 + C40.613,24.345,35.91,19.641,30.127,19.641z"/> + </g> + </g> +</g> +</svg> \ No newline at end of file diff --git a/src/index.css b/src/index.css index 8a35dab4f09eac3c63f976adfb8aa68f3a7bdec3..e3892e5bd564d3d1a725a40baad5e8cef6768977 100644 --- a/src/index.css +++ b/src/index.css @@ -1,5 +1,11 @@ -@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap'); +@font-face { + font-family: Montserrat; + src: url("../src/assets/fonts/Montserrat-Bold.ttf"); +} + + @theme { --font-montserrat: Montserrat, "sans-serif" ; } + @import "tailwindcss"; \ No newline at end of file diff --git a/src/pages/seller_login.jsx b/src/pages/seller_login.jsx index 39e634135d01f9a5c31371bab2a5899f732c9ba3..cb33c1832b6b11c3678cacd38ef8cc81d76ee4d0 100644 --- a/src/pages/seller_login.jsx +++ b/src/pages/seller_login.jsx @@ -1,146 +1,137 @@ -import React from "react"; +import React, { useState } from "react"; import key from "../assets/seller-login/first!.svg"; -import info from "../assets/seller-login/info.svg"; -import icon2 from "../assets/seller-login/eye.svg"; import icon from "../assets/seller-login/mail.svg"; -import { useState } from "react"; -import { useNavigate } from "react-router-dom"; +import icon1 from "../assets/seller-login/eye.svg"; +import icon2 from "../assets/seller-login/open-eye.svg"; + function Seller_login() { - const navigate = useNavigate(); - const goto = () => { - navigate("/create-account"); - }; - const Infoicon = () =>( - <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5 inline-block ml-1"> - <path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M12 20a8 8 0 100-16 8 8 0 000 16z" /> - </svg> - ); - const [merchantId, setMerchantId] = useState(""); - const [password, setPassword] = useState(""); - const [errors, setErrors] = useState({}); - - // Regex Patterns - const merchantIdPattern = /^[A-Za-z]{4}[0-9]{4}$/; - const passwordPattern = /^(?=.*[A-Za-z]{3,})(?=.*\d{3,})(?=.*[\W_]).{3,}$/; - - const validate = () => { - let newErrors = {}; - - if (!merchantId) { - newErrors.merchantId = "* Please type your ID"; - } else if (!merchantIdPattern.test(merchantId)) { - newErrors.merchantId = - "* Merchant ID must start with 4 letters followed by 5 digits"; - } - - if (!password) { - newErrors.password = "* Please type your password "; - } else if (!passwordPattern.test(password)) { - newErrors.password = - "* Password must have at least 3 letters, 3 numbers, and 1 special character"; - } - - setErrors(newErrors); - }; - - const handleChange = (e) => { - const { name, value } = e.target; - if (name === "merchantId") setMerchantId(value); - if (name === "password") setPassword(value); - validate(); - }; + const Infoicon = () =>( + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5 inline-block ml-1"> + <path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M12 20a8 8 0 100-16 8 8 0 000 16z" /> + </svg> +); + const [merchantId, setMerchantId] = useState(""); + const [password, setPassword] = useState(""); + const [merchantIdError, setMerchantIdError] = useState(""); + const [passwordError, setPasswordError] = useState(""); + const [showPassword, setShowPassword] = useState(false); + + const validateMerchantId = (id) => { + const pattern = /^[A-Za-z]{4}\d{5}$/; + if (!pattern.test(id)) { + setMerchantIdError("*Merchant ID must be 4 letters followed by 5 numbers"); + return false; + } + setMerchantIdError(""); + return true; + }; + + const validatePassword = (pass) => { + const pattern = /^(?=.*[a-zA-Z]{4,})(?=.*\d{3,})(?=.*[^a-zA-Z\d]{2,}).{9,}$/; + if (!pattern.test(pass)) { + setPasswordError( + "*Password must contain at least 4 letters, 2 special characters, and 3 numbers" + ); + return false; + } + setPasswordError(""); + return true; + }; + return ( - <> - <div className="relative bg-[#E9FAFF] p-4 flex flex-col md:flex-row font-montserrat"> - <div className="relative w-full"> - <h2 className="font-bold text-[15px] md:text-5xl px-2 md:px-10 py-3 md:py-10 "> - OMPOI-Seller - </h2> - <div className=" bg-[#FFFFFF] grid grid-cols-1 md:grid-cols-3 items-center justify-center gap-3 p-10 shadow-lg rounded-[15.3px] md:rounded-[32.6px] left-[10px] right-[10px] "> - <img - src={key} - alt="illutration" - className="size-full md:size-[380px] px-4 md:px-12" - /> - <div className="hidden md:flex bg-[#E2E7EE] w-[3px] h-full ml-[180px] "></div> - <div className="flex flex-col p-4 bg-[#FFFFFF] border-none"> - <form className="mt-0 md:mt-[-150px] ml-0 md:ml-[-150px] "> - <div className="flex justify-center items-center mt-[70px]"> - <div className="font-[600px] text-center text-[16.48px] mt-[50px] md:text-[33.91px] mb-[15px] md:mb-[30px] ">LOGIN</div> - </div> - <div> - <label - className="text-[10px] md:text-[18px] text-[#45505F] p-[0.5px] bg-white relative top-1 left-6 px-1" - > - Merchant ID - </label> - <input - type="text" - name="merchantId" - value={merchantId} - onChange={handleChange} - onBlur={validate} - className={`w-full p-2 md:p-3 border border-[#C4CFDE] rounded-[12px] mt-[-10px] text-[10px] md:text-[18px] focus:outline-none ${errors.merchantId - ? "border-red-500 text-red-500" - : merchantId - ? "border-green-500 text-green-500" - : "border-gray-300" - } `} - placeholder="Enter id" - required - /> - <span className="flex inset-y-0 justify-end "> - <img src={icon} alt="icon" className=" relative items-center w-3 md:w-5 h-3 md:h-5 mt-[-25px] md:mt-[-35px] mr-[12px] md:mr-[20px] " /> - </span> - {errors.merchantId && ( - <p className="text-red-500 text-sm mt-1">{errors.merchantId} <Infoicon /></p> - )} - <br /> - <div> - <label - className="text-[10px] md:text-[18px] text-[#45505F] p-[0.5px] bg-white relative top-1 left-6 px-1 " - > - Password - </label> - <input - type="text" - name="password" - value={password} - onChange={handleChange} - onBlur={validate} - className={`w-full p-2 md:p-3 border border-[#C4CFDE] rounded-[12px] mt-[-10px] text-[10px] md:text-[18px] focus:outline-none ${errors.password - ? "border-red-500 text-red-500" - : merchantId - ? "border-green-500 text-green-500" - : "border-gray-300" - }`} - placeholder="Enter your password" - required - /> - <span className="flex inset-y-0 justify-end "> - <img src={icon2} alt="icon" className=" relative items-center w-3 md:w-5 h-3 md:h-5 mt-[-25px] md:mt-[-35px] mr-[12px] md:mr-[20px]" /> - </span> - {errors.password && ( - <p className="text-red-500 text-sm mt-1">{errors.merchantId} <Infoicon /> </p> - )} - <div className="flex flex-col md:flex-row gap-1 md:gap-3 items-center justify-center md:justify-between p-3 md:p-4"> - <span className="relative font-[300px] md:font-[600px] text-[10px] md:text-[18.26px] ">Forgot Password</span> - <span className="relative font-[300px] md:font-[600px] text-[10px] md:text-[18.26px] cursor-pointer hover:text-[#FFBD69] " onClick={goto}>Create Account</span> - </div> - <div className="flex justify-center p-4"> - <button onClick={validate} className="bg-[#FFBD69] pb-[13.04px] pt-[13.04px] pr-[39.12px] pl-[39.12px] w-fit h-flt rounded-[32.60px] inline-flex justify-center items-center text-[10px] md:text-[20.87px] font-[800px] ">Sign in</button> - </div> - <div className="flex justify-center p-4"> - <button className="bg-white pb-[13.04px] pt-[13.04px] pr-[39.12px] pl-[39.12px] w-fit h-fit rounded-[32.60px] border-[#FFBD69] border-2 inline-flex justify-center items-center text-[10px] md:text-[20.87px] font-[800px] ">check Status</button> - </div> - </div> - </div> - </form> + <div className="flex flex-col items-center min-h-screen bg-blue-50 p-4 font-montserrat"> + {/* Header */} + <div className="w-full text-left max-w-6xl px-2 md:px-0 mb-6 mt-6"> + <h1 className="text-[48.31px] font-[700px] text-[#030A1E] self-start">OMPOI - Seller</h1> + </div> + + <div className="flex flex-col md:flex-row items-center justify-center w-full max-w-6xl bg-white p-15 rounded-[32.6px] shadow-lg"> + {/* Left Section - Image */} + <div className="w-full md:w-1/2 flex justify-center md:pr-8 relative"> + <img src={key} alt="Login Illustration" className="max-w-xs md:max-w-sm p-10" /> + <div className="hidden md:block absolute right-0 top-0 bottom-0 w-[1px] bg-gray-300"></div> + </div> + + {/* Right Section - Login Form */} + <div className="w-full md:w-1/2 flex flex-col items-center md:pl-8 mt-6 md:mt-0"> + <h2 className="text-2xl font-semibold mb-10 self-center">Login</h2> + + <form className="w-full max-w-sm"> + <div className="relative mb-8"> + <label + className={`text-[10px] md:text-[18px] text-[#8B9BB1] p-[0.5px] px-1 relative top-1 left-6 bg-white ${ + merchantIdError ? "text-red-500" : "text-green-500" + }`} + > + Merchant ID + </label> + <input + type="text" + id="merchantId" + className={`w-full p-2 md:p-3 border border-[#C4CFDE] rounded-[12px] mt-[-10px] text-[10px] md:text-[18px] focus:outline-none ${ + merchantIdError ? "border-red-500" : "border-green-500 " + }`} + required + placeholder="Enter ID" + value={merchantId} + onChange={(e) => { + setMerchantId(e.target.value); + validateMerchantId(e.target.value); + }} + /> + <span className="flex inset-y-0 justify-end"> + <img src={icon} alt="icon" className="relative items-center w-3 md:w-5 h-3 md:h-5 mt-[-25px] md:mt-[-35px] mr-[12px] md:mr-[20px]" /> + </span> + {merchantIdError && <p className="text-red-500 text-[10px]">{merchantIdError} <Infoicon /> </p>} + </div> + + <div className="relative mb-4"> + <label + className={`text-[10px] md:text-[18px] text-[#8B9BB1] p-[0.5px] px-1 relative top-1 left-6 bg-white ${ + passwordError ? "text-red-500" : "text-green-500" + }`} + > + Password + </label> + <input + type={showPassword ? "text" : "password"} + id="password" + className={`w-full p-2 md:p-3 border border-[#C4CFDE] rounded-[12px] mt-[-10px] text-[10px] md:text-[18px] focus:outline-none ${ + passwordError ? "border-red-500" : "border-green-500 " + }`} + required + placeholder="Enter your password" + value={password} + onChange={(e) => { + setPassword(e.target.value); + validatePassword(e.target.value); + }} + /> + <span className="flex inset-y-0 justify-end cursor-pointer" onClick={() => setShowPassword(!showPassword)}> + <img src={showPassword ? icon2 : icon1} alt="icon" className="relative items-center w-3 md:w-5 h-3 md:h-5 mt-[-25px] md:mt-[-35px] mr-[12px] md:mr-[20px]" /> + </span> + {passwordError && <p className="text-red-500 text-[10px]">{passwordError} <Infoicon /></p>} + </div> + + <div className="flex justify-between w-full text-sm mb-8"> + <p className="text-gray-600">Forgot Password?</p> + <p className="text-yellow-500">Create an Account</p> + </div> + <div className="flex justify-center items-center"> + <button className="w-52 px-10 bg-yellow-500 text-[#020617] py-3.5 rounded-[32.6px] mb-8 mt-8 font-semibold"> + Sign in + </button> + </div> + <div className="flex justify-center items-center"> + <button className="w-52 px-10 border border-[#fdba74] text-[#020617] py-3.5 rounded-[32.6px] font-semibold"> + Check Status + </button> </div> - </div> + </form> </div> </div> - </> + </div> ); } + export default Seller_login;