feat: complete security overhaul with JWT backend and authenticated frontend API
This commit is contained in:
@@ -75,8 +75,9 @@ const Bills: React.FC = () => {
|
||||
};
|
||||
|
||||
const filteredOrders = orders.filter(order => {
|
||||
const matchesSearch = order.purchaseId.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
order.referenceId?.toLowerCase().includes(searchTerm.toLowerCase());
|
||||
const search = (searchTerm || '').toLowerCase();
|
||||
const matchesSearch = (order.purchaseId || '').toLowerCase().includes(search) ||
|
||||
(order.referenceId || '').toLowerCase().includes(search);
|
||||
const matchesStatus = statusFilter === 'All' || order.status === statusFilter;
|
||||
return matchesSearch && matchesStatus;
|
||||
});
|
||||
|
||||
@@ -44,13 +44,13 @@ const Login = () => {
|
||||
const user = await response.json();
|
||||
|
||||
// Strict Role Validation
|
||||
if (user.role.toLowerCase() !== role) {
|
||||
alert(`Access Denied: You are trying to login as ${role.toUpperCase()}, but your credentials belong to a ${user.role.toUpperCase()} account.`);
|
||||
if ((user.role || '').toLowerCase() !== (role || '').toLowerCase()) {
|
||||
alert(`Access Denied: You are trying to login as ${(role || '').toUpperCase()}, but your credentials belong to a ${(user.role || '').toUpperCase()} account.`);
|
||||
return;
|
||||
}
|
||||
|
||||
sessionStorage.setItem('isLoggedIn', 'true');
|
||||
sessionStorage.setItem('userRole', user.role.toLowerCase());
|
||||
sessionStorage.setItem('userRole', (user.role || '').toLowerCase());
|
||||
sessionStorage.setItem('userPermissions', JSON.stringify(user.permissions || []));
|
||||
|
||||
// Persist user profile + JWT token for authenticated API calls
|
||||
|
||||
@@ -194,7 +194,11 @@ const Managers = () => {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-[#e2e8f0]">
|
||||
{managers.filter(m => m.name.toLowerCase().includes(searchQuery.toLowerCase()) || m.email.toLowerCase().includes(searchQuery.toLowerCase())).map((manager) => (
|
||||
{managers.filter(m => {
|
||||
const query = (searchQuery || '').toLowerCase();
|
||||
return (m.name || '').toLowerCase().includes(query) ||
|
||||
(m.email || '').toLowerCase().includes(query);
|
||||
}).map((manager) => (
|
||||
<tr key={manager.id} className="hover:bg-gray-50/50 transition-colors">
|
||||
<td className="px-6 py-5">
|
||||
<div className="flex items-center gap-3">
|
||||
|
||||
@@ -162,7 +162,7 @@ const PurchaseAnalytics = () => {
|
||||
};
|
||||
|
||||
const filteredAnalytics = analytics.filter(item => {
|
||||
const matchesSearch = item.product.toLowerCase().includes(searchTerm.toLowerCase());
|
||||
const matchesSearch = (item.product || '').toLowerCase().includes((searchTerm || '').toLowerCase());
|
||||
const matchesFilter = filterType === 'all' || item.trend === filterType;
|
||||
return matchesSearch && matchesFilter;
|
||||
});
|
||||
|
||||
@@ -298,7 +298,7 @@ const Purchases: React.FC = () => {
|
||||
<Loader2 className="animate-spin inline-block mr-2" /> Loading records...
|
||||
</td>
|
||||
</tr>
|
||||
) : orders.filter(o => o.purchaseId.toLowerCase().includes(searchTerm.toLowerCase())).map((order) => (
|
||||
) : orders.filter(o => (o.purchaseId || '').toLowerCase().includes((searchTerm || '').toLowerCase())).map((order) => (
|
||||
<tr key={order.id} className="hover:bg-gray-50/50 transition-all font-medium">
|
||||
<td className="px-6 py-4 text-sm font-bold text-[#231651]">{order.purchaseId}</td>
|
||||
<td className="px-6 py-4 text-sm text-[#64748b]">{new Date(order.date).toLocaleDateString()}</td>
|
||||
|
||||
@@ -110,10 +110,11 @@ const Staff = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const filteredStaff = staffList.filter(s =>
|
||||
s.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
s.email.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
const filteredStaff = staff.filter(s => {
|
||||
const query = (searchQuery || '').toLowerCase();
|
||||
return (s.name || '').toLowerCase().includes(query) ||
|
||||
(s.email || '').toLowerCase().includes(query);
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="p-8 space-y-8 bg-[#f8fafc] min-h-screen font-inter">
|
||||
|
||||
@@ -61,11 +61,11 @@ const Terminals = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const filteredTerminals = terminals.filter(t =>
|
||||
t.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
t.location.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
const filteredTerminals = terminals.filter(t => {
|
||||
const query = (searchQuery || '').toLowerCase();
|
||||
return (t.name || '').toLowerCase().includes(query) ||
|
||||
(t.location || '').toLowerCase().includes(query);
|
||||
});
|
||||
return (
|
||||
<div className="p-8 max-w-7xl mx-auto space-y-8 font-inter">
|
||||
{/* Header Section */}
|
||||
|
||||
@@ -135,10 +135,13 @@ const Vendors: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const filteredVendors = vendors.filter(v =>
|
||||
v.name?.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
v.companyName?.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
);
|
||||
const filteredVendors = vendors.filter(v => {
|
||||
if (!v) return false;
|
||||
const search = (searchTerm || '').toLowerCase();
|
||||
const name = (v.name || '').toLowerCase();
|
||||
const company = (v.companyName || '').toLowerCase();
|
||||
return name.includes(search) || company.includes(search);
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user