diff --git a/src/app/ChangePassword/CaptchaImage.tsx b/src/app/ChangePassword/CaptchaImage.tsx new file mode 100644 index 0000000..d63d34c --- /dev/null +++ b/src/app/ChangePassword/CaptchaImage.tsx @@ -0,0 +1,23 @@ +import React, { useEffect, useRef } from 'react'; + +const CaptchaImage = ({ text }: { text: string }) => { + const canvasRef = useRef(null); + + useEffect(() => { + const canvas = canvasRef.current; + const ctx = canvas?.getContext('2d'); + if (canvas && ctx) { + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.fillStyle = '#ffffff'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.font = '26px Arial'; + ctx.fillStyle = '#000'; + ctx.setTransform(1, 0.1, -0.1, 1, 0, 0); + ctx.fillText(text, 10, 30); + } + }, [text]); + + return ; +}; + +export default CaptchaImage; diff --git a/src/app/ChangePassword/clientCarousel.tsx b/src/app/ChangePassword/clientCarousel.tsx new file mode 100644 index 0000000..bc19c85 --- /dev/null +++ b/src/app/ChangePassword/clientCarousel.tsx @@ -0,0 +1,98 @@ +'use client'; + +import { Box, Image, ActionIcon } from '@mantine/core'; +import { IconChevronLeft, IconChevronRight } from '@tabler/icons-react'; +import { useRef } from 'react'; +import DICGC from '@/app/image/DICGC_image.jpg'; +import objective from '@/app/image/objective.jpg'; +import frontPage from '@/app/image/ib_front_page.jpg'; + +export default function CustomCarousel() { + const scrollRef = useRef(null); + const scrollBy = 300; // px per click + + const scrollLeft = () => { + scrollRef.current?.scrollBy({ left: -scrollBy, behavior: 'smooth' }); + }; + + const scrollRight = () => { + scrollRef.current?.scrollBy({ left: scrollBy, behavior: 'smooth' }); + }; + + const images = [DICGC, objective, frontPage]; + + return ( + + {/* Scrollable container */} + + {images.map((img, i) => ( + + {`Slide + + ))} + + + {/* Left Scroll Button */} + + + + + {/* Right Scroll Button */} + + + + + ); +} + \ No newline at end of file diff --git a/src/app/ChangePassword/page.module.css b/src/app/ChangePassword/page.module.css new file mode 100644 index 0000000..7fb5753 --- /dev/null +++ b/src/app/ChangePassword/page.module.css @@ -0,0 +1,62 @@ +.root { + width: 100vw; + height: 100vh; + + } + +.title { + color: light-dark(var(--mantine-color-black), var(--mantine-color-white)); + font-family: + Greycliff CF, + var(--mantine-font-family); +} + + + .mobileImage { + @media (min-width: 48em) { + display: none; + } + } + +.desktopImage { + object-fit: cover; + width: 100%; + height: 100%; + @media (max-width: 47.99em) { + display: none; + } + } + +.carousel-wrapper { + width: 100%; + max-width: 800px; + margin: 0 auto; + overflow: hidden; +} + +.gradient-control { + width: 15%; + height: 100%; + position: absolute; + top: 0; + z-index: 2; + background-color: transparent; + display: flex; + align-items: center; + justify-content: center; + opacity: 0.6; + color: white; + pointer-events: all; +} + +/* First control is left */ +.gradient-control:first-of-type { + left: 0; + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.0001)); +} + +/* Last control is right */ +.gradient-control:last-of-type { + right: 0; + background-image: linear-gradient(to left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.0001)); +} diff --git a/src/app/ChangePassword/page.tsx b/src/app/ChangePassword/page.tsx new file mode 100644 index 0000000..1797470 --- /dev/null +++ b/src/app/ChangePassword/page.tsx @@ -0,0 +1,218 @@ +"use client"; +import React, { useState, useEffect } from "react"; +import { Text, Button, TextInput, PasswordInput, Title, Card, Group, Flex, Box, Image, Anchor, Stack, Container, rem, Grid } from "@mantine/core"; +import { notifications } from "@mantine/notifications"; +import { Providers } from "@/app/providers"; +import { useRouter } from "next/navigation"; +import NextImage from "next/image"; +import myImage from '@/app/image/ebanking.jpg'; +import changePwdImage from '@/app/image/changepw.png'; +import dynamic from 'next/dynamic'; +import RegistrationTimeline from '../_components/timeline/RegistrationTimeline'; +import CaptchaImage from './CaptchaImage'; // adjust path if needed + + + + + +function generateCaptcha(length = 6) { + const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + return Array.from({ length }, () => chars[Math.floor(Math.random() * chars.length)]).join(""); +} + +export default function Login() { + const router = useRouter(); + // const [error, setError] = useState(null); + //const [CIF, SetCIF] = useState(""); + // const [psw, SetPsw] = useState(""); + const [captcha, setCaptcha] = useState(""); + const [inputCaptcha, setInputCaptcha] = useState(""); + + const [password, setPassword] = useState(""); + const [confirmPassword, setConfirmPassword] = useState(""); + const [error, setError] = useState(""); + + const ClientCarousel = dynamic(() => import('./clientCarousel'), { ssr: false }); + + // const [captcha, setCaptcha] = useState(''); + const [captchaInput, setCaptchaInput] = useState(''); + const [captchaError, setCaptchaError] = useState(''); + + + + + // useEffect(() => { + // setCaptcha(generateCaptcha()); + // }, []); + + // const regenerateCaptcha = () => { + // setCaptcha(generateCaptcha()); + // setInputCaptcha(""); + // }; + + useEffect(() => { + generateCaptcha(); + }, []); + + const generateCaptcha = () => { + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let result = ''; + for (let i = 0; i < 6; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)); + } + setCaptcha(result); + setCaptchaInput(''); + setCaptchaError(''); + }; + + return ( + +
+ + ebanking + +
+ + + Change Password Image + + + Change User Login Password + +
+ e.preventDefault()} + onPaste={(e) => e.preventDefault()} + onCut={(e) => e.preventDefault()} + /> + + e.preventDefault()} + onPaste={(e) => e.preventDefault()} + onCut={(e) => e.preventDefault()} + + /> + + {/* CAPTCHA */} +
+ +
+ + +
+ setCaptchaInput(e.currentTarget.value)} + required + /> + {captchaError &&

{captchaError}

} +
+ + + + + {/* */} + + + {/* */} + + +

