feat : In home page "get statement" worked.
feat : After 5 minutes session timeout automatically. feat: realtime otp feature up
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Box, Button, Divider, Group, Image, Popover, Stack, Text, Title } from '@mantine/core';
|
||||
import { Box, Button, Divider, Group, Image, Modal, Popover, Stack, Text, Title } from '@mantine/core';
|
||||
import { IconBook, IconCurrencyRupee, IconHome, IconLogout, IconPhoneFilled, IconSettings } from '@tabler/icons-react';
|
||||
import Link from 'next/link';
|
||||
import { useRouter, usePathname } from "next/navigation";
|
||||
@@ -17,6 +17,8 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
const [userLastLoginDetails, setUserLastLoginDetails] = useState(null);
|
||||
const [custname, setCustname] = useState<string | null>(null);
|
||||
const isMobile = useMediaQuery("(max-width: 768px)");
|
||||
const [sessionModal, setSessionModal] = useState(false);
|
||||
const [countdown, setCountdown] = useState(30); // 30 sec countdown before auto logout
|
||||
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
|
||||
@@ -80,6 +82,8 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// When reload and click on back then logout
|
||||
useEffect(() => {
|
||||
// Push fake history state to trap navigation
|
||||
window.history.pushState(null, "", window.location.href);
|
||||
@@ -155,6 +159,58 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
fetchLoginTime();
|
||||
}, []);
|
||||
|
||||
// LOGOUT AFTER 5 MINUTES OF INACTIVITY OR TAB SWITCH
|
||||
useEffect(() => {
|
||||
const INACTIVITY_LIMIT = 5 * 60 * 1000; // 5 minutes
|
||||
let inactiveSince: number | null = null;
|
||||
let countdownTimer: NodeJS.Timeout;
|
||||
|
||||
const startCountdown = () => {
|
||||
setSessionModal(true);
|
||||
setCountdown(30); // start from 30 seconds
|
||||
|
||||
countdownTimer = setInterval(() => {
|
||||
setCountdown((prev) => {
|
||||
if (prev <= 1) {
|
||||
clearInterval(countdownTimer);
|
||||
doLogout(); // auto logout after countdown
|
||||
return 0;
|
||||
}
|
||||
return prev - 1;
|
||||
});
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
const handleVisibilityChange = () => {
|
||||
if (document.hidden) {
|
||||
// User switched tab → mark inactive time
|
||||
inactiveSince = Date.now();
|
||||
} else {
|
||||
// User returned to tab
|
||||
if (inactiveSince && Date.now() - inactiveSince >= INACTIVITY_LIMIT) {
|
||||
// Inactive for ≥ 5 min → show modal
|
||||
startCountdown();
|
||||
}
|
||||
inactiveSince = null; // reset inactiveSince
|
||||
}
|
||||
};
|
||||
|
||||
const handleUserActivity = () => {
|
||||
// Reset inactivity timestamp if user interacts
|
||||
inactiveSince = null;
|
||||
};
|
||||
|
||||
const activityEvents = ["mousemove", "keydown", "click", "scroll", "touchstart"];
|
||||
activityEvents.forEach((event) => window.addEventListener(event, handleUserActivity));
|
||||
document.addEventListener("visibilitychange", handleVisibilityChange);
|
||||
|
||||
return () => {
|
||||
activityEvents.forEach((event) => window.removeEventListener(event, handleUserActivity));
|
||||
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
||||
clearInterval(countdownTimer);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const navItems = [
|
||||
{ href: "/home", label: "Home", icon: IconHome },
|
||||
{ href: "/accounts", label: "Accounts", icon: IconBook },
|
||||
@@ -274,6 +330,32 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
{/* this model for session logout */}
|
||||
<Modal
|
||||
opened={sessionModal}
|
||||
onClose={() => setSessionModal(false)}
|
||||
withCloseButton={false}
|
||||
centered
|
||||
closeOnClickOutside={false} // <--- prevents clicking outside to close
|
||||
closeOnEscape={false} // <--- prevents ESC key
|
||||
title="Session Timeout Warning"
|
||||
>
|
||||
<Stack align="center" gap="md">
|
||||
<Text ta="center" c="red">
|
||||
You have been inactive for a while.
|
||||
<br />
|
||||
You’ll be logged out automatically in <b>{countdown}</b> seconds.
|
||||
</Text>
|
||||
<Group justify="center" mt="sm">
|
||||
{/* <Button color="gray" variant="default" onClick={() => setSessionModal(false)}>
|
||||
Stay Logged In
|
||||
</Button> */}
|
||||
<Button color="red" onClick={doLogout}>
|
||||
Logout Now
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Modal>
|
||||
|
||||
<Divider size="xs" color="blue" />
|
||||
|
||||
|
||||
Reference in New Issue
Block a user