diff --git a/package-lock.json b/package-lock.json index 89f8df0801bdfd5caa5b938bdf76583e03eaa6da..73f8dc4785545fc6ea71b3d7b9261ac00d07e733 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "ompi", "version": "0.0.0", "dependencies": { + "@heroicons/react": "^2.2.0", "@reduxjs/toolkit": "^2.6.1", "@tailwindcss/postcss": "^4.0.3", "@tailwindcss/vite": "^4.0.3", @@ -881,6 +882,15 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@heroicons/react": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz", + "integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==", + "license": "MIT", + "peerDependencies": { + "react": ">= 16 || ^19.0.0-rc" + } + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", diff --git a/package.json b/package.json index 4853f9c6bf87b0a19962d3360dabf7d73c40d7d0..a1d1207ec0d2e17b88d126c5968157a585024cd6 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "preview": "vite preview" }, "dependencies": { + "@heroicons/react": "^2.2.0", "@reduxjs/toolkit": "^2.6.1", "@tailwindcss/postcss": "^4.0.3", "@tailwindcss/vite": "^4.0.3", diff --git a/src/assets/seller-login/info.svg b/src/assets/seller-login/info.svg new file mode 100644 index 0000000000000000000000000000000000000000..ec38171522e4e4ab066a7f1ab37740be589df4b4 --- /dev/null +++ b/src/assets/seller-login/info.svg @@ -0,0 +1 @@ +<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px" height="24px"> <path d="M 12 2 C 6.4889971 2 2 6.4889971 2 12 C 2 17.511003 6.4889971 22 12 22 C 17.511003 22 22 17.511003 22 12 C 22 6.4889971 17.511003 2 12 2 z M 12 4 C 16.430123 4 20 7.5698774 20 12 C 20 16.430123 16.430123 20 12 20 C 7.5698774 20 4 16.430123 4 12 C 4 7.5698774 7.5698774 4 12 4 z M 11 7 L 11 9 L 13 9 L 13 7 L 11 7 z M 11 11 L 11 17 L 13 17 L 13 11 L 11 11 z"/></svg> \ No newline at end of file diff --git a/src/pages/seller_login.jsx b/src/pages/seller_login.jsx index 5caefea1c5b5ab89ad7327adb3e9e312127a0734..39e634135d01f9a5c31371bab2a5899f732c9ba3 100644 --- a/src/pages/seller_login.jsx +++ b/src/pages/seller_login.jsx @@ -1,13 +1,54 @@ import React 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"; 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(); + }; return ( <> <div className="relative bg-[#E9FAFF] p-4 flex flex-col md:flex-row font-montserrat"> @@ -29,43 +70,65 @@ function Seller_login() { </div> <div> <label - htmlFor="merchant_id" 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" - className="w-full p-2 md:p-3 border border-[#C4CFDE] rounded-[12px] mt-[-10px] text-[10px] md:text-[18px] focus:outline-none" + 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 - htmlFor="password" 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" - className="w-full p-2 md:p-3 border border-[#C4CFDE] rounded-[12px] mt-[-10px] text-[10px] md:text-[18px] focus:outline-none" + 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 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> + <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> diff --git a/src/slice/sellerlogin_fromslice.js b/src/slice/sellerlogin_fromslice.js index 381da410efc06098777b5119997486e24b0155db..d8cf2f2f6136872398cb0964e3b8e252df88e7ba 100644 --- a/src/slice/sellerlogin_fromslice.js +++ b/src/slice/sellerlogin_fromslice.js @@ -1,29 +1,31 @@ -import { createSlice } from "@reduxjs/toolkit"; +{/* + import { createSlice } from "@reduxjs/toolkit"; const initialState ={ - merchantId:"", - password:"", - errors:{ - merchantId:"", - password:"", + merchantId: "", + password: "", + errors: { + merchantId: "", + password: "", }, -}; + }; -const fromslice = createSlice({ - name:"form", + +const sellerlogin_fromslice = createSlice({ + name: 'sellerlogin', initialState, - reducers:{ - setMerchantId: (state, action) =>{ - state.merchantId = action.payload; - }, - setPassword: (state, action) =>{ - state.password = action.payload; - }, - setErrors: (state, action) =>{ - state.errors = action.payload; - }, - } + reducers: { + setMerchantId: (state, action) => { + state.merchantId = action.payload; + }, + setPassword: (state, action) => { + state.password = action.payload; + }, + setErrors: (state, action) => { + state.errors = action.payload; + }, + }, }); - -export const {setMerchantId, setPassword, setErrors} = fromslice.actions; -export default fromslice.reducer; \ No newline at end of file +export const {setMerchantId, setPassword, setErrors} = sellerlogin_fromslice.actions; +export default sellerlogin_fromslice.reducer; + */} \ No newline at end of file diff --git a/src/store/Sellerlogin_store.js b/src/store/Sellerlogin_store.js index 52dabffcc3c01faf35e4f8a132ab1b1eddfed171..727e10718fc81632d9c86f94f39171a1c35f55c4 100644 --- a/src/store/Sellerlogin_store.js +++ b/src/store/Sellerlogin_store.js @@ -1,7 +1,9 @@ -import { configureStore } from "@reduxjs/toolkit"; -import formReducer from "../slice/sellerlogin_fromslice"; -export const store = configureStore({ +{/* + import { configureStore } from "@reduxjs/toolkit"; +import sellerloginreducer from "../slice/sellerlogin_fromslice"; +export const store= configureStore({ reducer: { - form: formReducer, + form: sellerloginreducer, }, -}); \ No newline at end of file +}); + */} \ No newline at end of file