+ + + Note: Password will contains minimum one alphabet, one digit, one special symbol and total 8 charecters. + + +
+
+
+ + + © 2025 KCC Bank. All rights reserved. {" "} + + + +
+
+
+ ); +} diff --git a/src/app/ChangeTxn/CaptchaImage.tsx b/src/app/ChangeTxn/CaptchaImage.tsx new file mode 100644 index 0000000..d63d34c --- /dev/null +++ b/src/app/ChangeTxn/CaptchaImage.tsx @@ -0,0 +1,23 @@ +import React, { useEffect, useRef } from 'react'; + +const CaptchaImage = ({ text }: { text: string }) => { + const canvasRef = useRef(null); + + useEffect(() => { + const canvas = canvasRef.current; + const ctx = canvas?.getContext('2d'); + if (canvas && ctx) { + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.fillStyle = '#ffffff'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.font = '26px Arial'; + ctx.fillStyle = '#000'; + ctx.setTransform(1, 0.1, -0.1, 1, 0, 0); + ctx.fillText(text, 10, 30); + } + }, [text]); + + return ; +}; + +export default CaptchaImage; diff --git a/src/app/ChangeTxn/clientCarousel.tsx b/src/app/ChangeTxn/clientCarousel.tsx new file mode 100644 index 0000000..bc19c85 --- /dev/null +++ b/src/app/ChangeTxn/clientCarousel.tsx @@ -0,0 +1,98 @@ +'use client'; + +import { Box, Image, ActionIcon } from '@mantine/core'; +import { IconChevronLeft, IconChevronRight } from '@tabler/icons-react'; +import { useRef } from 'react'; +import DICGC from '@/app/image/DICGC_image.jpg'; +import objective from '@/app/image/objective.jpg'; +import frontPage from '@/app/image/ib_front_page.jpg'; + +export default function CustomCarousel() { + const scrollRef = useRef(null); + const scrollBy = 300; // px per click + + const scrollLeft = () => { + scrollRef.current?.scrollBy({ left: -scrollBy, behavior: 'smooth' }); + }; + + const scrollRight = () => { + scrollRef.current?.scrollBy({ left: scrollBy, behavior: 'smooth' }); + }; + + const images = [DICGC, objective, frontPage]; + + return ( + + {/* Scrollable container */} + + {images.map((img, i) => ( + + {`Slide + + ))} + + + {/* Left Scroll Button */} + + + + + {/* Right Scroll Button */} + + + + + ); +} + \ No newline at end of file diff --git a/src/app/ChangeTxn/page.modukle.css b/src/app/ChangeTxn/page.modukle.css new file mode 100644 index 0000000..7fb5753 --- /dev/null +++ b/src/app/ChangeTxn/page.modukle.css @@ -0,0 +1,62 @@ +.root { + width: 100vw; + height: 100vh; + + } + +.title { + color: light-dark(var(--mantine-color-black), var(--mantine-color-white)); + font-family: + Greycliff CF, + var(--mantine-font-family); +} + + + .mobileImage { + @media (min-width: 48em) { + display: none; + } + } + +.desktopImage { + object-fit: cover; + width: 100%; + height: 100%; + @media (max-width: 47.99em) { + display: none; + } + } + +.carousel-wrapper { + width: 100%; + max-width: 800px; + margin: 0 auto; + overflow: hidden; +} + +.gradient-control { + width: 15%; + height: 100%; + position: absolute; + top: 0; + z-index: 2; + background-color: transparent; + display: flex; + align-items: center; + justify-content: center; + opacity: 0.6; + color: white; + pointer-events: all; +} + +/* First control is left */ +.gradient-control:first-of-type { + left: 0; + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.0001)); +} + +/* Last control is right */ +.gradient-control:last-of-type { + right: 0; + background-image: linear-gradient(to left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.0001)); +} diff --git a/src/app/ChangeTxn/page.tsx b/src/app/ChangeTxn/page.tsx new file mode 100644 index 0000000..5bb847e --- /dev/null +++ b/src/app/ChangeTxn/page.tsx @@ -0,0 +1,279 @@ +"use client"; +import React, { useState, useEffect } from "react"; +import { Text, Button, TextInput, PasswordInput, Title, Card, Group, Flex, Box, Image, Anchor, Stack, Container, rem, Grid } from "@mantine/core"; +import { notifications } from "@mantine/notifications"; +import { Providers } from "@/app/providers"; +import { useRouter } from "next/navigation"; +import NextImage from "next/image"; +import myImage from '@/app/image/ebanking.jpg'; +import changePwdImage from '@/app/image/changepw.png'; +import dynamic from 'next/dynamic'; +import CaptchaImage from './CaptchaImage'; + +function generateCaptcha(length = 6) { + const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + return Array.from({ length }, () => chars[Math.floor(Math.random() * chars.length)]).join(""); +} + +export default function Login() { + const router = useRouter(); + const [error, setError] = useState(null); + const [CIF, SetCIF] = useState(""); + const [psw, SetPsw] = useState(""); + const [captcha, setCaptcha] = useState(""); + const [inputCaptcha, setInputCaptcha] = useState(""); + const ClientCarousel = dynamic(() => import('./clientCarousel'), { ssr: false }); + //const [captcha, setCaptcha] = useState(''); + const [captchaInput, setCaptchaInput] = useState(''); + const [captchaError, setCaptchaError] = useState(''); + // const [isClient,SetIsClient] =useState(false); + + + // useEffect(()=> SetIsClient(true),[]); + + // useEffect(() => { + // setCaptcha(generateCaptcha()); + // }, []); + + // const regenerateCaptcha = () => { + // setCaptcha(generateCaptcha()); + // setInputCaptcha(""); + // }; + + useEffect(() => { + generateCaptcha(); + }, []); + + const generateCaptcha = () => { + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let result = ''; + for (let i = 0; i < 6; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)); + } + setCaptcha(result); + setCaptchaInput(''); + setCaptchaError(''); + }; + + async function handleLogin(e: React.FormEvent) { + e.preventDefault(); + const onlyDigit = /^\d{11}$/; + if (!onlyDigit.test(CIF)) { + setError('Input value must be 11 digit'); + } + + if (inputCaptcha !== captcha) { + notifications.show({ + withBorder: true, + color: "red", + title: "Captcha Error", + message: "Please enter the correct captcha", + autoClose: 5000, + }); + return; + } + + if (CIF === "30022497139" && psw === "SecurePass123!") { + const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30"; + localStorage.setItem("customerNumber", CIF); + localStorage.setItem("password", psw); + localStorage.setItem("access_token", token); + router.push("/home"); + } else { + // SetCIF(''); + // SetPsw(''); + // setCaptcha(''); + notifications.show({ + withBorder: true, + color: "red", + title: "Wrong User Id or Password", + message: "Wrong User Id or Password", + autoClose: 5000, + }); + } + } + + return ( + +
+ + ebanking + +
+ {/*
+
+ ebanking +
+ + Change User Login Password +
+ + + + + +

+ + + Note: Password will contains minimum one alphabet, one digit, one special symbol and total 8 charecters. + + +
+
*/} + + Change Password Image + + + Change Transaction Password +
+ e.preventDefault()} + onPaste={(e) => e.preventDefault()} + onCut={(e) => e.preventDefault()} + /> + e.preventDefault()} + onPaste={(e) => e.preventDefault()} + onCut={(e) => e.preventDefault()} + /> + {/* */} + + {/* CAPTCHA */} +
+ +
+ + +
+ setCaptchaInput(e.currentTarget.value)} + required + /> + {captchaError &&

{captchaError}

} +
+ + + + + + + +

