From 833453241c30e14eb6b886c34c23621bcbf8efd7 Mon Sep 17 00:00:00 2001 From: "tomosa.sarkar" Date: Mon, 8 Sep 2025 13:15:33 +0530 Subject: [PATCH] Wip : Admin module in progress --- TODO.md | 4 + instruction.md | 8 +- .../statement_download/CsvGenerator.tsx | 2 +- .../statement_download/PdfGenerator.tsx | 2 +- .../administrator/home/UserConfiguration.tsx | 210 +++++++++++++++--- src/app/administrator/home/page.tsx | 21 +- src/app/login/page.tsx | 4 +- 7 files changed, 205 insertions(+), 46 deletions(-) diff --git a/TODO.md b/TODO.md index 1051ef8..67530c7 100644 --- a/TODO.md +++ b/TODO.md @@ -17,6 +17,10 @@ - In Every OTP page "Resend button" & 5 min timing of expiry. - OTP binding with actual mobile number. - IN settings page NOTE position Fixing. +- Admin page + - give rights + - view rights (Pending) +- Forget Password diff --git a/instruction.md b/instruction.md index 96ac0e8..e0f6669 100644 --- a/instruction.md +++ b/instruction.md @@ -81,6 +81,12 @@ scp -P 9022 Smsservice/smsserviceapplication.jar @localhost:/home/ ${headerHTML} -

Account Statement

+

Account Statement

Account No: ${accountNo}

