jai #4

Merged
jaipandey merged 4 commits from jai into master 2025-07-15 10:08:58 +00:00
6 changed files with 293 additions and 225 deletions
Showing only changes of commit 7fffb22e09 - Show all commits

View File

@ -110,6 +110,12 @@ const Account = () => {
// Add more cards here if needed // Add more cards here if needed
]; ];
}; };
const [activeAccountId, setActiveAccountId] = useState<string | null>(
JSON.parse(sessionStorage.getItem('activeAccountId') || 'null')
);
console.log("activeAccountId Trans.",activeAccountId)
// const { accountId } = useParams<{ accountId: string }>(); // const { accountId } = useParams<{ accountId: string }>();
const [transactions, setTransactions] = useState<Transaction[]>([]); const [transactions, setTransactions] = useState<Transaction[]>([]);
const [selectedTransactions, setSelectedTransactions] = useState<number[]>([]); const [selectedTransactions, setSelectedTransactions] = useState<number[]>([]);
@ -121,25 +127,52 @@ const Account = () => {
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const getUserDetails = async () => { // const getUserDetails = async () => {
try { // try {
let res = await api.get('/api/user/details') // let res = await api.get('/api/user/details')
let accountIDData = res?.data?.account?.id // let accountIDData = res?.data?.account?.id
setAccountID(accountIDData) // setAccountID(accountIDData)
} catch (error) { // } catch (error) {
console.log(error) // console.log(error)
} // }
} // }
useEffect(() => { // useEffect(() => {
getUserDetails() // getUserDetails()
}, []) // }, [])
// Listen for sessionStorage changes
useEffect(() => {
const handleStorageChange = (e: StorageEvent) => {
if (e.key === 'activeAccountId') {
const newActiveAccountId = e.newValue ? JSON.parse(e.newValue) : null;
setActiveAccountId(newActiveAccountId);
}
};
// Listen for storage events (works for changes from other tabs)
window.addEventListener('storage', handleStorageChange);
// Custom event listener for same-tab changes
const handleCustomStorageChange = (e: CustomEvent) => {
if (e.detail.key === 'activeAccountId') {
setActiveAccountId(e.detail.newValue);
}
};
window.addEventListener('sessionStorageChange', handleCustomStorageChange as EventListener);
return () => {
window.removeEventListener('storage', handleStorageChange);
window.removeEventListener('sessionStorageChange', handleCustomStorageChange as EventListener);
};
}, []);
const getDashboardData = async () => { const getDashboardData = async () => {
setIsLoading(true) setIsLoading(true)
const payload = { const payload = {
account: accountID account: activeAccountId
}; };
try { try {
@ -154,50 +187,51 @@ const Account = () => {
} }
}; };
useEffect(() => {
if (accountID) {
getDashboardData()
fetchTransactions();
}
}, [accountID]);
const handleOpenModal = () => {
setIsModalOpen(true);
};
const fetchTransactions = async () => { const fetchTransactions = async () => {
console.log("fetchTransactions") console.log("fetchTransactions")
try { try {
const response = await api(`/api/accounts/${accountID}/transactions`); const response = await api(`/api/accounts/${activeAccountId}/transactions`);
setTransactions(response.data || []); setTransactions(response.data || []);
} catch (error) { } catch (error) {
console.error("Error fetching transactions:", error); console.error("Error fetching transactions:", error);
} }
}; };
useEffect(() => {
if (activeAccountId) {
getDashboardData()
fetchTransactions();
}
}, [activeAccountId]);
const handleOpenModal = () => {
setIsModalOpen(true);
};
// useEffect(() => { // useEffect(() => {
// if (accountID) fetchTransactions(); // if (accountID) fetchTransactions();
// }, [accountID]); // }, [accountID]);
const getAccountDetails = async () => { // const getAccountDetails = async () => {
try { // try {
let res = await api.get('/api/user/accounts') // let res = await api.get('/api/user/accounts')
let items = res?.data // let items = res?.data
setAccountsData(items) // setAccountsData(items)
} catch (error) { // } catch (error) {
console.log(error) // console.log(error)
} // }
} // }
useEffect(() => { // useEffect(() => {
getAccountDetails() // getAccountDetails()
}, []) // }, [])
const navigate = useNavigate(); const navigate = useNavigate();
const handleTransactionClick = (id: number) => { const handleTransactionClick = (id: number) => {
navigate(`/accounts/${accountID}/transactions/${id}`); navigate(`/accounts/${activeAccountId}/transactions/${id}`);
}; };
const handleInvite = async (data: { i_accountName: number; email: string; role: string }) => { const handleInvite = async (data: { i_accountName: number; email: string; role: string }) => {
@ -235,7 +269,7 @@ const Account = () => {
return ( return (
<> <>
<Cards type="transactions" onOpenModal={handleOpenModal} cards={cards} <Cards type="transactions" onOpenModal={handleOpenModal} cards={cards}
isLoading={isLoading}/> isLoading={isLoading} />
{transactions.length > 0 && ( {transactions.length > 0 && (
<div className="overflow-x-auto py-2"> <div className="overflow-x-auto py-2">
<table className="min-w-full text-sm border border-gray-200 rounded bg-white shadow-sm"> <table className="min-w-full text-sm border border-gray-200 rounded bg-white shadow-sm">

View File

@ -1,21 +1,13 @@
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
// import { useSelector } from 'react-redux';
import { Link, useLocation, useNavigate } from 'react-router-dom'; import { Link, useLocation, useNavigate } from 'react-router-dom';
import { FaSignOutAlt, FaUser, FaBuilding, FaChevronDown, FaCheck } from "react-icons/fa"; import { FaSignOutAlt, FaUser, FaBuilding, FaChevronDown, FaCheck } from "react-icons/fa";
import api from '../../config/api'; import api from '../../config/api';
// import { FaUser, FaSignOutAlt, FaBuilding, FaChevronDown, FaCheck } from 'react-icons/fa';
// import { RootState } from '../../store/store';
// import { UserState } from '../../store/slices/userSlice';
interface AccountNavProps { interface AccountNavProps {
accountName?: string | null; accountName?: string | null;
transactionName?: string | null; transactionName?: string | null;
} }
// Define the shape of state object
interface Account { interface Account {
id: number; id: number;
isDefault: boolean; isDefault: boolean;
@ -23,32 +15,45 @@ interface Account {
} }
interface UserData { interface UserData {
id: string; id: number;
firstName: string; name: string;
lastName: string;
email: string; email: string;
language: string; language: string;
account: Account; account: Account;
} }
interface AccountDataArray { interface AccountDataArray {
accountId: number, accountName: string, role: string, status: boolean userId: number,
userEmail: string,
name: string,
accountId: number;
accountName: string;
role: string;
status: string;
} }
// Helper function to dispatch custom storage event
const dispatchSessionStorageChange = (key: string, newValue: any) => {
window.dispatchEvent(new CustomEvent('sessionStorageChange', {
detail: { key, newValue }
}));
};
const AccountNav: React.FC<AccountNavProps> = ({ accountName = null, transactionName = null }) => { const AccountNav: React.FC<AccountNavProps> = ({ accountName = null, transactionName = null }) => {
// const user: UserState = useSelector((state: RootState) => state.user); const activeAccountId = JSON.parse(sessionStorage.getItem('activeAccountId') || 'null');
const userDetails = JSON.parse(sessionStorage.getItem('userDetails') || '{}');
console.log("activeAccountId", activeAccountId);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [accountsOpen, setAccountsOpen] = useState(false); const [accountsOpen, setAccountsOpen] = useState(false);
const [loadingAccounts, setLoadingAccounts] = useState(false); const [loadingAccounts, setLoadingAccounts] = useState(false);
const [accounts, setAccounts] = useState<AccountDataArray[]>([]); const [accounts, setAccounts] = useState<AccountDataArray[]>([]);
const [hasModalBeenClosed, setHasModalBeenClosed] = useState(false); // Track if modal was closed const [hasModalBeenClosed, setHasModalBeenClosed] = useState(false);
const dropdownRef = useRef(null); const dropdownRef = useRef<HTMLDivElement>(null);
const [user, setUser] = useState<UserData>({ const [user, setUser] = useState<UserData>({
id: "", id: 0,
firstName: "", name: "",
lastName: "",
email: "", email: "",
language: "", language: "",
account: { account: {
@ -58,13 +63,17 @@ const AccountNav: React.FC<AccountNavProps> = ({ accountName = null, transaction
}, },
}); });
console.log("user", user)
const getAccountDetails = async () => { const getAccountDetails = async () => {
try { try {
let res = await api.get('/api/user/accounts') let res = await api.get('/api/user/accounts');
let items = res?.data let items = res?.data;
console.log('items', items) console.log('items', items);
// Extract only the fields you want
const cleanedData: AccountDataArray[] = items.map((item: any) => ({ const cleanedData: AccountDataArray[] = items.map((item: any) => ({
userId: item.userId,
userEmail: item.userEmail,
name: item.name,
accountId: item.accountId, accountId: item.accountId,
accountName: item.accountName, accountName: item.accountName,
role: item.role, role: item.role,
@ -73,10 +82,9 @@ const AccountNav: React.FC<AccountNavProps> = ({ accountName = null, transaction
setAccounts(cleanedData); setAccounts(cleanedData);
} catch (error) { } catch (error) {
console.log(error) console.log(error);
} }
} };
const handleAccountsClick = async () => { const handleAccountsClick = async () => {
setAccountsOpen(!accountsOpen); setAccountsOpen(!accountsOpen);
@ -84,78 +92,127 @@ const AccountNav: React.FC<AccountNavProps> = ({ accountName = null, transaction
if (!accountsOpen) { if (!accountsOpen) {
setLoadingAccounts(true); setLoadingAccounts(true);
// Fetch API if:
// 1. No accounts data exists (first time), OR
// 2. Modal was previously closed (need fresh data)
if (accounts.length === 0 || hasModalBeenClosed) { if (accounts.length === 0 || hasModalBeenClosed) {
await getAccountDetails(); await getAccountDetails();
setHasModalBeenClosed(false); // Reset the flag after fetching setHasModalBeenClosed(false);
} }
setLoadingAccounts(false); setLoadingAccounts(false);
} }
}; };
const handleAccountSwitch = (account) => { const handleAccountSwitch = (account: any) => {
setUser(prev => ({ console.log("handleAccountSwitch", account);
...prev,
account: { name: account.name, id: account.id }
}));
// Update accounts active status // Update sessionStorage
setAccounts(prevAccounts => sessionStorage.setItem('activeAccountId', JSON.stringify(account.accountId));
prevAccounts.map(acc => ({
...acc, // Dispatch custom event
isActive: acc.id === account.id dispatchSessionStorageChange('activeAccountId', account.accountId);
}))
); // Update user state
setUser({
id: account.userId,
name: account.name,
email: account.userEmail,
language: "", // set it if available
account: {
id: account.accountId,
isDefault: false, // update as needed
name: account.accountName,
},
});
sessionStorage.setItem('userDetails', JSON.stringify({
id: account.userId,
name: account.name,
email: account.userEmail,
language: "", // set it if available
account: {
id: account.accountId,
isDefault: false, // update as needed
name: account.accountName,
},
}));
setAccountsOpen(false); setAccountsOpen(false);
setOpen(false); setOpen(false);
}; };
const navigate = useNavigate()
const navigate = useNavigate();
const getUserDetails = async () => { const getUserDetails = async () => {
try { try {
let res = await api.get(`/api/user/details`) let res = await api.get(`/api/user/details`);
console.log("getuser", res) console.log("getuser", res);
setUser(res?.data) const item = res?.data;
if (item) {
const userData = {
id: item?.id,
name : item?.firstName + " " + item?.lastName ,
email: item?.email,
language: "",
account: {
id: item?.account.id,
isDefault: false,
name: item?.account.name,
},
};
console.log("userData",userData)
setUser(userData);
sessionStorage.setItem('userDetails', JSON.stringify(userData));
sessionStorage.setItem('activeAccountId', JSON.stringify(userData.account.id));
// Dispatch event for initial load
dispatchSessionStorageChange('activeAccountId', userData.account.id);
console.log("Data is saved in sessionStorage");
}
} catch (error) { } catch (error) {
console.error("Error fetching user details:", error); console.error("Error fetching user details:", error);
} }
} };
useEffect(() => { useEffect(() => {
getUserDetails() if (!activeAccountId) {
}, []) getUserDetails();
} else {
setUser(userDetails);
}
}, []);
const location = useLocation(); const location = useLocation();
const pathnames = location.pathname const rawPathnames = location.pathname
.split("/") .split("/")
.filter((x) => x && isNaN(Number(x))); // remove numeric IDs .filter((x) => x && isNaN(Number(x)));
// Special case: if first segment is 's' and next is 'settings', remove 's'
const pathnames =
rawPathnames[0] === "s" && rawPathnames[1] === "settings"
? rawPathnames.slice(1)
: rawPathnames;
const labelMap: Record<string, string> = { const labelMap: Record<string, string> = {
accounts: "Accounts", accounts: "Accounts",
transactions: "Transactions", transactions: "Transactions",
templates: "Templates" templates: "Templates"
// Add more routes here if needed
}; };
// const [open, setOpen] = useState(false);
// const dropdownRef = useRef<HTMLDivElement>(null);
// Close dropdown when clicked outside
useEffect(() => { useEffect(() => {
function handleClickOutside(event: MouseEvent) { function handleClickOutside(event: MouseEvent) {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
if (open) { if (open) {
setHasModalBeenClosed(true); // Mark modal as closed when clicking outside setHasModalBeenClosed(true);
} }
setOpen(false); setOpen(false);
setAccountsOpen(false); // Also close accounts dropdown setAccountsOpen(false);
} }
} }
@ -165,24 +222,24 @@ const AccountNav: React.FC<AccountNavProps> = ({ accountName = null, transaction
const handleLogout = async () => { const handleLogout = async () => {
try { try {
let res = await api.post('/api/auth/logout') let res = await api.post('/api/auth/logout');
if (res.status === 200) { if (res.status === 200) {
sessionStorage.clear();
setOpen(false); setOpen(false);
navigate("/login") navigate("/login");
} }
} catch (error) { } catch (error) {
console.log(error) console.log(error);
} }
}; };
// Handle main dropdown toggle
const handleMainDropdownToggle = () => { const handleMainDropdownToggle = () => {
if (open) { if (open) {
setHasModalBeenClosed(true); // Mark as closed when manually closing setHasModalBeenClosed(true);
} }
setOpen(!open); setOpen(!open);
if (!open) { if (!open) {
setAccountsOpen(false); // Close accounts dropdown when opening main dropdown setAccountsOpen(false);
} }
}; };
@ -191,7 +248,6 @@ const AccountNav: React.FC<AccountNavProps> = ({ accountName = null, transaction
.replace(/[-_]/g, " ") .replace(/[-_]/g, " ")
.replace(/\b\w/g, (char) => char.toUpperCase()); .replace(/\b\w/g, (char) => char.toUpperCase());
const ShimmerRow = () => ( const ShimmerRow = () => (
<div className="animate-pulse px-4 py-3 border-b border-gray-100 last:border-b-0"> <div className="animate-pulse px-4 py-3 border-b border-gray-100 last:border-b-0">
<div className="flex items-center space-x-3"> <div className="flex items-center space-x-3">
@ -205,7 +261,6 @@ const AccountNav: React.FC<AccountNavProps> = ({ accountName = null, transaction
</div> </div>
); );
return ( return (
<header className="w-full px-6 py-2 flex justify-between items-center bg-white border-b rounded-sm border-gray-200"> <header className="w-full px-6 py-2 flex justify-between items-center bg-white border-b rounded-sm border-gray-200">
<nav className="text-md font-medium text-gray-800 capitalize flex items-center flex-wrap"> <nav className="text-md font-medium text-gray-800 capitalize flex items-center flex-wrap">
@ -237,46 +292,40 @@ const AccountNav: React.FC<AccountNavProps> = ({ accountName = null, transaction
</nav> </nav>
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
{/* User Dropdown */}
<div className="relative" ref={dropdownRef}> <div className="relative" ref={dropdownRef}>
{/* Avatar Button */}
<button <button
className="flex items-center space-x-2 p-1 cursor-pointer rounded-lg transition-colors" className="flex items-center space-x-2 p-1 cursor-pointer rounded-lg transition-colors"
onClick={handleMainDropdownToggle} onClick={handleMainDropdownToggle}
aria-expanded={open} aria-expanded={open}
aria-haspopup="true" aria-haspopup="true"
> >
<div className="w-8 h-8 rounded-full overflow-hidden bg-gradient-to-br from-green-500 to-blue-600 flex items-center justify-center text-white font-semibold text-sm shadow-md"> <div className="w-8 h-8 rounded-full overflow-hidden bg-gradient-to-br from-green-500 to-blue-600 flex items-center justify-center text-white font-semibold text-sm shadow-md">
{user ? ( {user ? (
<span <span className="w-full h-full object-cover p-1.5 font-bold">
className="w-full h-full object-cover p-1.5 font-bold" {(user?.name?.slice(0, 2)).toUpperCase()}
>{(user?.firstName + " " + user?.lastName).split(' ').map((item) => item.slice(0, 1)).join("").toUpperCase()}</span> </span>
) : ( ) : (
<FaUser className="text-lg" /> <FaUser className="text-lg" />
)} )}
</div> </div>
</button> </button>
{/* Enhanced Dropdown */}
{open && ( {open && (
<div className="absolute right-0 mt-2 w-72 top-8 rounded-xl shadow-xl bg-white border border-gray-200 z-50 overflow-hidden"> <div className="absolute right-0 mt-2 w-72 top-8 rounded-xl shadow-xl bg-white border border-gray-200 z-50 overflow-hidden">
{/* User Info Section */}
<div className="px-4 py-4 bg-gradient-to-r from-blue-50 to-purple-50 border-b border-gray-100"> <div className="px-4 py-4 bg-gradient-to-r from-blue-50 to-purple-50 border-b border-gray-100">
<div className="flex items-center space-x-3"> <div className="flex items-center space-x-3">
<div className="w-12 h-12 rounded-full overflow-hidden bg-gradient-to-br from-green-500 to-blue-600 flex items-center justify-center text-white font-semibold shadow-md"> <div className="w-12 h-12 rounded-full overflow-hidden bg-gradient-to-br from-green-500 to-blue-600 flex items-center justify-center text-white font-semibold shadow-md">
{(user) ? ( {user ? (
<span <span className="w-full h-full object-cover px-3 text-xl py-2.5 font-bold">
className="w-full h-full object-cover px-3 text-xl py-2.5 font-bold" {(user?.name?.slice(0, 2)).toUpperCase()}
> </span>
{(user?.firstName + " " + user?.lastName).split(' ').map((item) => item.slice(0, 1)).join("").toUpperCase()}</span>
) : ( ) : (
<FaUser className="text-lg" /> <FaUser className="text-lg" />
)} )}
</div> </div>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<div className="font-semibold text-gray-900 truncate">{user.firstName + ' ' + user.lastName || '-'}</div> <div className="font-semibold text-gray-900 truncate">{user?.name || '-'}</div>
<div className="text-sm text-gray-600 truncate">{user.email || '-'}</div> <div className="text-sm text-gray-600 truncate">{user?.email || '-'}</div>
<div className="text-xs text-gray-500 mt-1"> <div className="text-xs text-gray-500 mt-1">
Account #{user?.account?.name || '-'} Account #{user?.account?.name || '-'}
</div> </div>
@ -284,7 +333,6 @@ const AccountNav: React.FC<AccountNavProps> = ({ accountName = null, transaction
</div> </div>
</div> </div>
{/* Account List Section */}
<div className="border-b border-gray-100"> <div className="border-b border-gray-100">
<button <button
onClick={handleAccountsClick} onClick={handleAccountsClick}
@ -297,7 +345,6 @@ const AccountNav: React.FC<AccountNavProps> = ({ accountName = null, transaction
<FaChevronDown className={`text-gray-400 transition-transform ${accountsOpen ? 'rotate-180' : ''}`} /> <FaChevronDown className={`text-gray-400 transition-transform ${accountsOpen ? 'rotate-180' : ''}`} />
</button> </button>
{/* Accounts Dropdown */}
{accountsOpen && ( {accountsOpen && (
<div className="bg-gray-50 max-h-64 overflow-y-auto"> <div className="bg-gray-50 max-h-64 overflow-y-auto">
{loadingAccounts ? ( {loadingAccounts ? (
@ -307,42 +354,43 @@ const AccountNav: React.FC<AccountNavProps> = ({ accountName = null, transaction
</div> </div>
) : ( ) : (
<div className="divide-y divide-gray-200"> <div className="divide-y divide-gray-200">
{accounts.length > 0 ? (accounts?.map((account) => ( {accounts?.length > 0 ? (
<button accounts?.map((account) => (
key={account.accountId} <button
// onClick={() => handleAccountSwitch(account)} key={account.accountId}
className="w-full px-4 py-3 hover:bg-white transition-colors cursor-pointer text-left" onClick={() => handleAccountSwitch(account)}
> className={`w-full px-4 py-3 hover:bg-white transition-colors cursor-pointer text-left`}
<div className="flex items-center justify-between"> >
<div className="flex items-center space-x-3"> <div className={`flex items-center justify-between`}>
<div className="w-8 h-8 rounded-full bg-gradient-to-br from-gray-200 to-gray-400 flex items-center justify-center text-white font-semibold text-xs"> <div className="flex items-center space-x-3">
{account.accountName.slice(0, 2).toUpperCase()} <div className="w-8 h-8 rounded-full bg-gradient-to-br from-gray-200 to-gray-400 flex items-center justify-center text-white font-semibold text-xs">
</div> {/* {account.accountName.slice(0, 2).toUpperCase()} */}
<div className="flex-1 min-w-0">
<div className="flex items-center space-x-2">
<span className="font-medium text-gray-900 text-sm">{account.accountName}</span>
{account.status && (
<FaCheck className="text-green-500 text-xs" />
)}
</div> </div>
<div className="text-xs text-gray-600 truncate">{account.company}</div> <div className="flex-1 min-w-0">
<div className="flex items-center space-x-2">
<span className="font-medium text-gray-900 text-sm">{account.accountName}</span>
{account.accountId === activeAccountId && (
<FaCheck className="text-green-600 text-xs" />
)}
</div>
</div>
</div>
<div className="text-xs text-gray-500 bg-gray-200 px-2 py-1 rounded">
{account.role}
</div> </div>
</div> </div>
<div className="text-xs text-gray-500 bg-gray-200 px-2 py-1 rounded"> </button>
{account.role} ))
</div> ) : (
</div> <span className='text-gray-400 font-medium text-[12px] flex justify-center p-3'>No Account...</span>
</button> )}
))) : <span className='text-gray-400 font-medium text-[12px] flex justify-center p-3'>No Account...</span>}
</div> </div>
)} )}
</div> </div>
)} )}
</div> </div>
{/* Logout Section */} <div className="border-t border-gray-100">
<div className="border-t border-gray-100 ">
<button <button
onClick={handleLogout} onClick={handleLogout}
className="w-full flex items-center px-4 py-3 text-sm text-red-600 hover:bg-red-50 transition-colors cursor-pointer" className="w-full flex items-center px-4 py-3 text-sm text-red-600 hover:bg-red-50 transition-colors cursor-pointer"

View File

@ -42,6 +42,7 @@ const SideBar: React.FC<SideBarProps> = ({ showSideBar, setShowSideBar }) => {
headers: { "ngrok-skip-browser-warning": "69420" } headers: { "ngrok-skip-browser-warning": "69420" }
} }
); );
sessionStorage.clear();
// Redirect to login or refresh the page after logout // Redirect to login or refresh the page after logout
window.location.href = '/login'; window.location.href = '/login';
} catch (err) { } catch (err) {

View File

@ -61,8 +61,8 @@ const Home = () => {
trend: 'up' trend: 'up'
}, },
{ {
title: 'Waiting for Others', title: 'Draft',
count: data.waitingForOthers || 0, count: data.draft || 0,
icon: <FaClock size={18} className="text-stone-600" />, icon: <FaClock size={18} className="text-stone-600" />,
gradient: 'bg-gradient-to-br from-blue-50 to-blue-100', gradient: 'bg-gradient-to-br from-blue-50 to-blue-100',
shadowColor: 'shadow-blue-200/50', shadowColor: 'shadow-blue-200/50',
@ -70,69 +70,27 @@ const Home = () => {
textColor: 'text-blue-700', textColor: 'text-blue-700',
trend: 'down' trend: 'down'
}, },
// {
// title: 'declined',
// count: data.declined || 0,
// icon: <FaClock size={18} className="text-purple-600" />,
// gradient: 'bg-gradient-to-br from-purple-50 to-purple-100',
// shadowColor: 'shadow-purple-200/50',
// iconBg: 'bg-purple-100 border-purple-200',
// textColor: 'text-purple-700',
// trend: 'down'
// },
// {
// title: 'cancelled',
// count: data.cancelled || 0,
// icon: <FaClock size={18} className="text-green-600" />,
// gradient: 'bg-gradient-to-br from-green-50 to-green-100',
// shadowColor: 'shadow-green-200/50',
// iconBg: 'bg-green-100 border-green-200',
// textColor: 'text-green-700',
// trend: 'down'
// },
// {
// title: 'draft',
// count: data.draft || 0,
// icon: <FaClock size={18} className="text-stone-600" />,
// gradient: 'bg-gradient-to-br from-stone-50 to-stone-100',
// shadowColor: 'shadow-stone-200/50',
// iconBg: 'bg-stone-100 border-stone-200',
// textColor: 'text-stone-700',
// trend: 'down'
// }
// Add more cards here if needed
]; ];
}; };
const [activeAccountId, setActiveAccountId] = useState<string | null>(
JSON.parse(sessionStorage.getItem('activeAccountId') || 'null')
);
const [dashboardData, setDashboardData] = useState<any>(null); const [dashboardData, setDashboardData] = useState<any>(null);
const [fromDate, setFromDate] = useState<string>(''); // ISO string const [fromDate, setFromDate] = useState<string>('');
const [toDate, setToDate] = useState<string>(''); // ISO string const [toDate, setToDate] = useState<string>('');
const [cards, setCards] = useState<CardData[]>([]); const [cards, setCards] = useState<CardData[]>([]);
const [accountID, setAccountID] = useState<number>()
const [isLoading, setIsLoading] = useState<boolean>(false); const [isLoading, setIsLoading] = useState<boolean>(false);
console.log("cards", cards) console.log("activeAccountId", activeAccountId);
console.log("cards", cards);
const getUserDetails = async () => { const getDashboardData = async () => {
try { if (!activeAccountId) return;
let res = await api.get('/api/user/details')
let accountIDData = res?.data?.account?.id
setAccountID(accountIDData)
} catch (error) {
console.log(error)
}
}
useEffect(() => { setIsLoading(true);
getUserDetails()
}, [])
const getDashboardData = async (from: string, to: string) => {
setIsLoading(true)
const payload = { const payload = {
fromDate: from, // already ISO string account: activeAccountId
toDate: to,
account : accountID
}; };
try { try {
@ -143,8 +101,8 @@ const Home = () => {
setCards(cardDataArray); setCards(cardDataArray);
} catch (error) { } catch (error) {
console.error("Error fetching dashboard data:", error); console.error("Error fetching dashboard data:", error);
}finally{ } finally {
setIsLoading(false) setIsLoading(false);
} }
}; };
@ -155,16 +113,41 @@ const Home = () => {
setToDate(isoTo); setToDate(isoTo);
}, []); }, []);
// Listen for sessionStorage changes
useEffect(() => { useEffect(() => {
if (fromDate && toDate && accountID) { const handleStorageChange = (e: StorageEvent) => {
getDashboardData(fromDate, toDate); if (e.key === 'activeAccountId') {
const newActiveAccountId = e.newValue ? JSON.parse(e.newValue) : null;
setActiveAccountId(newActiveAccountId);
}
};
// Listen for storage events (works for changes from other tabs)
window.addEventListener('storage', handleStorageChange);
// Custom event listener for same-tab changes
const handleCustomStorageChange = (e: CustomEvent) => {
if (e.detail.key === 'activeAccountId') {
setActiveAccountId(e.detail.newValue);
}
};
window.addEventListener('sessionStorageChange', handleCustomStorageChange as EventListener);
return () => {
window.removeEventListener('storage', handleStorageChange);
window.removeEventListener('sessionStorageChange', handleCustomStorageChange as EventListener);
};
}, []);
// Re-fetch dashboard data when activeAccountId changes
useEffect(() => {
if (activeAccountId) {
getDashboardData();
} }
}, [fromDate, toDate , accountID]); }, [activeAccountId]);
// Set default date range on mount (last 7 days)
// Set default range on mount (last 7 days)
useEffect(() => { useEffect(() => {
const now = new Date(); const now = new Date();
const from = new Date(); const from = new Date();

View File

@ -277,10 +277,10 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
tagsData = groupByRecipientId(tagsData); tagsData = groupByRecipientId(tagsData);
sendTagsToRecipients(tagsData, accountId, transactionId); sendTagsToRecipients(tagsData, accountId, transactionId);
// (async () => { (async () => {
// const res = await api.put(`/api/accounts/${accountId}/transactions/${transactionId}`, {status: "SENT"}) const res = await api.put(`/api/accounts/${accountId}/transactions/${transactionId}`, {status: "SENT"})
// console.log(res, "Check123") console.log(res, "Check123")
// })() })()
}, [isSend]) }, [isSend])
// Save Tags - END // Save Tags - END

View File

@ -43,7 +43,9 @@ interface AccountOption {
const Setting = () => { const Setting = () => {
const { page1 } = useParams<{ page1: string }>(); const { page1 } = useParams<{ page1: string }>();
console.log("page1" , page1)
const location = useLocation(); const location = useLocation();
console.log("location",location)
const navigate = useNavigate(); const navigate = useNavigate();
// Refs for subsections within each main tab // Refs for subsections within each main tab
@ -337,8 +339,8 @@ const Setting = () => {
return ( return (
<> <>
<SettingNav /> {/* <SettingNav /> */}
{/* <AccountNav/> */} <AccountNav/>
<div className="bg-[#f9fafa] h-[calc(90vh-20px)] flex flex-col mt-2"> <div className="bg-[#f9fafa] h-[calc(90vh-20px)] flex flex-col mt-2">
{/* Main Navigation Tabs */} {/* Main Navigation Tabs */}
<div className="sticky top-0 z-10 bg-white border-b border-gray-200 px-8 pt-5"> <div className="sticky top-0 z-10 bg-white border-b border-gray-200 px-8 pt-5">