feat : screen for user create and update
feat : unlocked users.
This commit is contained in:
@@ -1,183 +1,332 @@
|
||||
"use client";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Text, Box, Image, Button, Stack, Divider, Title } from "@mantine/core";
|
||||
import {
|
||||
Text,
|
||||
Box,
|
||||
Image,
|
||||
Stack,
|
||||
Divider,
|
||||
Title,
|
||||
Collapse,
|
||||
Group,
|
||||
UnstyledButton,
|
||||
} from "@mantine/core";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { Providers } from "@/app/providers";
|
||||
import { useRouter } from "next/navigation";
|
||||
import NextImage from "next/image";
|
||||
import logo from '@/app/image/logo1.jpg';
|
||||
import { IconEye, IconLogout, IconPhoneFilled, IconUsers, IconUserScreen } from "@tabler/icons-react";
|
||||
import logo from "@/app/image/logo1.jpg";
|
||||
import {
|
||||
IconLogout,
|
||||
IconPhoneFilled,
|
||||
IconUsers,
|
||||
IconChevronDown,
|
||||
IconChevronUp,
|
||||
IconSettings,
|
||||
} from "@tabler/icons-react";
|
||||
import UserConfiguration from "./UserConfiguration";
|
||||
import ViewUserConfiguration from "./ViewUserConfiguration";
|
||||
import UnlockedUsers from "./UnlockedUsers";
|
||||
|
||||
export default function Login() {
|
||||
const router = useRouter();
|
||||
const [authorized, SetAuthorized] = useState<boolean | null>(null);
|
||||
const [view, setView] = useState<'userConf' | 'view' | null>(null);
|
||||
const [lastLoginDetails, setLastLoginDetails] = useState(null);
|
||||
const [name, setName] = useState(null);
|
||||
const router = useRouter();
|
||||
const [authorized, SetAuthorized] = useState<boolean | null>(null);
|
||||
const [view, setView] = useState<string | null>(null);
|
||||
const [name, setName] = useState<string | null>(null);
|
||||
const [lastLoginDetails, setLastLoginDetails] = useState<string | null>(null);
|
||||
const [userMenuOpen, setUserMenuOpen] = useState(true);
|
||||
const [configMenuOpen, setConfigMenuOpen] = useState(false);
|
||||
|
||||
async function handleLogout(e: React.FormEvent) {
|
||||
e.preventDefault();
|
||||
localStorage.removeItem("admin_access_token");
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
router.push("/administrator/login");
|
||||
async function handleLogout(e: React.FormEvent) {
|
||||
e.preventDefault();
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
router.push("/administrator/login");
|
||||
}
|
||||
|
||||
async function handleFetchUserDetails(e: React.FormEvent) {
|
||||
e.preventDefault();
|
||||
const token = localStorage.getItem("admin_access_token");
|
||||
const response = await fetch("/api/auth/admin/admin_details", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Login-Type": "Admin",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
const data = await response.json();
|
||||
if (response.ok) {
|
||||
return data;
|
||||
} else if (response.status === 401 || data.message === "invalid or expired token") {
|
||||
localStorage.removeItem("admin_access_token");
|
||||
router.push("/administrator/login");
|
||||
} else {
|
||||
notifications.show({
|
||||
withBorder: true,
|
||||
color: "red",
|
||||
title: "Please try again later",
|
||||
message: "Unable to fetch timestamp, please try again later",
|
||||
autoClose: 5000,
|
||||
});
|
||||
}
|
||||
async function handleFetchUserDetails(e: React.FormEvent) {
|
||||
e.preventDefault();
|
||||
const token = localStorage.getItem("admin_access_token");
|
||||
const response = await fetch('/api/auth/admin/admin_details', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
"X-Login-Type": "Admin",
|
||||
'Authorization': `Bearer ${token}`
|
||||
},
|
||||
});
|
||||
const data = await response.json();
|
||||
// console.log(data)
|
||||
if (response.ok) {
|
||||
return data;
|
||||
}
|
||||
else if (response.status === 401 || data.message === 'invalid or expired token') {
|
||||
localStorage.removeItem("admin_access_token");
|
||||
router.push('/administrator/login');
|
||||
}
|
||||
else {
|
||||
notifications.show({
|
||||
withBorder: true,
|
||||
color: "red",
|
||||
title: "Please try again later",
|
||||
message: "Unable to fetch timestamp, please try again later",
|
||||
autoClose: 5000,
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const token = localStorage.getItem("admin_access_token");
|
||||
if (!token) {
|
||||
SetAuthorized(false);
|
||||
router.push("/administrator/login/");
|
||||
} else {
|
||||
SetAuthorized(true);
|
||||
const fetchLoginTime = async () => {
|
||||
const result = await handleFetchUserDetails({
|
||||
preventDefault: () => { },
|
||||
} as React.FormEvent);
|
||||
if (result) {
|
||||
setLastLoginDetails(result.last_login);
|
||||
setName(result.name);
|
||||
}
|
||||
};
|
||||
fetchLoginTime();
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const token = localStorage.getItem("admin_access_token");
|
||||
if (!token) {
|
||||
SetAuthorized(false);
|
||||
router.push("/administrator/login/");
|
||||
} else {
|
||||
SetAuthorized(true);
|
||||
const fetchLoginTime = async () => {
|
||||
const result = await handleFetchUserDetails({ preventDefault: () => { } } as React.FormEvent);
|
||||
if (result) {
|
||||
setLastLoginDetails(result.last_login);
|
||||
setName(result.name);
|
||||
}
|
||||
};
|
||||
fetchLoginTime();
|
||||
}
|
||||
}, []);
|
||||
if (!authorized) return null;
|
||||
|
||||
const handleClick = (type: 'UserConf' | 'ViewUser' | 'logout') => {
|
||||
if (type === 'UserConf') {
|
||||
setView('userConf');
|
||||
} else if (type === 'ViewUser') {
|
||||
setView('view');
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Providers>
|
||||
<div style={{ backgroundColor: "#f8f9fa", width: "100%", height: "100%" }}>
|
||||
{/* Header */}
|
||||
<Box
|
||||
style={{
|
||||
height: "60px",
|
||||
position: "relative",
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "flex-start",
|
||||
background:
|
||||
"linear-gradient(15deg,rgba(10, 114, 40, 1) 55%, rgba(101, 101, 184, 1) 100%)",
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
fit="cover"
|
||||
src={logo}
|
||||
component={NextImage}
|
||||
alt="ebanking"
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
/>
|
||||
<Title
|
||||
order={2}
|
||||
style={{
|
||||
fontFamily: "Roboto",
|
||||
position: "absolute",
|
||||
top: "30%",
|
||||
left: "6%",
|
||||
color: "White",
|
||||
}}
|
||||
>
|
||||
THE KANGRA CENTRAL CO-OPERATIVE BANK LTD.
|
||||
</Title>
|
||||
<Text
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "80%",
|
||||
color: "white",
|
||||
textShadow: "1px 1px 2px black",
|
||||
}}
|
||||
>
|
||||
<IconPhoneFilled size={18} /> Toll Free No : 1800-180-8008
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
if (!authorized) return null;
|
||||
{/* Layout */}
|
||||
<Box style={{ display: "flex", height: "90vh" }}>
|
||||
{/* Sidebar */}
|
||||
<Box
|
||||
style={{
|
||||
width: 240,
|
||||
background: "#02a355",
|
||||
padding: "0.75rem",
|
||||
borderRight: "1px solid #ccc",
|
||||
color: "white",
|
||||
fontSize: "13px",
|
||||
}}
|
||||
>
|
||||
<Title order={4} c="white" style={{ textAlign: "center", marginBottom: "6px" }}>
|
||||
Admin Portal
|
||||
</Title>
|
||||
<Divider my="xs" color="rgba(255,255,255,0.3)" />
|
||||
|
||||
if (authorized) {
|
||||
return (
|
||||
<Providers>
|
||||
<div style={{ backgroundColor: "#f8f9fa", width: "100%", height: "100%", }}>
|
||||
{/* Header */}
|
||||
<Box
|
||||
style={{
|
||||
height: "60px",
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
display: "flex",
|
||||
justifyContent: "flex-start",
|
||||
background: "linear-gradient(15deg,rgba(10, 114, 40, 1) 55%, rgba(101, 101, 184, 1) 100%)",
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
fit="cover"
|
||||
src={logo}
|
||||
component={NextImage}
|
||||
alt="ebanking"
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
/>
|
||||
<Title
|
||||
order={2}
|
||||
style={{
|
||||
fontFamily: 'Roboto',
|
||||
position: 'absolute',
|
||||
top: '30%',
|
||||
left: '6%',
|
||||
color: 'White',
|
||||
transition: "opacity 0.5s ease-in-out",
|
||||
}}
|
||||
>
|
||||
THE KANGRA CENTRAL CO-OPERATIVE BANK LTD.
|
||||
</Title>
|
||||
<Text
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
left: '80%',
|
||||
color: 'white',
|
||||
textShadow: '1px 1px 2px black',
|
||||
}}
|
||||
>
|
||||
<IconPhoneFilled size={20} /> Toll Free No : 1800-180-8008
|
||||
</Text>
|
||||
</Box>
|
||||
{/* layout and */}
|
||||
<Box style={{ display: 'flex', height: '90vh' }}>
|
||||
{/* Sidebar manually placed under header */}
|
||||
<Box
|
||||
style={{
|
||||
width: 250,
|
||||
background: "#ebf5f5ff",
|
||||
// background: "linear-gradient(90deg,rgba(42, 123, 155, 1) 0%, rgba(87, 199, 133, 1) 30%)",
|
||||
padding: '1rem',
|
||||
borderRight: '1px solid #ccc',
|
||||
}}
|
||||
>
|
||||
<Title order={3} style={{ textAlign: 'center' }}>Admin Portal</Title>
|
||||
<Divider my="xs" label="Menu" labelPosition="center" />
|
||||
<Stack>
|
||||
<Text td="underline" variant="light" style={{ cursor: 'pointer' }} onClick={() => handleClick('UserConf')}>
|
||||
<IconUsers size="15" /> User Configuration
|
||||
</Text>
|
||||
<Text td="underline" variant="light" style={{ cursor: 'pointer' }} onClick={() => handleClick('ViewUser')}>
|
||||
<IconEye size="15" /> View User Configuration
|
||||
</Text>
|
||||
<Text td="underline" variant="light" style={{ cursor: 'pointer' }} onClick={handleLogout}>
|
||||
<IconLogout size="15" /> Logout
|
||||
</Text>
|
||||
</Stack>
|
||||
</Box>
|
||||
{/* User Maintenance */}
|
||||
<UnstyledButton
|
||||
onClick={() => setUserMenuOpen(!userMenuOpen)}
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
width: "100%",
|
||||
padding: "5px 6px",
|
||||
borderRadius: "4px",
|
||||
backgroundColor: "rgba(255,255,255,0.1)",
|
||||
color: "white",
|
||||
fontSize: "13px",
|
||||
}}
|
||||
>
|
||||
<Group gap="xs">
|
||||
<IconUsers size={15} />
|
||||
<Text fw={600} size="sm">
|
||||
User Maintenance
|
||||
</Text>
|
||||
</Group>
|
||||
{userMenuOpen ? <IconChevronUp size={15} /> : <IconChevronDown size={15} />}
|
||||
</UnstyledButton>
|
||||
<Collapse in={userMenuOpen}>
|
||||
<Stack gap={2} pl="md" mt={4}>
|
||||
<Box
|
||||
onClick={() => setView("userConf")}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
color: view === "userConf" ? "#02a355" : "white",
|
||||
backgroundColor: view === "userConf" ? "white" : "transparent",
|
||||
borderRadius: "3px",
|
||||
padding: "3px 6px",
|
||||
transition: "0.2s",
|
||||
}}
|
||||
>
|
||||
• User Create / Update
|
||||
</Box>
|
||||
<Box
|
||||
onClick={() => setView("viewUser")}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
color: view === "viewUser" ? "#02a355" : "white",
|
||||
backgroundColor: view === "viewUser" ? "white" : "transparent",
|
||||
borderRadius: "3px",
|
||||
padding: "3px 6px",
|
||||
transition: "0.2s",
|
||||
}}
|
||||
>
|
||||
• Users Status
|
||||
</Box>
|
||||
<Box
|
||||
onClick={() => setView("unlockUser")}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
color: view === "unlockUser" ? "#02a355" : "white",
|
||||
backgroundColor: view === "unlockUser" ? "white" : "transparent",
|
||||
borderRadius: "3px",
|
||||
padding: "3px 6px",
|
||||
transition: "0.2s",
|
||||
}}
|
||||
>
|
||||
• User Unlock
|
||||
</Box>
|
||||
</Stack>
|
||||
</Collapse>
|
||||
|
||||
{/* Main Content Area */}
|
||||
<Stack style={{ flex: 1, padding: '1rem' }}>
|
||||
<Box>
|
||||
<Text c="Blue" size="lg" fs='italic'>Welcome ,{name} </Text>
|
||||
<Text size="xs" c="gray" style={{ fontFamily: "inter", fontSize: '13px' }}>
|
||||
Last logged in at {lastLoginDetails ? new Date(lastLoginDetails).toLocaleString() : "N/A"}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
{view === 'userConf' && <UserConfiguration />}
|
||||
{view === 'view' && <Text size="xl"><ViewUserConfiguration /></Text>}
|
||||
{!view &&
|
||||
<Text size="xl">Welcome To The Admin Portal</Text>
|
||||
}
|
||||
</Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
<Divider size="xs" color='#99c2ff' />
|
||||
<Text size="sm" style={{ textAlign: "center" }}>© 2025 The Kangra Central Co-Operative Bank</Text>
|
||||
</div>
|
||||
</Providers>
|
||||
);
|
||||
}
|
||||
{/* Configuration */}
|
||||
<UnstyledButton
|
||||
onClick={() => setConfigMenuOpen(!configMenuOpen)}
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
width: "100%",
|
||||
padding: "5px 6px",
|
||||
marginTop: "8px",
|
||||
borderRadius: "4px",
|
||||
backgroundColor: "rgba(255,255,255,0.1)",
|
||||
color: "white",
|
||||
fontSize: "13px",
|
||||
}}
|
||||
>
|
||||
<Group gap="xs">
|
||||
<IconSettings size={15} />
|
||||
<Text fw={600} size="sm">
|
||||
Configuration
|
||||
</Text>
|
||||
</Group>
|
||||
{configMenuOpen ? <IconChevronUp size={15} /> : <IconChevronDown size={15} />}
|
||||
</UnstyledButton>
|
||||
<Collapse in={configMenuOpen}>
|
||||
<Stack gap={2} pl="md" mt={4}>
|
||||
<Box
|
||||
onClick={() => setView("ifscConfig")}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
color: view === "ifscConfig" ? "#02a355" : "white",
|
||||
backgroundColor: view === "ifscConfig" ? "white" : "transparent",
|
||||
borderRadius: "3px",
|
||||
padding: "3px 6px",
|
||||
transition: "0.2s",
|
||||
}}
|
||||
>
|
||||
• IFSC Configuration
|
||||
</Box>
|
||||
</Stack>
|
||||
</Collapse>
|
||||
|
||||
<Divider my="xs" color="rgba(255,255,255,0.3)" />
|
||||
<Text
|
||||
onClick={handleLogout}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "4px",
|
||||
color: "white",
|
||||
marginTop: "8px",
|
||||
fontSize: "13px",
|
||||
}}
|
||||
>
|
||||
<IconLogout size={14} /> Logout
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
{/* Main Content */}
|
||||
<Stack style={{ flex: 1, padding: "1rem" }}>
|
||||
<Box>
|
||||
<Text c="Blue" size="sm" fs="italic">
|
||||
Welcome, {name}
|
||||
</Text>
|
||||
<Text size="xs" c="gray" style={{ fontFamily: "inter" }}>
|
||||
Last logged in at{" "}
|
||||
{lastLoginDetails
|
||||
? new Date(lastLoginDetails).toLocaleString()
|
||||
: "N/A"}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
{view === "userConf" && <UserConfiguration />}
|
||||
{view === "viewUser" && <ViewUserConfiguration />}
|
||||
{view === "unlockUser" && <UnlockedUsers />}
|
||||
{view === "ifscConfig" && (
|
||||
<Text size="sm" c="gray">
|
||||
IFSC Configuration Page Coming Soon
|
||||
</Text>
|
||||
)}
|
||||
{!view && (
|
||||
<>
|
||||
<Text size="xl" c="gray">
|
||||
Welcome To The Internet Banking Admin Portal
|
||||
</Text>
|
||||
<Text size="sm" c="black">
|
||||
Choose the service from the menu.
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
|
||||
<Divider size="xs" color="#99c2ff" />
|
||||
<Text size="xs" style={{ textAlign: "center" }}>
|
||||
© 2025 The Kangra Central Co-Operative Bank
|
||||
</Text>
|
||||
</div>
|
||||
</Providers>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user