Available Balance: ₹ ${parseFloat( balance diff --git a/src/app/administrator/home/UserConfiguration.tsx b/src/app/administrator/home/UserConfiguration.tsx index 1a47d42..11deebb 100644 --- a/src/app/administrator/home/UserConfiguration.tsx +++ b/src/app/administrator/home/UserConfiguration.tsx @@ -1,8 +1,10 @@ import React, { useState } from 'react'; -import { TextInput, Button, Title, Stack, Radio, Group, Text, Divider, LoadingOverlay, Box, Modal, Card, Checkbox } from '@mantine/core'; +import { TextInput, Button, Title, Stack, Group, Text, Divider, LoadingOverlay, Box, Modal, Checkbox } from '@mantine/core'; import { notifications } from '@mantine/notifications'; +import { useRouter } from "next/navigation"; export default function UserConfiguration() { + const router = useRouter(); const [CIF, setCIF] = useState(''); const [userDetails, setUserDetails] = useState(null); const [loading, setLoading] = useState(false); @@ -12,9 +14,9 @@ export default function UserConfiguration() { const [showPreviewModal, setShowPreviewModal] = useState(false); const [confirmedPreview, setConfirmedPreview] = useState(false); const [ibEnabled, setIbEnabled] = useState(false); - const [ibAccess, setIbAccess] = useState<"read" | "transaction" | "">(""); + const [ibAccess, setIbAccess] = useState<"2" | "1" | "">(""); const [mbEnabled, setMbEnabled] = useState(false); - const [mbAccess, setMbAccess] = useState<"read" | "transaction" | "">(""); + const [mbAccess, setMbAccess] = useState<"2" | "1" | "">(""); const isValidated = !!userDetails; const canSubmit = isValidated && !!savingsAccount && confirmedPreview; @@ -60,6 +62,10 @@ export default function UserConfiguration() { address: user.custaddress, activeAccount: user.activeAccounts, }); + if (!user.mobileno) { + localStorage.setItem("user_mob_no", user.mobileno); + setAccountError('User not have any registered Mobile Number'); + } } else { throw new Error('User not found or data format incorrect'); } @@ -74,7 +80,31 @@ export default function UserConfiguration() { } }; - const handleSubmit = () => { + const handlePreview = () => { + const hasRight = ibAccess || mbAccess; + const hasSavings = savingsAccount; + + if (!hasRight) { + notifications.show({ + title: "Rights Required", + message: "Please select at least one rights (Internet Banking or Mobile Banking).", + color: "red", + }); + return; + } + + if (!hasSavings) { + notifications.show({ + title: "Savings Account Required", + message: "User must have at least one Savings account.", + color: "red", + }); + return; + } + setShowPreviewModal(true); + }; + + const handleSubmit = async () => { if (!canSubmit) { notifications.show({ color: 'red', @@ -84,26 +114,113 @@ export default function UserConfiguration() { return; } else { - const rightsData = { - CIF, - }; - console.log('Submitting rights:', rightsData); - notifications.show({ - color: 'blue', - title: 'Submitted', - message: `User -${CIF} rights submitted successfully.`, - }); - } - setSavingsAccount(null); - setUserDetails(null); - setCIF(''); - }; + try { + const token = localStorage.getItem("admin_access_token"); + const response = await fetch('/api/auth/admin/user/rights', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }, + body: JSON.stringify({ + CIF: CIF, + ib_access_level: ibAccess, + mb_access_level: mbAccess + }), + }); + const data = await response.json(); + if (response.ok) { + if (data?.otp) { + const otp = data.otp; + try { + const otp_response = await fetch('/api/otp/send', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + mobileNumber: localStorage.getItem("user_mob_no"), + type: "REGISTRATION", + userOtp: otp + }), + }); + // const otp_result = await otp_response.json(); + if (otp_response.ok) { + notifications.show({ + color: 'blue', + title: 'Submitted', + message: `User ${CIF} rights submitted successfully. The password has been sent to the user as an OTP.`, + }); + } + } + catch (err: any) { + notifications.show({ + color: 'red', + title: 'Failed to Send', + message: `Rights for User ${CIF} saved successfully. Message delivery failed.`, + autoClose: false, + }); + } + } + if(data?.message){ + try { + const otp_response = await fetch('/api/otp/send', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + mobileNumber: localStorage.getItem("user_mob_no"), + type: "RIGHT_UPDATE", + }), + }); + if (otp_response.ok) { + notifications.show({ + color: 'blue', + title: 'Submitted', + message: `User ${CIF} rights updated successfully. The confirmation has been sent to the user.`, + }); + } + } + catch (err: any) { + notifications.show({ + color: 'red', + title: 'Failed to Send', + message: `Rights for User ${CIF} saved successfully. Message delivery failed.`, + autoClose: false, + }); + } + } + } + else if (response.status === 401 || data.message === 'invalid or expired token') { + localStorage.removeItem("admin_access_token"); + localStorage.clear(); + sessionStorage.clear(); + router.push('/administrator/login'); + } + } + catch (err: any) { + notifications.show({ + color: 'red', + title: 'Failed -Right', + message: `Can not Processed user -${CIF} rights.`, + autoClose: false, + }); + } + finally { + setSavingsAccount(null); + setUserDetails(null); + setCIF(''); + setConfirmedPreview(false); + } + }; + } const handleMainAction = () => { if (!isValidated) { handleValidate(); } else if (!confirmedPreview) { - setShowPreviewModal(true); + handlePreview(); } else if (isValidated && confirmedPreview) { handleSubmit(); } @@ -176,6 +293,7 @@ export default function UserConfiguration() { { setIbEnabled(e.currentTarget.checked); @@ -185,16 +303,16 @@ export default function UserConfiguration() { setIbAccess("transaction")} + disabled={!ibEnabled || isValidated && confirmedPreview} + checked={ibAccess === "1"} + onChange={() => setIbAccess("1")} /> setIbAccess("read")} + disabled={!ibEnabled || isValidated && confirmedPreview} + checked={ibAccess === "2"} + onChange={() => setIbAccess("2")} /> @@ -206,6 +324,7 @@ export default function UserConfiguration() { { setMbEnabled(e.currentTarget.checked); @@ -215,16 +334,16 @@ export default function UserConfiguration() { setMbAccess("transaction")} + disabled={!mbEnabled || isValidated && confirmedPreview} + checked={mbAccess === "1"} + onChange={() => setMbAccess("1")} /> setMbAccess("read")} + disabled={!mbEnabled || isValidated && confirmedPreview} + checked={mbAccess === "2"} + onChange={() => setMbAccess("2")} /> @@ -247,7 +366,34 @@ export default function UserConfiguration() { centered > - + CIF: {CIF} + Savings Account: {savingsAccount} + Mobile Number: {userDetails?.mobile ?? "N/A"} + + + diff --git a/src/app/administrator/home/page.tsx b/src/app/administrator/home/page.tsx index bdb8b38..91a736d 100644 --- a/src/app/administrator/home/page.tsx +++ b/src/app/administrator/home/page.tsx @@ -6,7 +6,7 @@ import { Providers } from "@/app/providers"; import { useRouter } from "next/navigation"; import NextImage from "next/image"; import logo from '@/app/image/logo1.jpg'; -import { IconLogout, IconPhoneFilled, IconUsers, IconUserScreen } from "@tabler/icons-react"; +import { IconEye, IconLogout, IconPhoneFilled, IconUsers, IconUserScreen } from "@tabler/icons-react"; import UserConfiguration from "./UserConfiguration"; export default function Login() { @@ -19,6 +19,8 @@ export default function Login() { async function handleLogout(e: React.FormEvent) { e.preventDefault(); localStorage.removeItem("admin_access_token"); + localStorage.clear(); + sessionStorage.clear(); router.push("/administrator/login"); } async function handleFetchUserDetails(e: React.FormEvent) { @@ -82,7 +84,7 @@ export default function Login() { if (authorized) { return ( -

+
{/* Header */} {/* layout and */} - + {/* Sidebar manually placed under header */} handleClick('UserConf')}> - User Configuration + User Configuration handleClick('ViewUser')}> - View Users + View User Configuration - Logout + Logout {/* Main Content Area */} - + Welcome ,{name} @@ -163,13 +165,14 @@ export default function Login() { {view === 'userConf' && } - {view === 'view' && view} + {view === 'view' && Feature will be available soon ....} {!view && Welcome To The Admin Portal } + © 2025 The Kangra Central Co-Operative Bank
); diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 2ee2733..f8c0a7d 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -290,12 +290,12 @@ export default function Login() { mt="sm" /> - router.push("/ValidateUser")} > Forgot Password? - + */} {captcha}