+ + + Note: Password will contains minimum one alphabet, one digit, one special symbol and total 8 charecters. + + +
+
+
+ + + © 2025 KCC Bank. All rights reserved. {" "} + + + +
+
+
+ ); +} diff --git a/src/app/_components/timeline/RegistrationTimeline.tsx b/src/app/_components/timeline/RegistrationTimeline.tsx new file mode 100644 index 0000000..e122cb0 --- /dev/null +++ b/src/app/_components/timeline/RegistrationTimeline.tsx @@ -0,0 +1,32 @@ +import { useState } from 'react'; +import { Stepper, Button, Group } from '@mantine/core'; + +export default function RegistrationTimeline() { + const [active, setActive] = useState(1); + const nextStep = () => setActive((current) => (current < 3 ? current + 1 : current)); + const prevStep = () => setActive((current) => (current > 0 ? current - 1 : current)); + + return ( + <> + + + + + + + + {/* + + */} + + Completed, click back button to get to previous step + + + {/* + + + + */} + + ); +} \ No newline at end of file diff --git a/src/app/global.css b/src/app/global.css index 891070e..862abf4 100644 --- a/src/app/global.css +++ b/src/app/global.css @@ -2,9 +2,10 @@ margin: 0; padding: 0; box-sizing: border-box; - /* border: 1px solid black; */ + /* border: 1px solid black; */ } -html, body { +html, +body { height: 100vh; -} +} \ No newline at end of file diff --git a/src/app/image/changepw.png b/src/app/image/changepw.png new file mode 100644 index 0000000..2afd614 Binary files /dev/null and b/src/app/image/changepw.png differ diff --git a/src/app/image/changepw_b.jpg b/src/app/image/changepw_b.jpg new file mode 100644 index 0000000..2e7cebb Binary files /dev/null and b/src/app/image/changepw_b.jpg differ diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index c26d660..d13fe34 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react"; import { Text, Button, TextInput, PasswordInput, Title, Card, Group, Flex, Box, Image, Anchor, Stack } from "@mantine/core"; import { notifications } from "@mantine/notifications"; -import { Carousel } from '@mantine/carousel'; +// import { Carousel } from '@mantine/carousel'; import { Providers } from "@/app/providers"; import { useRouter } from "next/navigation"; import NextImage from "next/image"; @@ -24,7 +24,7 @@ export default function Login() { const [psw, SetPsw] = useState(""); const [captcha, setCaptcha] = useState(""); const [inputCaptcha, setInputCaptcha] = useState(""); - const ClientCarousel =dynamic(() => import ('./clientCarousel'),{ssr:false}); + const ClientCarousel = dynamic(() => import('./clientCarousel'), { ssr: false }); // const [isClient,SetIsClient] =useState(false); @@ -241,9 +241,9 @@ export default function Login() { width: "100%", height: '60vh', textAlign: "left", - marginTop:0, + marginTop: 0, }}> - +