diff --git a/src/app/eMandate/login/page.tsx b/src/app/eMandate/login/page.tsx index f9e156d..a835ef6 100644 --- a/src/app/eMandate/login/page.tsx +++ b/src/app/eMandate/login/page.tsx @@ -88,6 +88,7 @@ export default function Login() { method: 'POST', headers: { 'Content-Type': 'application/json', + 'X-Login-Type': 'emandate', }, body: JSON.stringify({ customerNo: CIF, @@ -103,33 +104,34 @@ export default function Login() { message: data?.error || "Internal Server Error", autoClose: 5000, }); - localStorage.removeItem("access_token"); + regenerateCaptcha() + localStorage.removeItem("mandate_token"); localStorage.clear(); sessionStorage.clear(); return; - } setIsLogging(true); if (response.ok) { console.log(data); const token = data.token; - localStorage.setItem("emandate_token", token); + localStorage.setItem("mandate_token", token); // localStorage.setItem("pswExpiryDate", data.loginPswExpiry); if (data.FirstTimeLogin === true) { notifications.show({ withBorder: true, color: "red", title: "Error", - message: "Please set your credential into Internet Banking before login.", + message: "Please go to Internet Banking, set your credentials, and then try logging in here again.", autoClose: 5000, }); } else { - router.push("/mandate_page"); + router.push("/eMandate/mandate_page"); } } else { + regenerateCaptcha(); setIsLogging(false); notifications.show({ withBorder: true, diff --git a/src/app/eMandate/mandate_page/page.tsx b/src/app/eMandate/mandate_page/page.tsx index 4b60ee9..88a1450 100644 --- a/src/app/eMandate/mandate_page/page.tsx +++ b/src/app/eMandate/mandate_page/page.tsx @@ -1,5 +1,5 @@ "use client"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { Text, Title, @@ -13,12 +13,16 @@ import { Container, ActionIcon, Divider, + Modal, + TextInput, } from "@mantine/core"; import { Providers } from "@/app/providers"; import { useRouter } from "next/navigation"; import NextImage from "next/image"; import logo from "@/app/image/logo1.jpg"; -import { IconLogout } from "@tabler/icons-react"; +import { IconLogout, IconX } from "@tabler/icons-react"; +import { notifications } from "@mantine/notifications"; +import { useMediaQuery } from "@mantine/hooks"; type Mandate = { id: string; @@ -33,15 +37,29 @@ type Mandate = { const MandateCard = ({ mandate, - onAccept, - onReject, + onAction, }: { mandate: Mandate; - onAccept: (id: string) => void; - onReject: (id: string) => void; + onAction: (id: string, action: "accept" | "reject") => void; }) => { const [agreed, setAgreed] = useState(false); + const handleClick = (action: "accept" | "reject") => { + if (!agreed) { + notifications.show({ + withBorder: true, + icon: , + color: "red", + title: "Error", + message: + "Please agree to the debit of mandate processing charges first.", + autoClose: 4000, + }); + return; + } + onAction(mandate.id, action); + }; + return ( {mandate.category} @@ -62,19 +80,10 @@ const MandateCard = ({ /> - - @@ -84,6 +93,64 @@ const MandateCard = ({ export default function MandatePage() { const router = useRouter(); + const [authorized, setAuthorized] = useState(null); + const [custname, setCustname] = useState(null); + const isMobile = useMediaQuery("(max-width: 768px)"); + + // OTP Modal states + const [otpModalOpen, setOtpModalOpen] = useState(false); + const [otp, setOtp] = useState(""); + const [pendingAction, setPendingAction] = useState<{ id: string; action: "accept" | "reject" } | null>(null); + + useEffect(() => { + const token = localStorage.getItem("mandate_token"); + if (!token) { + setAuthorized(false); + router.push("/eMandate/login"); + } else { + setAuthorized(true); + handleFetchUserName(); + } + }, []); + + const handleLogout = () => { + localStorage.removeItem("mandate_token"); + localStorage.removeItem("user_name"); + localStorage.removeItem("userMobNo"); + router.push("/eMandate/login"); + }; + + const handleFetchUserName = async () => { + try { + const token = localStorage.getItem("mandate_token"); + const response = await fetch("/api/customer", { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + }); + if (!response.ok) throw new Error(); + const data = await response.json(); + if (Array.isArray(data) && data.length > 0) { + const name = data[0].custname; + const mobileNumber = data[0].mobileno; + localStorage.setItem("user_name", name); + localStorage.setItem("userMobNo", mobileNumber); + setCustname(name); + } + } catch { + notifications.show({ + withBorder: true, + color: "red", + title: "Please try again later", + message: "Unable to Fetch, Please try again later", + autoClose: 5000, + }); + } + }; + + // Dummy mandates const [mandates] = useState([ { id: "1", @@ -105,21 +172,95 @@ export default function MandatePage() { firstCollection: "2025-10-01", finalCollection: "2030-10-01", }, - ]); - const handleAccept = (id: string) => { - alert(`Accepted mandate ${id}`); + // STEP 1: When Accept/Reject pressed → call send OTP API + const handleMandateAction = async (id: string, action: "accept" | "reject") => { + try { + const response = await fetch("/api/otp/send", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + mobileNumber: '7890544527', + type: 'EMandate' + }), + }); + const data = await response.json(); + console.log(data) + if (!response.ok) throw new Error("Failed to send OTP"); + + notifications.show({ + withBorder: true, + color: "green", + title: "OTP Sent", + message: "An OTP has been sent to your registered mobile number.", + autoClose: 4000, + }); + + setPendingAction({ id, action }); + setOtp(""); + setOtpModalOpen(true); + } catch (err) { + notifications.show({ + withBorder: true, + color: "red", + title: "Error", + message: "Failed to send OTP. Please try again.", + autoClose: 5000, + }); + } }; - const handleReject = (id: string) => { - alert(`Rejected mandate ${id}`); - }; - const handleLogout = () => { - localStorage.removeItem("access_token"); - router.push("/eMandate/login"); // redirect to login page + // STEP 2: Verify OTP and complete action + const handleOtpSubmit = async () => { + // if (!otp) { + // notifications.show({ + // withBorder: true, + // color: "red", + // title: "Invalid Input", + // message: "Please enter OTP before proceed", + // autoClose: 5000, + // }); + // } + if (!pendingAction) return; + try { + const response = await fetch(`/api/otp/verify?mobileNumber=${7890544527}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + otp: otp, + }), + }); + + if (!response.ok) throw new Error("Invalid OTP"); + + notifications.show({ + withBorder: true, + color: "green", + title: "Success", + message: `Mandate ${pendingAction.action}ed successfully!`, + autoClose: 4000, + }); + + setOtpModalOpen(false); + setPendingAction(null); + } catch { + notifications.show({ + withBorder: true, + color: "red", + title: "Error", + message: "Invalid OTP. Please try again.", + autoClose: 4000, + }); + } }; + if (!authorized) return null; + return (
- + ebanking - - THE KANGRA CENTRAL CO-OPERATIVE BANK LTD. - + /> + {!isMobile && ( + + THE KANGRA CENTRAL CO-OPERATIVE BANK LTD. + + )} - {/* Logout Icon */} - - - + {isMobile ? ( + + + + ) : ( + + + +
); diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 7eee408..a762ba1 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -129,6 +129,7 @@ export default function Login() { message: data?.error || "Internal Server Error", autoClose: 5000, }); + regenerateCaptcha(); localStorage.removeItem("access_token"); localStorage.clear(); sessionStorage.clear(); @@ -150,6 +151,7 @@ export default function Login() { } else { + regenerateCaptcha(); setIsLogging(false); notifications.show({ withBorder: true, @@ -218,7 +220,7 @@ export default function Login() { }); const data = await res.json(); - console.log(data) + // console.log(data) if (!res.ok) { notifications.show({ color: "red",